import 'package:flutter/material.dart'; import '../core/app_controller.dart'; import '../core/build_info.dart'; import '../l10n/strings.dart'; import 'adaptive.dart'; import 'change_password.dart'; import 'common.dart'; import 'gates.dart'; import 'profile_io.dart'; class SettingsPage extends StatefulWidget { final AppController controller; const SettingsPage(this.controller, {super.key}); @override State createState() => _SettingsPageState(); } class _SettingsPageState extends State { bool busy = false; Future action(Future Function() task) async { setState(() => busy = true); try { await task(); } catch (e) { if (mounted) showFailure(context, e); } finally { if (mounted) setState(() => busy = false); } } @override Widget build(BuildContext context) { final c = widget.controller; return LayoutBuilder( builder: (context, constraints) => ListView( padding: readablePadding(constraints), children: [ Text( 'CH-J · SM Mobile $appVersion', style: Theme.of(context).textTheme.titleLarge, ), Text(buildId), const SizedBox(height: 12), Text(context.tr('localOnly')), const SizedBox(height: 24), languagePicker(context, c), const SizedBox(height: 16), DropdownButtonFormField( initialValue: c.theme, isExpanded: true, decoration: InputDecoration(labelText: context.tr('theme')), items: ThemeMode.values .map( (t) => DropdownMenuItem( value: t, child: Text(context.tr(t.name)), ), ) .toList(), onChanged: (t) => action(() async { c.theme = t!; await c.saveSettings(); }), ), const SizedBox(height: 24), Text( context.tr('securitySection'), style: Theme.of(context).textTheme.titleMedium, ), ListTile( contentPadding: EdgeInsets.zero, leading: const Icon(Icons.password), title: Text(context.tr('changePassword')), subtitle: Text( '${context.tr('kdfInfo')}: ' '${c.vault.kdfName == 'argon2id' ? 'Argon2id' : 'PBKDF2-SHA256'}' ' · AES-256-GCM', ), trailing: const Icon(Icons.chevron_right), onTap: busy ? null : () async { await Navigator.push( context, MaterialPageRoute(builder: (_) => ChangePasswordPage(c)), ); if (mounted) setState(() {}); }, ), SwitchListTile.adaptive( contentPadding: EdgeInsets.zero, title: Text(context.tr('biometric')), subtitle: Text(context.tr('biometricNote')), value: c.biometric, onChanged: busy ? null : (v) => action( () => c.setBiometric(v, context.tr('biometricReason')), ), ), SwitchListTile.adaptive( contentPadding: EdgeInsets.zero, title: Text(context.tr('lockBackground')), value: c.lockBackground, onChanged: (v) => action(() async { c.lockBackground = v; await c.saveSettings(); }), ), const SizedBox(height: 16), DropdownButtonFormField( isExpanded: true, initialValue: c.idleMinutes, decoration: InputDecoration(labelText: context.tr('idleTimeout')), items: idleChoices .map((i) => DropdownMenuItem(value: i, child: Text('$i'))) .toList(), onChanged: (i) => action(() async { c.idleMinutes = i!; await c.saveSettings(); }), ), const SizedBox(height: 16), DropdownButtonFormField( isExpanded: true, initialValue: c.monitorSeconds, decoration: InputDecoration( labelText: context.tr('monitorInterval'), ), items: [5, 10, 30, 60] .map((i) => DropdownMenuItem(value: i, child: Text('$i'))) .toList(), onChanged: (i) => action(() async { c.monitorSeconds = i!; await c.saveSettings(); }), ), const SizedBox(height: 24), OutlinedButton.icon( onPressed: busy ? null : () => action(() => importProfiles(context, c)), icon: const Icon(Icons.file_open), label: Text(context.tr('importProfiles')), ), OutlinedButton.icon( onPressed: busy ? null : () => action(() => exportProfiles(c)), icon: const Icon(Icons.ios_share), label: Text(context.tr('exportProfiles')), ), const SizedBox(height: 16), ListTile( title: Text(context.tr('license')), leading: const Icon(Icons.description_outlined), onTap: () => Navigator.push( context, MaterialPageRoute( builder: (ctx) => Scaffold( appBar: AppBar(title: Text(ctx.tr('license'))), body: SingleChildScrollView( padding: const EdgeInsets.all(20), child: SelectableText(c.legal.license), ), ), ), ), ), ListTile( title: Text(context.tr('guidance')), leading: const Icon(Icons.shield_outlined), onTap: () => Navigator.push( context, MaterialPageRoute( builder: (ctx) => Scaffold( appBar: AppBar(title: Text(ctx.tr('guidance'))), body: SingleChildScrollView( padding: const EdgeInsets.all(20), child: SelectableText( c.legal.guidance[Localizations.localeOf( ctx, ).languageCode] ?? c.legal.guidance['en']!, ), ), ), ), ), ), ListTile( title: Text(context.tr('componentLicenses')), leading: const Icon(Icons.inventory_2_outlined), onTap: () => showLicensePage( context: context, applicationName: 'SM Mobile', applicationVersion: appVersion, ), ), const SizedBox(height: 16), FilledButton.icon( onPressed: c.lock, icon: const Icon(Icons.lock), label: Text(context.tr('lock')), ), if (busy) const LinearProgressIndicator(), ], ), ); } }