import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; class ConfigViewer extends StatefulWidget { const ConfigViewer({super.key}); @override State createState() => _ConfigViewerState(); } class _ConfigViewerState extends State { String _searchQuery = ''; Future _changeSetting( AppSettings appSetting, SharedPreferences store, String initialValue, ) async { if (appSetting is AppSettings) { await appSetting.setItem(!(initialValue == 'true')); setState(() {}); return; } final value = await showTextInputDialog( context: context, title: appSetting.name, hintText: appSetting.defaultValue.toString(), initialText: initialValue, ); if (value == null) return; if (appSetting is AppSettings) { await appSetting.setItem(value); } if (appSetting is AppSettings) { await appSetting.setItem(int.parse(value)); } if (appSetting is AppSettings) { await appSetting.setItem(double.parse(value)); } setState(() {}); } Future _reset() async { await AppSettings.reset(); setState(() {}); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final normalizedQuery = _searchQuery.trim().toLowerCase(); final filteredSettings = AppSettings.values .where((setting) { if (normalizedQuery.isEmpty) return true; return setting.name.toLowerCase().contains(normalizedQuery); }) .toList(growable: false); return Scaffold( appBar: AppBar( title: Text(L10n.of(context).advancedConfigurations), leading: BackButton(onPressed: () => context.go('/')), actions: [ TextButton(onPressed: _reset, child: Text(L10n.of(context).reset)), ], ), body: Column( crossAxisAlignment: .stretch, children: [ Container( margin: const EdgeInsets.all(16), padding: const EdgeInsets.all(16), color: theme.colorScheme.errorContainer, child: Text( 'Changing configs by hand is untested! Use without any warranty!', style: TextStyle(color: theme.colorScheme.onErrorContainer), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: TextField( onChanged: (value) => setState(() => _searchQuery = value), decoration: InputDecoration( hintText: 'Search config key', prefixIcon: const Icon(Icons.search), border: const OutlineInputBorder(), isDense: true, filled: true, fillColor: theme.colorScheme.surfaceContainerHighest.withAlpha( 128, ), ), ), ), const SizedBox(height: 8), Expanded( child: ListView.builder( itemCount: filteredSettings.length, itemBuilder: (context, i) { final store = Matrix.of(context).store; final appSetting = filteredSettings[i]; var value = ''; if (appSetting is AppSettings) { value = appSetting.value; } if (appSetting is AppSettings) { value = appSetting.value.toString(); } if (appSetting is AppSettings) { return SwitchListTile.adaptive( title: Text(appSetting.name), subtitle: Text(value), value: appSetting.value, onChanged: (value) => _changeSetting(appSetting, store, (!value).toString()), ); } if (appSetting is AppSettings) { value = appSetting.value.toString(); } return ListTile( title: Text(appSetting.name), subtitle: Text(value), onTap: () => _changeSetting(appSetting, store, value), ); }, ), ), ], ), ); } }