vitallens_flutter 0.1.0
vitallens_flutter: ^0.1.0 copied to clipboard
Flutter plugin for Rouast VitalLens contactless facial physiological vital signs estimation (Heart Rate, HRV, Respiration, rPPG waveforms).
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:vitallens_flutter/vitallens_flutter.dart';
void main() {
runApp(const VitalLensExampleApp());
}
class VitalLensExampleApp extends StatelessWidget {
const VitalLensExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'VitalLens Flutter Example',
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: const Color(0xFF0F141C),
colorScheme: const ColorScheme.dark(
primary: Color(0xFF00E5FF),
secondary: Color(0xFF00E676),
),
),
home: const ExampleHomeScreen(),
);
}
}
class ExampleHomeScreen extends StatefulWidget {
const ExampleHomeScreen({super.key});
@override
State<ExampleHomeScreen> createState() => _ExampleHomeScreenState();
}
class _ExampleHomeScreenState extends State<ExampleHomeScreen> {
final TextEditingController _keyController = TextEditingController(
text: const String.fromEnvironment('ROUAST_API_KEY'),
);
VitalLensResult? _lastResult;
bool _isScanning = false;
@override
void dispose() {
_keyController.dispose();
super.dispose();
}
Future<void> _launchScan() async {
final key = _keyController.text.trim();
if (key.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please enter your Rouast VitalLens API Key'),
backgroundColor: Colors.amber,
),
);
return;
}
setState(() => _isScanning = true);
final result = await VitalLens.startScan(
apiKey: key,
mode: VitalLensMode.eco,
);
setState(() {
_isScanning = false;
_lastResult = result;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('VitalLens Flutter Example'),
backgroundColor: const Color(0xFF131A26),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
controller: _keyController,
obscureText: true,
decoration: InputDecoration(
labelText: 'VitalLens API Key',
hintText: 'Enter API Key from rouast.com',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
prefixIcon: const Icon(Icons.key_rounded),
),
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _isScanning ? null : _launchScan,
icon: _isScanning
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.videocam_rounded),
label: Text(_isScanning ? 'Scanning...' : 'Start 30s Face Scan'),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF00E5FF),
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
),
const SizedBox(height: 24),
if (_lastResult != null) ...[
Card(
color: const Color(0xFF1B2838),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_lastResult!.isCompleted
? 'Estimation Results'
: 'Scan Status: ${_lastResult!.message}',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Color(0xFF00E5FF),
),
),
const SizedBox(height: 12),
if (_lastResult!.isCompleted) ...[
Text(
'Heart Rate: ${_lastResult!.heartRate?.toStringAsFixed(1) ?? '--'} BPM',
style: const TextStyle(fontSize: 18),
),
Text(
'HRV (SDNN): ${_lastResult!.hrvSdnn?.toStringAsFixed(1) ?? '--'} ms',
style: const TextStyle(fontSize: 18),
),
Text(
'Respiration: ${_lastResult!.respiratoryRate?.toStringAsFixed(1) ?? '--'} BrPM',
style: const TextStyle(fontSize: 18),
),
if (_lastResult!.ppgData.isNotEmpty) ...[
const SizedBox(height: 16),
const Text(
'rPPG Pulse Waveform',
style: TextStyle(fontSize: 14, color: Colors.white70),
),
const SizedBox(height: 8),
SizedBox(
height: 100,
child: PpgWaveformView(
dataPoints: _lastResult!.ppgData,
strokeColor: const Color(0xFF00E5FF),
),
),
],
],
],
),
),
),
],
],
),
),
);
}
}