import 'package:flutter/material.dart'; import '../../core/theme.dart'; import '../../services/biometric_service.dart'; /// Settings screen with biometric authentication configuration class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { final BiometricService _biometricService = BiometricService(); bool _biometricsEnabled = false; bool _biometricsAvailable = false; LockPolicy _lockPolicy = LockPolicy.afterInactive; String _biometricTypeName = 'Biometrics'; bool _isLoading = true; @override void initState() { super.initState(); _loadSettings(); } Future _loadSettings() async { final available = await _biometricService.isBiometricsAvailable(); final enabled = await _biometricService.isBiometricEnabled(); final policy = await _biometricService.getLockPolicy(); final typeName = await _biometricService.getBiometricTypeName(); if (mounted) { setState(() { _biometricsAvailable = available; _biometricsEnabled = enabled; _lockPolicy = policy; _biometricTypeName = typeName; _isLoading = false; }); } } Future _toggleBiometrics(bool value) async { if (value) { // Verify biometrics work before enabling final result = await _biometricService.authenticate( reason: 'Verify biometrics to enable', ); if (result != BiometricResult.success) { if (mounted) { _showError(_biometricService.getErrorMessage(result)); } return; } } await _biometricService.setBiometricEnabled(value); if (mounted) { setState(() { _biometricsEnabled = value; }); } } Future _changeLockPolicy(LockPolicy? policy) async { if (policy == null) return; await _biometricService.setLockPolicy(policy); if (mounted) { setState(() { _lockPolicy = policy; }); } } void _showError(String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: Colors.red.shade700, behavior: SnackBarBehavior.floating, ), ); } String _policyDisplayName(LockPolicy policy) { switch (policy) { case LockPolicy.always: return 'Always'; case LockPolicy.afterInactive: return 'After 5 minutes inactive'; case LockPolicy.never: return 'Never'; } } String _policyDescription(LockPolicy policy) { switch (policy) { case LockPolicy.always: return 'Require authentication every time you open the app'; case LockPolicy.afterInactive: return 'Require authentication after 5 minutes of inactivity'; case LockPolicy.never: return 'Never require authentication (not recommended)'; } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Settings'), centerTitle: true, ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : ListView( children: [ _buildSection( title: 'Security', children: [ // Biometric toggle SwitchListTile( title: Text('$_biometricTypeName Authentication'), subtitle: Text( _biometricsAvailable ? 'Use $_biometricTypeName to unlock the app' : 'Not available on this device', ), value: _biometricsEnabled && _biometricsAvailable, onChanged: _biometricsAvailable ? _toggleBiometrics : null, activeColor: AppTheme.primaryColor, secondary: Icon( _biometricsAvailable ? Icons.fingerprint : Icons.no_encryption, color: _biometricsAvailable ? AppTheme.primaryColor : Colors.grey, ), ), // Lock policy (only shown if biometrics enabled) if (_biometricsEnabled && _biometricsAvailable) ...[ const Divider(height: 1), ListTile( leading: const Icon(Icons.lock_clock), title: const Text('Lock Timing'), subtitle: Text(_policyDisplayName(_lockPolicy)), trailing: const Icon(Icons.chevron_right), onTap: () => _showLockPolicyDialog(), ), ], // Biometrics not enrolled warning if (!_biometricsAvailable) ...[ const Divider(height: 1), ListTile( leading: Icon( Icons.warning_amber, color: Colors.orange.shade400, ), title: const Text('Set Up Biometrics'), subtitle: const Text( 'Enable Face ID, Touch ID, or fingerprint in your device settings', ), onTap: () { _showBiometricsSetupInfo(); }, ), ], ], ), _buildSection( title: 'Input', children: [ ListTile( leading: const Icon(Icons.camera_alt), title: const Text('Camera Permissions'), trailing: const Icon(Icons.chevron_right), onTap: () { // TODO: Open camera permissions }, ), ListTile( leading: const Icon(Icons.mic), title: const Text('Microphone Permissions'), trailing: const Icon(Icons.chevron_right), onTap: () { // TODO: Open microphone permissions }, ), ], ), _buildSection( title: 'About', children: [ const ListTile( leading: Icon(Icons.info_outline), title: Text('Version'), trailing: Text('1.0.0'), ), ListTile( leading: const Icon(Icons.code), title: const Text('Open Source Licenses'), trailing: const Icon(Icons.chevron_right), onTap: () { showLicensePage(context: context); }, ), ], ), ], ), ); } void _showLockPolicyDialog() { showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: AppTheme.surfaceColor, title: const Text('Lock Timing'), content: Column( mainAxisSize: MainAxisSize.min, children: LockPolicy.values.map((policy) { return RadioListTile( title: Text(_policyDisplayName(policy)), subtitle: Text( _policyDescription(policy), style: TextStyle( fontSize: 12, color: AppTheme.textColor.withOpacity(0.7), ), ), value: policy, groupValue: _lockPolicy, activeColor: AppTheme.primaryColor, onChanged: (value) { _changeLockPolicy(value); Navigator.of(context).pop(); }, ); }).toList(), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), ], ), ); } void _showBiometricsSetupInfo() { showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: AppTheme.surfaceColor, title: const Text('Set Up Biometrics'), content: const Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('To use biometric authentication:'), SizedBox(height: 16), Text('iOS:'), Text('Settings → Face ID & Passcode (or Touch ID)'), SizedBox(height: 12), Text('Android:'), Text('Settings → Security → Fingerprint / Face unlock'), SizedBox(height: 16), Text( 'After setting up biometrics on your device, return to this app to enable authentication.', style: TextStyle(fontSize: 12), ), ], ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Got it'), ), ], ), ); } Widget _buildSection({ required String title, required List children, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), child: Text( title, style: TextStyle( color: AppTheme.primaryColor, fontWeight: FontWeight.bold, fontSize: 14, ), ), ), ...children, const Divider(), ], ); } }