fluffychat/lib/widgets/config_viewer.dart
2026-03-13 09:16:54 +01:00

143 lines
4.6 KiB
Dart

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<ConfigViewer> createState() => _ConfigViewerState();
}
class _ConfigViewerState extends State<ConfigViewer> {
String _searchQuery = '';
Future<void> _changeSetting(
AppSettings appSetting,
SharedPreferences store,
String initialValue,
) async {
if (appSetting is AppSettings<bool>) {
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<String>) {
await appSetting.setItem(value);
}
if (appSetting is AppSettings<int>) {
await appSetting.setItem(int.parse(value));
}
if (appSetting is AppSettings<double>) {
await appSetting.setItem(double.parse(value));
}
setState(() {});
}
Future<void> _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<String>) {
value = appSetting.value;
}
if (appSetting is AppSettings<int>) {
value = appSetting.value.toString();
}
if (appSetting is AppSettings<bool>) {
return SwitchListTile.adaptive(
title: Text(appSetting.name),
subtitle: Text(value),
value: appSetting.value,
onChanged: (value) =>
_changeSetting(appSetting, store, (!value).toString()),
);
}
if (appSetting is AppSettings<double>) {
value = appSetting.value.toString();
}
return ListTile(
title: Text(appSetting.name),
subtitle: Text(value),
onTap: () => _changeSetting(appSetting, store, value),
);
},
),
),
],
),
);
}
}