refactor: Use AppSettings enum based configuration everywhere and fix load from json on web

This commit is contained in:
Christian Kußowski 2025-10-19 19:36:47 +02:00
commit 4c357f6249
No known key found for this signature in database
GPG key ID: E067ECD60F1A0652
46 changed files with 357 additions and 402 deletions

View file

@ -4,7 +4,6 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:matrix/matrix.dart';
import 'package:provider/provider.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/widgets/lock_screen.dart';
class AppLockWidget extends StatefulWidget {
@ -65,7 +64,7 @@ class AppLock extends State<AppLockWidget> with WidgetsBindingObserver {
Future<void> changePincode(String? pincode) async {
await const FlutterSecureStorage().write(
key: SettingKeys.appLockKey,
key: 'chat.fluffy.app_lock',
value: pincode,
);
_pincode = pincode;

View file

@ -21,7 +21,7 @@ class _ConfigViewerState extends State<ConfigViewer> {
String initialValue,
) async {
if (appSetting is AppSettings<bool>) {
await appSetting.setItem(store, !(initialValue == 'true'));
await appSetting.setItem(!(initialValue == 'true'));
setState(() {});
return;
}
@ -35,13 +35,13 @@ class _ConfigViewerState extends State<ConfigViewer> {
if (value == null) return;
if (appSetting is AppSettings<String>) {
await appSetting.setItem(store, value);
await appSetting.setItem(value);
}
if (appSetting is AppSettings<int>) {
await appSetting.setItem(store, int.parse(value));
await appSetting.setItem(int.parse(value));
}
if (appSetting is AppSettings<double>) {
await appSetting.setItem(store, double.parse(value));
await appSetting.setItem(double.parse(value));
}
setState(() {});
@ -78,16 +78,16 @@ class _ConfigViewerState extends State<ConfigViewer> {
final appSetting = AppSettings.values[i];
var value = '';
if (appSetting is AppSettings<String>) {
value = appSetting.getItem(store);
value = appSetting.value;
}
if (appSetting is AppSettings<int>) {
value = appSetting.getItem(store).toString();
value = appSetting.value.toString();
}
if (appSetting is AppSettings<bool>) {
value = appSetting.getItem(store).toString();
value = appSetting.value.toString();
}
if (appSetting is AppSettings<double>) {
value = appSetting.getItem(store).toString();
value = appSetting.value.toString();
}
return ListTile(
title: Text(appSetting.name),

View file

@ -5,11 +5,11 @@ import 'package:matrix/matrix.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluffychat/config/routes.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/widgets/app_lock.dart';
import 'package:fluffychat/widgets/theme_builder.dart';
import '../config/app_config.dart';
import '../utils/custom_scroll_behaviour.dart';
import 'matrix.dart';
@ -43,7 +43,7 @@ class FluffyChatApp extends StatelessWidget {
Widget build(BuildContext context) {
return ThemeBuilder(
builder: (context, themeMode, primaryColor) => MaterialApp.router(
title: AppConfig.applicationName,
title: AppSettings.applicationName.value,
themeMode: themeMode,
theme: FluffyThemes.buildTheme(context, Brightness.light, primaryColor),
darkTheme:

View file

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/utils/platform_infos.dart';
@ -107,7 +108,7 @@ class _PrivacyButtons extends StatelessWidget {
),
),
TextButton(
onPressed: () => launchUrlString(AppConfig.privacyUrl),
onPressed: () => launchUrlString(AppSettings.privacyUrl.value),
child: Text(
L10n.of(context).privacy,
style: shadowTextStyle,

View file

@ -9,7 +9,7 @@ import 'package:image/image.dart';
import 'package:matrix/matrix.dart';
import 'package:universal_html/html.dart' as html;
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/setting_keys.dart';
import 'package:fluffychat/l10n/l10n.dart';
import 'package:fluffychat/utils/client_download_content_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
@ -114,7 +114,7 @@ extension LocalNotificationsExtension on MatrixState {
title,
body: body,
replacesId: linuxNotificationIds[roomId] ?? 0,
appName: AppConfig.applicationName,
appName: AppSettings.applicationName.value,
appIcon: 'fluffychat',
actions: [
NotificationAction(
@ -139,7 +139,7 @@ extension LocalNotificationsExtension on MatrixState {
event.room.setReadMarker(
event.eventId,
mRead: event.eventId,
public: AppConfig.sendPublicReadReceipts,
public: AppSettings.sendPublicReadReceipts.value,
);
break;
case DesktopNotificationActions.openChat:

View file

@ -6,7 +6,6 @@ import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'package:desktop_notifications/desktop_notifications.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:just_audio/just_audio.dart';
@ -27,7 +26,6 @@ import 'package:fluffychat/utils/voip_plugin.dart';
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
import 'package:fluffychat/widgets/fluffy_chat_app.dart';
import 'package:fluffychat/widgets/future_loading_dialog.dart';
import '../config/app_config.dart';
import '../config/setting_keys.dart';
import '../pages/key_verification/key_verification_dialog.dart';
import '../utils/account_bundles.dart';
@ -155,7 +153,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
}
final candidate =
_loginClientCandidate ??= await ClientManager.createClient(
'${AppConfig.applicationName}-${DateTime.now().millisecondsSinceEpoch}',
'${AppSettings.applicationName.value}-${DateTime.now().millisecondsSinceEpoch}',
store,
)
..onLoginStateChanged
@ -221,24 +219,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
super.initState();
WidgetsBinding.instance.addObserver(this);
initMatrix();
if (PlatformInfos.isWeb) {
initConfig().then((_) => initSettings());
} else {
initSettings();
}
}
Future<void> initConfig() async {
try {
final configJsonString =
utf8.decode((await http.get(Uri.parse('config.json'))).bodyBytes);
final configJson = json.decode(configJsonString);
AppConfig.loadFromJson(configJson);
} on FormatException catch (_) {
Logs().v('[ConfigLoader] config.json not found');
} catch (e) {
Logs().v('[ConfigLoader] config.json not found', e);
}
}
void _registerSubs(String name) {
@ -358,7 +338,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
);
}
if (result == OkCancelResult.cancel) {
await store.setBool(SettingKeys.showNoGoogle, true);
await AppSettings.showNoGoogle.setItem(true);
}
},
);
@ -368,7 +348,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
}
void createVoipPlugin() async {
if (store.getBool(SettingKeys.experimentalVoip) == false) {
if (AppSettings.experimentalVoip.value) {
voipPlugin = null;
return;
}
@ -390,55 +370,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
}
}
void initSettings() {
AppConfig.fontSizeFactor =
double.tryParse(store.getString(SettingKeys.fontSizeFactor) ?? '') ??
AppConfig.fontSizeFactor;
AppConfig.renderHtml =
store.getBool(SettingKeys.renderHtml) ?? AppConfig.renderHtml;
AppConfig.swipeRightToLeftToReply =
store.getBool(SettingKeys.swipeRightToLeftToReply) ??
AppConfig.swipeRightToLeftToReply;
AppConfig.hideRedactedEvents =
store.getBool(SettingKeys.hideRedactedEvents) ??
AppConfig.hideRedactedEvents;
AppConfig.hideUnknownEvents =
store.getBool(SettingKeys.hideUnknownEvents) ??
AppConfig.hideUnknownEvents;
AppConfig.separateChatTypes =
store.getBool(SettingKeys.separateChatTypes) ??
AppConfig.separateChatTypes;
AppConfig.autoplayImages =
store.getBool(SettingKeys.autoplayImages) ?? AppConfig.autoplayImages;
AppConfig.sendTypingNotifications =
store.getBool(SettingKeys.sendTypingNotifications) ??
AppConfig.sendTypingNotifications;
AppConfig.sendPublicReadReceipts =
store.getBool(SettingKeys.sendPublicReadReceipts) ??
AppConfig.sendPublicReadReceipts;
AppConfig.sendOnEnter =
store.getBool(SettingKeys.sendOnEnter) ?? AppConfig.sendOnEnter;
AppConfig.experimentalVoip = store.getBool(SettingKeys.experimentalVoip) ??
AppConfig.experimentalVoip;
AppConfig.showPresences =
store.getBool(SettingKeys.showPresences) ?? AppConfig.showPresences;
AppConfig.displayNavigationRail =
store.getBool(SettingKeys.displayNavigationRail) ??
AppConfig.displayNavigationRail;
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);

View file

@ -1,18 +1,16 @@
import 'package:flutter/material.dart';
import 'matrix.dart';
import 'package:fluffychat/config/setting_keys.dart';
class SettingsSwitchListTile extends StatefulWidget {
final bool defaultValue;
final String storeKey;
final AppSettings<bool> setting;
final String title;
final String? subtitle;
final Function(bool)? onChanged;
const SettingsSwitchListTile.adaptive({
super.key,
this.defaultValue = false,
required this.storeKey,
required this.setting,
required this.title,
this.subtitle,
this.onChanged,
@ -27,13 +25,12 @@ class SettingsSwitchListTileState extends State<SettingsSwitchListTile> {
Widget build(BuildContext context) {
final subtitle = widget.subtitle;
return SwitchListTile.adaptive(
value: Matrix.of(context).store.getBool(widget.storeKey) ??
widget.defaultValue,
value: widget.setting.value,
title: Text(widget.title),
subtitle: subtitle == null ? null : Text(subtitle),
onChanged: (bool newValue) async {
widget.onChanged?.call(newValue);
await Matrix.of(context).store.setBool(widget.storeKey, newValue);
await widget.setting.setItem(newValue);
setState(() {});
},
);