From 4c357f6249d2543308b61acdc2049b65c6e8ce6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Sun, 19 Oct 2025 19:36:47 +0200 Subject: [PATCH] refactor: Use AppSettings enum based configuration everywhere and fix load from json on web --- README.md | 58 +++++++- config.sample.json | 35 +++-- integration_test/app_test.dart | 3 +- lib/config/app_config.dart | 98 +++---------- lib/config/setting_keys.dart | 134 +++++++++++------- lib/config/themes.dart | 3 +- lib/main.dart | 15 +- lib/pages/chat/chat.dart | 29 ++-- lib/pages/chat/chat_input_row.dart | 11 +- lib/pages/chat/chat_view.dart | 4 +- lib/pages/chat/events/cute_events.dart | 4 +- lib/pages/chat/events/image_bubble.dart | 9 +- lib/pages/chat/events/message.dart | 7 +- lib/pages/chat/events/message_content.dart | 12 +- .../chat/events/message_download_content.dart | 7 +- lib/pages/chat/events/reply_content.dart | 4 +- lib/pages/chat/events/state_message.dart | 3 +- lib/pages/chat/events/video_player.dart | 9 +- lib/pages/chat/input_bar.dart | 3 +- lib/pages/chat/recording_view_model.dart | 15 +- lib/pages/chat_list/chat_list.dart | 11 +- lib/pages/chat_list/chat_list_body.dart | 9 +- lib/pages/chat_list/chat_list_view.dart | 4 +- .../homeserver_picker/homeserver_picker.dart | 5 +- .../homeserver_picker_view.dart | 3 +- lib/pages/settings/settings_view.dart | 4 +- .../settings_chat/settings_chat_view.dart | 29 +--- .../settings_security/settings_security.dart | 1 - .../settings_security_view.dart | 8 +- lib/pages/settings_style/settings_style.dart | 10 +- .../settings_style/settings_style_view.dart | 22 ++- lib/utils/background_push.dart | 25 ++-- lib/utils/client_manager.dart | 7 +- lib/utils/init_with_restore.dart | 5 +- .../filtered_timeline_extension.dart | 11 +- .../cipher.dart | 6 +- .../notification_background_handler.dart | 9 +- lib/utils/platform_infos.dart | 5 +- lib/utils/push_helper.dart | 6 +- lib/widgets/app_lock.dart | 3 +- lib/widgets/config_viewer.dart | 16 +-- lib/widgets/fluffy_chat_app.dart | 4 +- lib/widgets/layouts/login_scaffold.dart | 3 +- .../local_notifications_extension.dart | 6 +- lib/widgets/matrix.dart | 75 +--------- lib/widgets/settings_switch_list_tile.dart | 13 +- 46 files changed, 359 insertions(+), 404 deletions(-) diff --git a/README.md b/README.md index 884e220f8..e33536a27 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,63 @@ Please visit the website for installation instructions: # How to build -Please visit the [Wiki](https://github.com/krille-chan/fluffychat/wiki) for build instructions: +1. To build FluffyChat you need [Flutter](https://flutter.dev) and [Rust](https://www.rust-lang.org/tools/install) -- https://github.com/krille-chan/fluffychat/wiki/How-To-Build +2. Clone the repo: +``` +git clone https://github.com/krille-chan/fluffychat.git +cd fluffychat +``` +3. Choose your target platform below and enable support for it. +3.1 If you want, enable Googles Firebase Cloud Messaging: + +`git apply ./scripts/enable-android-google-services.patch` + +4. Debug with: `flutter run` + +### Android + +* Build with: `flutter build apk` + +### iOS / iPadOS + +* Have a Mac with Xcode installed, and set up for Xcode-managed app signing +* If you want automatic app installation to connected devices, make sure you have Apple Configurator installed, with the Automation Tools (`cfgutil`) enabled +* Set a few environment variables + * FLUFFYCHAT_NEW_TEAM: the Apple Developer team that your certificates should live under + * FLUFFYCHAT_NEW_GROUP: the group you want App IDs and such to live under (ie: com.example.fluffychat) + * FLUFFYCHAT_INSTALL_IPA: set to `1` if you want the IPA to be deployed to connected devices after building, otherwise unset +* Run `./scripts/build-ios.sh` + +### Web + +* Build with: +```bash +./scripts/prepare-web.sh # To install Vodozemac +flutter build web --release +``` + +* Optionally configure by serving a `config.json` at the same path as fluffychat. + An example can be found at `config.sample.json`. All values there are optional. + **Please only the values, you really need**. If you e.g. only want + to change the default homeserver, then only modify the `defaultHomeserver` key. + +### Desktop (Linux, Windows, macOS) + +* Enable Desktop support in Flutter: https://flutter.dev/desktop + +#### Install custom dependencies (Linux) + +```bash +sudo apt install libjsoncpp1 libsecret-1-dev libsecret-1-0 librhash0 libwebkit2gtk-4.0-dev +``` + +* Build with one of these: +```bash +flutter build linux --release +flutter build windows --release +flutter build macos --release +``` # Special thanks diff --git a/config.sample.json b/config.sample.json index ff37ec238..5aa0a4bb0 100644 --- a/config.sample.json +++ b/config.sample.json @@ -1,10 +1,29 @@ { - "application_name": "FluffyChat", - "application_welcome_message": null, - "default_homeserver": "matrix.org", - "web_base_url": "https://fluffychat.im/web", - "privacy_url": "https://fluffychat.im/en/privacy.html", - "render_html": false, - "hide_redacted_events": false, - "hide_unknown_events": false + "applicationName": "FluffyChat", + "defaultHomeserver": "matrix.org", + "privacyUrl": "https://github.com/krille-chan/fluffychat/blob/main/PRIVACY.md", + "audioRecordingNumChannels": 1, + "audioRecordingAutoGain": true, + "audioRecordingEchoCancel": false, + "audioRecordingNoiseSuppress": true, + "audioRecordingBitRate": 64000, + "audioRecordingSamplingRate": 44100, + "renderHtml": true, + "fontSizeFactor": 1, + "hideRedactedEvents": false, + "hideUnknownEvents": true, + "separateChatTypes": false, + "autoplayImages": true, + "sendTypingNotifications": true, + "sendPublicReadReceipts": true, + "swipeRightToLeftToReply": true, + "sendOnEnter": false, + "showPresences": true, + "displayNavigationRail": false, + "experimentalVoip": false, + "shareKeysWith": "all", + "noEncryptionWarningShown": false, + "displayChatDetailsColumn": false, + "colorSchemeSeedInt": 4283835834, + "enableSoftLogout": false } \ No newline at end of file diff --git a/integration_test/app_test.dart b/integration_test/app_test.dart index 4b49aac6b..3a0139365 100644 --- a/integration_test/app_test.dart +++ b/integration_test/app_test.dart @@ -1,4 +1,3 @@ -import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/pages/chat/chat_view.dart'; import 'package:fluffychat/pages/chat_list/chat_list_body.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart'; @@ -25,7 +24,7 @@ void main() { () async { // this random dialog popping up is super hard to cover in tests SharedPreferences.setMockInitialValues({ - SettingKeys.showNoGoogle: false, + 'chat.fluffy.show_no_google': false, }); }, ); diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index a80d16e14..e6a4b6c0c 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -1,32 +1,25 @@ import 'dart:ui'; -import 'package:matrix/matrix.dart'; - abstract class AppConfig { - static String _applicationName = 'FluffyChat'; - - static String get applicationName => _applicationName; - static String? _applicationWelcomeMessage; - - static String? get applicationWelcomeMessage => _applicationWelcomeMessage; - static String _defaultHomeserver = 'matrix.org'; - - static String get defaultHomeserver => _defaultHomeserver; - static double fontSizeFactor = 1; - static const Color chatColor = primaryColor; - static Color? colorSchemeSeed = primaryColor; - static const double messageFontSize = 16.0; - static const bool allowOtherHomeservers = true; - static const bool enableRegistration = true; + // Const and final configuration values (immutable) static const Color primaryColor = Color(0xFF5625BA); static const Color primaryColorLight = Color(0xFFCCBDEA); static const Color secondaryColor = Color(0xFF41a2bc); - static String _privacyUrl = - 'https://github.com/krille-chan/fluffychat/blob/main/PRIVACY.md'; - static const Set defaultReactions = {'👍', '❤️', '😂', '😮', '😢'}; + static const Color chatColor = primaryColor; + static const double messageFontSize = 16.0; + static const bool allowOtherHomeservers = true; + static const bool enableRegistration = true; + static const bool hideTypingUsernames = false; + + static const String inviteLinkPrefix = 'https://matrix.to/#/'; + static const String deepLinkPrefix = 'im.fluffychat://chat/'; + static const String schemePrefix = 'matrix:'; + static const String pushNotificationsChannelId = 'fluffychat_push'; + static const String pushNotificationsAppId = 'chat.fluffy.fluffychat'; + static const double borderRadius = 18.0; + static const double columnWidth = 360.0; - static String get privacyUrl => _privacyUrl; static const String website = 'https://fluffychat.im'; static const String enablePushTutorial = 'https://github.com/krille-chan/fluffychat/wiki/Push-Notifications-without-Google-Services'; @@ -36,80 +29,25 @@ abstract class AppConfig { 'https://github.com/krille-chan/fluffychat/wiki/How-to-Find-Users-in-FluffyChat'; static const String appId = 'im.fluffychat.FluffyChat'; static const String appOpenUrlScheme = 'im.fluffychat'; - static String _webBaseUrl = 'https://fluffychat.im/web'; - static String get webBaseUrl => _webBaseUrl; static const String sourceCodeUrl = 'https://github.com/krille-chan/fluffychat'; static const String supportUrl = 'https://github.com/krille-chan/fluffychat/issues'; static const String changelogUrl = 'https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md'; + + static const Set defaultReactions = {'👍', '❤️', '😂', '😮', '😢'}; + static final Uri newIssueUrl = Uri( scheme: 'https', host: 'github.com', path: '/krille-chan/fluffychat/issues/new', ); - static bool renderHtml = true; - static bool hideRedactedEvents = false; - static bool hideUnknownEvents = true; - static bool separateChatTypes = false; - static bool autoplayImages = true; - static bool sendTypingNotifications = true; - static bool sendPublicReadReceipts = true; - static bool swipeRightToLeftToReply = true; - static bool? sendOnEnter; - static bool showPresences = true; - static bool displayNavigationRail = false; - static bool experimentalVoip = false; - static const bool hideTypingUsernames = false; - static const String inviteLinkPrefix = 'https://matrix.to/#/'; - static const String deepLinkPrefix = 'im.fluffychat://chat/'; - static const String schemePrefix = 'matrix:'; - static const String pushNotificationsChannelId = 'fluffychat_push'; - static const String pushNotificationsAppId = 'chat.fluffy.fluffychat'; - static const double borderRadius = 18.0; - static const double columnWidth = 360.0; + static final Uri homeserverList = Uri( scheme: 'https', host: 'servers.joinmatrix.org', path: 'servers.json', ); - - static void loadFromJson(Map json) { - if (json['chat_color'] != null) { - try { - colorSchemeSeed = Color(json['chat_color']); - } catch (e) { - Logs().w( - 'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"', - e, - ); - } - } - if (json['application_name'] is String) { - _applicationName = json['application_name']; - } - if (json['application_welcome_message'] is String) { - _applicationWelcomeMessage = json['application_welcome_message']; - } - if (json['default_homeserver'] is String) { - _defaultHomeserver = json['default_homeserver']; - } - if (json['privacy_url'] is String) { - _privacyUrl = json['privacy_url']; - } - if (json['web_base_url'] is String) { - _webBaseUrl = json['web_base_url']; - } - if (json['render_html'] is bool) { - renderHtml = json['render_html']; - } - if (json['hide_redacted_events'] is bool) { - hideRedactedEvents = json['hide_redacted_events']; - } - if (json['hide_unknown_events'] is bool) { - hideUnknownEvents = json['hide_unknown_events']; - } - } } diff --git a/lib/config/setting_keys.dart b/lib/config/setting_keys.dart index 484e48bc0..084e24007 100644 --- a/lib/config/setting_keys.dart +++ b/lib/config/setting_keys.dart @@ -1,40 +1,12 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; + +import 'package:http/http.dart' as http; +import 'package:matrix/matrix_api_lite/utils/logs.dart'; import 'package:shared_preferences/shared_preferences.dart'; -abstract class SettingKeys { - static const String renderHtml = 'chat.fluffy.renderHtml'; - static const String hideRedactedEvents = 'chat.fluffy.hideRedactedEvents'; - static const String hideUnknownEvents = 'chat.fluffy.hideUnknownEvents'; - static const String hideUnimportantStateEvents = - 'chat.fluffy.hideUnimportantStateEvents'; - static const String separateChatTypes = 'chat.fluffy.separateChatTypes'; - static const String sentry = 'sentry'; - static const String theme = 'theme'; - static const String amoledEnabled = 'amoled_enabled'; - static const String codeLanguage = 'code_language'; - static const String showNoGoogle = 'chat.fluffy.show_no_google'; - static const String fontSizeFactor = 'chat.fluffy.font_size_factor'; - static const String showNoPid = 'chat.fluffy.show_no_pid'; - static const String databasePassword = 'database-password'; - static const String appLockKey = 'chat.fluffy.app_lock'; - static const String unifiedPushRegistered = - 'chat.fluffy.unifiedpush.registered'; - static const String unifiedPushEndpoint = 'chat.fluffy.unifiedpush.endpoint'; - static const String ownStatusMessage = 'chat.fluffy.status_msg'; - static const String dontAskForBootstrapKey = - 'chat.fluffychat.dont_ask_bootstrap'; - static const String autoplayImages = 'chat.fluffy.autoplay_images'; - static const String sendTypingNotifications = - 'chat.fluffy.send_typing_notifications'; - static const String sendPublicReadReceipts = - 'chat.fluffy.send_public_read_receipts'; - static const String sendOnEnter = 'chat.fluffy.send_on_enter'; - static const String swipeRightToLeftToReply = - 'chat.fluffy.swipeRightToLeftToReply'; - static const String experimentalVoip = 'chat.fluffy.experimental_voip'; - static const String showPresences = 'chat.fluffy.show_presences'; - static const String displayNavigationRail = - 'chat.fluffy.display_navigation_rail'; -} +import 'package:fluffychat/utils/platform_infos.dart'; enum AppSettings { textMessageMaxLength('textMessageMaxLength', 16384), @@ -44,6 +16,9 @@ enum AppSettings { audioRecordingNoiseSuppress('audioRecordingNoiseSuppress', true), audioRecordingBitRate('audioRecordingBitRate', 64000), audioRecordingSamplingRate('audioRecordingSamplingRate', 44100), + showNoGoogle('chat.fluffy.show_no_google', false), + unifiedPushRegistered('chat.fluffy.unifiedpush.registered', false), + unifiedPushEndpoint('chat.fluffy.unifiedpush.endpoint', ''), pushNotificationsGatewayUrl( 'pushNotificationsGatewayUrl', 'https://push.fluffychat.im/_matrix/push/v1/notify', @@ -52,6 +27,19 @@ enum AppSettings { 'pushNotificationsPusherFormat', 'event_id_only', ), + renderHtml('chat.fluffy.renderHtml', true), + fontSizeFactor('chat.fluffy.font_size_factor', 1.0), + hideRedactedEvents('chat.fluffy.hideRedactedEvents', false), + hideUnknownEvents('chat.fluffy.hideUnknownEvents', true), + separateChatTypes('chat.fluffy.separateChatTypes', false), + autoplayImages('chat.fluffy.autoplay_images', true), + sendTypingNotifications('chat.fluffy.send_typing_notifications', true), + sendPublicReadReceipts('chat.fluffy.send_public_read_receipts', true), + swipeRightToLeftToReply('chat.fluffy.swipeRightToLeftToReply', true), + sendOnEnter('chat.fluffy.send_on_enter', false), + showPresences('chat.fluffy.show_presences', true), + displayNavigationRail('chat.fluffy.display_navigation_rail', false), + experimentalVoip('chat.fluffy.experimental_voip', false), shareKeysWith('chat.fluffy.share_keys_with_2', 'all'), noEncryptionWarningShown( 'chat.fluffy.no_encryption_warning_shown', @@ -61,40 +49,88 @@ enum AppSettings { 'chat.fluffy.display_chat_details_column', false, ), + // AppConfig-mirrored settings + applicationName('chat.fluffy.application_name', 'FluffyChat'), + defaultHomeserver('chat.fluffy.default_homeserver', 'matrix.org'), + privacyUrl( + 'chat.fluffy.privacy_url', + 'https://github.com/krille-chan/fluffychat/blob/main/PRIVACY.md', + ), + // colorSchemeSeed stored as ARGB int + colorSchemeSeedInt( + 'chat.fluffy.color_scheme_seed', + 0xFF5625BA, + ), enableSoftLogout('chat.fluffy.enable_soft_logout', false); final String key; final T defaultValue; const AppSettings(this.key, this.defaultValue); + + static late final SharedPreferences store; + + static Future init({loadWebConfigFile = true}) async { + final store = AppSettings.store = await SharedPreferences.getInstance(); + + if (store.getBool(AppSettings.sendOnEnter.key) == null) { + await store.setBool(AppSettings.sendOnEnter.key, !PlatformInfos.isMobile); + } + + if (kIsWeb && loadWebConfigFile) { + try { + final configJsonString = + utf8.decode((await http.get(Uri.parse('config.json'))).bodyBytes); + final configJson = + json.decode(configJsonString) as Map; + for (final setting in AppSettings.values) { + if (store.get(setting.key) != null) continue; + final configValue = configJson[setting.key]; + if (configValue == null) continue; + if (configValue is bool) { + await store.setBool(setting.key, configValue); + } + if (configValue is String) { + await store.setString(setting.key, configValue); + } + if (configValue is int) { + await store.setInt(setting.key, configValue); + } + if (configValue is double) { + await store.setDouble(setting.key, configValue); + } + } + } on FormatException catch (_) { + Logs().v('[ConfigLoader] config.json not found'); + } catch (e) { + Logs().v('[ConfigLoader] config.json not found', e); + } + } + + return store; + } } extension AppSettingsBoolExtension on AppSettings { - bool getItem(SharedPreferences store) => store.getBool(key) ?? defaultValue; + bool get value => AppSettings.store.getBool(key) ?? defaultValue; - Future setItem(SharedPreferences store, bool value) => - store.setBool(key, value); + Future setItem(bool value) => AppSettings.store.setBool(key, value); } extension AppSettingsStringExtension on AppSettings { - String getItem(SharedPreferences store) => - store.getString(key) ?? defaultValue; + String get value => AppSettings.store.getString(key) ?? defaultValue; - Future setItem(SharedPreferences store, String value) => - store.setString(key, value); + Future setItem(String value) => AppSettings.store.setString(key, value); } extension AppSettingsIntExtension on AppSettings { - int getItem(SharedPreferences store) => store.getInt(key) ?? defaultValue; + int get value => AppSettings.store.getInt(key) ?? defaultValue; - Future setItem(SharedPreferences store, int value) => - store.setInt(key, value); + Future setItem(int value) => AppSettings.store.setInt(key, value); } extension AppSettingsDoubleExtension on AppSettings { - double getItem(SharedPreferences store) => - store.getDouble(key) ?? defaultValue; + double get value => AppSettings.store.getDouble(key) ?? defaultValue; - Future setItem(SharedPreferences store, double value) => - store.setDouble(key, value); + Future setItem(double value) => AppSettings.store.setDouble(key, value); } diff --git a/lib/config/themes.dart b/lib/config/themes.dart index e7e516008..b409dc247 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'app_config.dart'; abstract class FluffyThemes { @@ -45,7 +46,7 @@ abstract class FluffyThemes { ]) { final colorScheme = ColorScheme.fromSeed( brightness: brightness, - seedColor: seed ?? AppConfig.colorSchemeSeed ?? AppConfig.primaryColor, + seedColor: seed ?? Color(AppSettings.colorSchemeSeedInt.value), ); final isColumnMode = FluffyThemes.isColumnMode(context); return ThemeData( diff --git a/lib/main.dart b/lib/main.dart index f3be9dc52..9f9c350c2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,7 +6,6 @@ import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod; import 'package:matrix/matrix.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/utils/client_manager.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'config/setting_keys.dart'; @@ -14,17 +13,17 @@ import 'utils/background_push.dart'; import 'widgets/fluffy_chat_app.dart'; void main() async { - Logs().i('Welcome to ${AppConfig.applicationName} <3'); - // Our background push shared isolate accesses flutter-internal things very early in the startup proccess // To make sure that the parts of flutter needed are started up already, we need to ensure that the // widget bindings are initialized already. WidgetsFlutterBinding.ensureInitialized(); + final store = await AppSettings.init(); + Logs().i('Welcome to ${AppSettings.applicationName.value} <3'); + await vod.init(wasmPath: './assets/assets/vodozemac/'); Logs().nativeColors = !PlatformInfos.isIOS; - final store = await SharedPreferences.getInstance(); final clients = await ClientManager.getClients(store: store); // If the app starts in detached mode, we assume that it is in @@ -44,14 +43,14 @@ void main() async { // To start the flutter engine afterwards we add an custom observer. WidgetsBinding.instance.addObserver(AppStarter(clients, store)); Logs().i( - '${AppConfig.applicationName} started in background-fetch mode. No GUI will be created unless the app is no longer detached.', + '${AppSettings.applicationName.value} started in background-fetch mode. No GUI will be created unless the app is no longer detached.', ); return; } // Started in foreground mode. Logs().i( - '${AppConfig.applicationName} started in foreground mode. Rendering GUI...', + '${AppSettings.applicationName.value} started in foreground mode. Rendering GUI...', ); await startGui(clients, store); } @@ -63,7 +62,7 @@ Future startGui(List clients, SharedPreferences store) async { if (PlatformInfos.isMobile) { try { pin = - await const FlutterSecureStorage().read(key: SettingKeys.appLockKey); + await const FlutterSecureStorage().read(key: 'chat.fluffy.app_lock'); } catch (e, s) { Logs().d('Unable to read PIN from Secure storage', e, s); } @@ -92,7 +91,7 @@ class AppStarter with WidgetsBindingObserver { if (state == AppLifecycleState.detached) return; Logs().i( - '${AppConfig.applicationName} switches from the detached background-fetch mode to ${state.name} mode. Rendering GUI...', + '${AppSettings.applicationName.value} switches from the detached background-fetch mode to ${state.name} mode. Rendering GUI...', ); // Switching to foreground mode needs to reenable send online sync presence. for (final client in clients) { diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 2490eea4c..125552c43 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -13,10 +13,8 @@ import 'package:go_router/go_router.dart'; import 'package:image_picker/image_picker.dart'; import 'package:matrix/matrix.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; -import 'package:shared_preferences/shared_preferences.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/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; @@ -224,7 +222,7 @@ class ChatController extends State } void _loadDraft() async { - final prefs = await SharedPreferences.getInstance(); + final prefs = Matrix.of(context).store; final draft = prefs.getString('draft_$roomId'); if (draft != null && draft.isNotEmpty) { sendController.text = draft; @@ -274,7 +272,7 @@ class ChatController extends State KeyEventResult _customEnterKeyHandling(FocusNode node, KeyEvent evt) { if (!HardwareKeyboard.instance.isShiftPressed && evt.logicalKey.keyLabel == 'Enter' && - (AppConfig.sendOnEnter ?? !PlatformInfos.isMobile)) { + AppSettings.sendOnEnter.value) { if (evt is KeyDownEvent) { send(); } @@ -325,7 +323,7 @@ class ChatController extends State WidgetsBinding.instance.addPostFrameCallback(_shareItems); super.initState(); _displayChatDetailsColumn = ValueNotifier( - AppSettings.displayChatDetailsColumn.getItem(Matrix.of(context).store), + AppSettings.displayChatDetailsColumn.value, ); sendingClient = Matrix.of(context).client; @@ -365,7 +363,9 @@ class ChatController extends State var readMarkerEventIndex = readMarkerEventId.isEmpty ? -1 : timeline!.events - .filterByVisibleInGui(exceptionEventId: readMarkerEventId) + .filterByVisibleInGui( + exceptionEventId: readMarkerEventId, + ) .indexWhere((e) => e.eventId == readMarkerEventId); // Read marker is existing but not found in first events. Try a single @@ -373,7 +373,9 @@ class ChatController extends State if (readMarkerEventId.isNotEmpty && readMarkerEventIndex == -1) { await timeline?.requestHistory(historyCount: _loadHistoryCount); readMarkerEventIndex = timeline!.events - .filterByVisibleInGui(exceptionEventId: readMarkerEventId) + .filterByVisibleInGui( + exceptionEventId: readMarkerEventId, + ) .indexWhere((e) => e.eventId == readMarkerEventId); } @@ -492,7 +494,7 @@ class ChatController extends State _setReadMarkerFuture = timeline .setReadMarker( eventId: eventId, - public: AppConfig.sendPublicReadReceipts, + public: AppSettings.sendPublicReadReceipts.value, ) .then((_) { _setReadMarkerFuture = null; @@ -542,7 +544,7 @@ class ChatController extends State Future send() async { if (sendController.text.trim().isEmpty) return; _storeInputTimeoutTimer?.cancel(); - final prefs = await SharedPreferences.getInstance(); + final prefs = Matrix.of(context).store; prefs.remove('draft_$roomId'); var parseCommands = true; @@ -960,7 +962,9 @@ class ChatController extends State final eventIndex = foundEvent == null ? -1 : timeline!.events - .filterByVisibleInGui(exceptionEventId: eventId) + .filterByVisibleInGui( + exceptionEventId: eventId, + ) .indexOf(foundEvent); if (eventIndex == -1) { @@ -1203,7 +1207,7 @@ class ChatController extends State _storeInputTimeoutTimer?.cancel(); _storeInputTimeoutTimer = Timer(_storeInputTimeout, () async { - final prefs = await SharedPreferences.getInstance(); + final prefs = Matrix.of(context).store; await prefs.setString('draft_$roomId', text); }); if (text.endsWith(' ') && Matrix.of(context).hasComplexBundles) { @@ -1220,7 +1224,7 @@ class ChatController extends State } } } - if (AppConfig.sendTypingNotifications) { + if (AppSettings.sendTypingNotifications.value) { typingCoolDown?.cancel(); typingCoolDown = Timer(const Duration(seconds: 2), () { typingCoolDown = null; @@ -1307,7 +1311,6 @@ class ChatController extends State void toggleDisplayChatDetailsColumn() async { await AppSettings.displayChatDetailsColumn.setItem( - Matrix.of(context).store, !_displayChatDetailsColumn.value, ); _displayChatDetailsColumn.value = !_displayChatDetailsColumn.value; diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index ea42e92f6..7d520bac1 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:animations/animations.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat/recording_input_row.dart'; import 'package:fluffychat/pages/chat/recording_view_model.dart'; @@ -297,10 +297,11 @@ class ChatInputRow extends StatelessWidget { maxLines: 8, autofocus: !PlatformInfos.isMobile, keyboardType: TextInputType.multiline, - textInputAction: AppConfig.sendOnEnter == true && - PlatformInfos.isMobile - ? TextInputAction.send - : null, + textInputAction: + AppSettings.sendOnEnter.value == true && + PlatformInfos.isMobile + ? TextInputAction.send + : null, onSubmitted: controller.onInputBarSubmitted, onSubmitImage: controller.sendImageFromClipBoard, focusNode: controller.inputFocus, diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index eb9b0e234..2d08b1a2c 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -6,7 +6,7 @@ import 'package:badges/badges.dart'; import 'package:desktop_drop/desktop_drop.dart'; import 'package:matrix/matrix.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/pages/chat/chat.dart'; @@ -119,7 +119,7 @@ class ChatView extends StatelessWidget { ]; } else if (!controller.room.isArchived) { return [ - if (AppConfig.experimentalVoip && + if (AppSettings.experimentalVoip.value && Matrix.of(context).voipPlugin != null && controller.room.isDirectChat) IconButton( diff --git a/lib/pages/chat/events/cute_events.dart b/lib/pages/chat/events/cute_events.dart index bb675e641..9d43021dc 100644 --- a/lib/pages/chat/events/cute_events.dart +++ b/lib/pages/chat/events/cute_events.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; class CuteContent extends StatefulWidget { @@ -21,7 +21,7 @@ class _CuteContentState extends State { @override void initState() { - if (AppConfig.autoplayImages && !_isOverlayShown) { + if (AppSettings.autoplayImages.value && !_isOverlayShown) { addOverlay(); } super.initState(); diff --git a/lib/pages/chat/events/image_bubble.dart b/lib/pages/chat/events/image_bubble.dart index ea0439bec..305b83ba8 100644 --- a/lib/pages/chat/events/image_bubble.dart +++ b/lib/pages/chat/events/image_bubble.dart @@ -4,6 +4,7 @@ import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/pages/image_viewer/image_viewer.dart'; import 'package:fluffychat/utils/file_description.dart'; import 'package:fluffychat/utils/url_launcher.dart'; @@ -139,14 +140,14 @@ class ImageBubble extends StatelessWidget { textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: - AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: - AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, ), diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index d0b4c025e..e9a8b3cc2 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -7,6 +7,7 @@ import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:matrix/matrix.dart'; import 'package:swipe_to_action/swipe_to_action.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat/events/room_creation_state_event.dart'; @@ -204,7 +205,7 @@ class Message extends StatelessWidget { child: Icon(Icons.check_outlined), ), ), - direction: AppConfig.swipeRightToLeftToReply + direction: AppSettings.swipeRightToLeftToReply.value ? SwipeDirection.endToStart : SwipeDirection.startToEnd, onSwipe: (_) => onSwipe(), @@ -243,7 +244,7 @@ class Message extends StatelessWidget { child: Text( event.originServerTs.localizedTime(context), style: TextStyle( - fontSize: 12 * AppConfig.fontSizeFactor, + fontSize: 12 * AppSettings.fontSizeFactor.value, fontWeight: FontWeight.bold, color: theme.colorScheme.secondary, ), @@ -890,7 +891,7 @@ class Message extends StatelessWidget { child: Text( L10n.of(context).readUpToHere, style: TextStyle( - fontSize: 12 * AppConfig.fontSizeFactor, + fontSize: 12 * AppSettings.fontSizeFactor.value, ), ), ), diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 5876335eb..85aa05941 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat/events/video_player.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; @@ -105,7 +106,8 @@ class MessageContent extends StatelessWidget { @override Widget build(BuildContext context) { - final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; + final fontSize = + AppConfig.messageFontSize * AppSettings.fontSizeFactor.value; final buttonTextColor = textColor; switch (event.type) { case EventTypes.Message: @@ -255,7 +257,7 @@ class MessageContent extends StatelessWidget { }, ); } - var html = AppConfig.renderHtml && event.isRichMessage + var html = AppSettings.renderHtml.value && event.isRichMessage ? event.formattedText : event.body; if (event.messageType == MessageTypes.Emote) { @@ -274,14 +276,14 @@ class MessageContent extends StatelessWidget { html: html, textColor: textColor, room: event.room, - fontSize: AppConfig.fontSizeFactor * + fontSize: AppSettings.fontSizeFactor.value * AppConfig.messageFontSize * (bigEmotes ? 5 : 1), limitHeight: !selected, linkStyle: TextStyle( color: linkColor, - fontSize: - AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, ), diff --git a/lib/pages/chat/events/message_download_content.dart b/lib/pages/chat/events/message_download_content.dart index f1b517d14..18b5c0b07 100644 --- a/lib/pages/chat/events/message_download_content.dart +++ b/lib/pages/chat/events/message_download_content.dart @@ -4,6 +4,7 @@ import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/utils/file_description.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/url_launcher.dart'; @@ -92,12 +93,14 @@ class MessageDownloadContent extends StatelessWidget { textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, ), diff --git a/lib/pages/chat/events/reply_content.dart b/lib/pages/chat/events/reply_content.dart index b3df56522..10e6c2351 100644 --- a/lib/pages/chat/events/reply_content.dart +++ b/lib/pages/chat/events/reply_content.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import '../../../config/app_config.dart'; @@ -30,7 +31,8 @@ class ReplyContent extends StatelessWidget { final timeline = this.timeline; final displayEvent = timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent; - final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; + final fontSize = + AppConfig.messageFontSize * AppSettings.fontSizeFactor.value; final color = theme.brightness == Brightness.dark ? theme.colorScheme.onTertiaryContainer : ownMessage diff --git a/lib/pages/chat/events/state_message.dart b/lib/pages/chat/events/state_message.dart index 7d6be428c..9ef9d4e7a 100644 --- a/lib/pages/chat/events/state_message.dart +++ b/lib/pages/chat/events/state_message.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; @@ -68,7 +69,7 @@ class StateMessage extends StatelessWidget { ), textAlign: TextAlign.center, style: TextStyle( - fontSize: 12 * AppConfig.fontSizeFactor, + fontSize: 12 * AppSettings.fontSizeFactor.value, decoration: event.redacted ? TextDecoration.lineThrough : null, diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index 6b31eb774..5635bd23f 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -6,6 +6,7 @@ import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/utils/file_description.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -136,14 +137,14 @@ class EventVideoPlayer extends StatelessWidget { textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: - AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: - AppConfig.fontSizeFactor * AppConfig.messageFontSize, + fontSize: AppSettings.fontSizeFactor.value * + AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, ), diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index cfb4bb16e..54915218d 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -415,8 +415,7 @@ class InputBar extends StatelessWidget { // it sets the types for the callback incorrectly onSubmitted!(text); }, - maxLength: - AppSettings.textMessageMaxLength.getItem(Matrix.of(context).store), + maxLength: AppSettings.textMessageMaxLength.value, decoration: decoration, onChanged: (text) { // fix for the library for now diff --git a/lib/pages/chat/recording_view_model.dart b/lib/pages/chat/recording_view_model.dart index f222f7c13..4c3471008 100644 --- a/lib/pages/chat/recording_view_model.dart +++ b/lib/pages/chat/recording_view_model.dart @@ -15,7 +15,6 @@ import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; import 'events/audio_player.dart'; class RecordingViewModel extends StatefulWidget { @@ -62,8 +61,6 @@ class RecordingViewModelState extends State { } if (await AudioRecorder().hasPermission() == false) return; - final store = Matrix.of(context).store; - final audioRecorder = _audioRecorder ??= AudioRecorder(); setState(() {}); @@ -93,12 +90,12 @@ class RecordingViewModelState extends State { await audioRecorder.start( RecordConfig( - bitRate: AppSettings.audioRecordingBitRate.getItem(store), - sampleRate: AppSettings.audioRecordingSamplingRate.getItem(store), - numChannels: AppSettings.audioRecordingNumChannels.getItem(store), - autoGain: AppSettings.audioRecordingAutoGain.getItem(store), - echoCancel: AppSettings.audioRecordingEchoCancel.getItem(store), - noiseSuppress: AppSettings.audioRecordingNoiseSuppress.getItem(store), + bitRate: AppSettings.audioRecordingBitRate.value, + sampleRate: AppSettings.audioRecordingSamplingRate.value, + numChannels: AppSettings.audioRecordingNumChannels.value, + autoGain: AppSettings.audioRecordingAutoGain.value, + echoCancel: AppSettings.audioRecordingEchoCancel.value, + noiseSuppress: AppSettings.audioRecordingNoiseSuppress.value, encoder: codec, ), path: path ?? '', diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 8bb8680af..07c71db4d 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -12,7 +12,6 @@ import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat_list/chat_list_view.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; @@ -94,9 +93,7 @@ class ChatListController extends State StreamSubscription? _intentUriStreamSubscription; - ActiveFilter activeFilter = AppConfig.separateChatTypes - ? ActiveFilter.messages - : ActiveFilter.allChats; + late ActiveFilter activeFilter; String? _activeSpaceId; String? get activeSpaceId => _activeSpaceId; @@ -401,6 +398,9 @@ class ChatListController extends State @override void initState() { + activeFilter = AppSettings.separateChatTypes.value + ? ActiveFilter.messages + : ActiveFilter.allChats; _initReceiveSharingIntent(); _activeSpaceId = widget.activeSpace; @@ -713,8 +713,7 @@ class ChatListController extends State context: context, ); if (result == OkCancelResult.ok) { - await Matrix.of(context).store.setBool(SettingKeys.showPresences, false); - AppConfig.showPresences = false; + AppSettings.showPresences.setItem(false); setState(() {}); } } diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index a789f3586..fe696b036 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; @@ -120,7 +120,8 @@ class ChatListViewBody extends StatelessWidget { ), ), ], - if (!controller.isSearchMode && AppConfig.showPresences) + if (!controller.isSearchMode && + AppSettings.showPresences.value) GestureDetector( onLongPress: () => controller.dismissStatusList(), child: StatusMessageList( @@ -155,14 +156,14 @@ class ChatListViewBody extends StatelessWidget { shrinkWrap: true, scrollDirection: Axis.horizontal, children: [ - if (AppConfig.separateChatTypes) + if (AppSettings.separateChatTypes.value) ActiveFilter.messages else ActiveFilter.allChats, ActiveFilter.groups, ActiveFilter.unread, if (spaceDelegateCandidates.isNotEmpty && - !AppConfig.displayNavigationRail && + !AppSettings.displayNavigationRail.value && !FluffyThemes.isColumnMode(context)) ActiveFilter.spaces, ] diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 35f763983..1b04bed8c 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.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/pages/chat_list/chat_list.dart'; @@ -32,7 +32,7 @@ class ChatListView extends StatelessWidget { child: Row( children: [ if (FluffyThemes.isColumnMode(context) || - AppConfig.displayNavigationRail) ...[ + AppSettings.displayNavigationRail.value) ...[ SpacesNavigationRail( activeSpaceId: controller.activeSpaceId, onGoToChats: controller.clearActiveSpace, diff --git a/lib/pages/homeserver_picker/homeserver_picker.dart b/lib/pages/homeserver_picker/homeserver_picker.dart index b17a3bc06..4e96a7154 100644 --- a/lib/pages/homeserver_picker/homeserver_picker.dart +++ b/lib/pages/homeserver_picker/homeserver_picker.dart @@ -11,6 +11,7 @@ import 'package:universal_html/html.dart' as html; 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/l10n/l10n.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart'; import 'package:fluffychat/utils/file_selector.dart'; @@ -34,7 +35,7 @@ class HomeserverPickerController extends State { bool isLoading = false; final TextEditingController homeserverController = TextEditingController( - text: AppConfig.defaultHomeserver, + text: AppSettings.defaultHomeserver.value, ); String? error; @@ -211,7 +212,7 @@ class HomeserverPickerController extends State { case MoreLoginActions.importBackup: restoreBackup(); case MoreLoginActions.privacy: - launchUrlString(AppConfig.privacyUrl); + launchUrlString(AppSettings.privacyUrl.value); case MoreLoginActions.about: PlatformInfos.showDialog(context); } diff --git a/lib/pages/homeserver_picker/homeserver_picker_view.dart b/lib/pages/homeserver_picker/homeserver_picker_view.dart index 4161f1f9a..6beedc47d 100644 --- a/lib/pages/homeserver_picker/homeserver_picker_view.dart +++ b/lib/pages/homeserver_picker/homeserver_picker_view.dart @@ -5,6 +5,7 @@ import 'package:url_launcher/url_launcher.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/l10n/l10n.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/adaptive_dialog_action.dart'; import 'package:fluffychat/widgets/layouts/login_scaffold.dart'; @@ -155,7 +156,7 @@ class HomeserverPickerView extends StatelessWidget { AppConfig.borderRadius, ), ), - hintText: AppConfig.defaultHomeserver, + hintText: AppSettings.defaultHomeserver.value, hintStyle: TextStyle( color: theme.colorScheme.surfaceTint, ), diff --git a/lib/pages/settings/settings_view.dart b/lib/pages/settings/settings_view.dart index 0a72704aa..aa9c3d50b 100644 --- a/lib/pages/settings/settings_view.dart +++ b/lib/pages/settings/settings_view.dart @@ -4,7 +4,7 @@ import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.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/fluffy_share.dart'; @@ -244,7 +244,7 @@ class SettingsView extends StatelessWidget { ListTile( leading: const Icon(Icons.privacy_tip_outlined), title: Text(L10n.of(context).privacy), - onTap: () => launchUrlString(AppConfig.privacyUrl), + onTap: () => launchUrlString(AppSettings.privacyUrl.value), ), ListTile( leading: const Icon(Icons.info_outline_rounded), diff --git a/lib/pages/settings_chat/settings_chat_view.dart b/lib/pages/settings_chat/settings_chat_view.dart index d3526a28e..b125cf734 100644 --- a/lib/pages/settings_chat/settings_chat_view.dart +++ b/lib/pages/settings_chat/settings_chat_view.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.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'; @@ -34,41 +33,29 @@ class SettingsChatView extends StatelessWidget { SettingsSwitchListTile.adaptive( title: L10n.of(context).formattedMessages, subtitle: L10n.of(context).formattedMessagesDescription, - onChanged: (b) => AppConfig.renderHtml = b, - storeKey: SettingKeys.renderHtml, - defaultValue: AppConfig.renderHtml, + setting: AppSettings.renderHtml, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).hideRedactedMessages, subtitle: L10n.of(context).hideRedactedMessagesBody, - onChanged: (b) => AppConfig.hideRedactedEvents = b, - storeKey: SettingKeys.hideRedactedEvents, - defaultValue: AppConfig.hideRedactedEvents, + setting: AppSettings.hideRedactedEvents, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).hideInvalidOrUnknownMessageFormats, - onChanged: (b) => AppConfig.hideUnknownEvents = b, - storeKey: SettingKeys.hideUnknownEvents, - defaultValue: AppConfig.hideUnknownEvents, + setting: AppSettings.hideUnknownEvents, ), if (PlatformInfos.isMobile) SettingsSwitchListTile.adaptive( title: L10n.of(context).autoplayImages, - onChanged: (b) => AppConfig.autoplayImages = b, - storeKey: SettingKeys.autoplayImages, - defaultValue: AppConfig.autoplayImages, + setting: AppSettings.autoplayImages, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).sendOnEnter, - onChanged: (b) => AppConfig.sendOnEnter = b, - storeKey: SettingKeys.sendOnEnter, - defaultValue: AppConfig.sendOnEnter ?? !PlatformInfos.isMobile, + setting: AppSettings.sendOnEnter, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).swipeRightToLeftToReply, - onChanged: (b) => AppConfig.swipeRightToLeftToReply = b, - storeKey: SettingKeys.swipeRightToLeftToReply, - defaultValue: AppConfig.swipeRightToLeftToReply, + setting: AppSettings.swipeRightToLeftToReply, ), Divider(color: theme.dividerColor), ListTile( @@ -102,12 +89,10 @@ class SettingsChatView extends StatelessWidget { SettingsSwitchListTile.adaptive( title: L10n.of(context).experimentalVideoCalls, onChanged: (b) { - AppConfig.experimentalVoip = b; Matrix.of(context).createVoipPlugin(); return; }, - storeKey: SettingKeys.experimentalVoip, - defaultValue: AppConfig.experimentalVoip, + setting: AppSettings.experimentalVoip, ), ], ), diff --git a/lib/pages/settings_security/settings_security.dart b/lib/pages/settings_security/settings_security.dart index a645460c5..2ec3747c0 100644 --- a/lib/pages/settings_security/settings_security.dart +++ b/lib/pages/settings_security/settings_security.dart @@ -112,7 +112,6 @@ class SettingsSecurityController extends State { void changeShareKeysWith(ShareKeysWith? shareKeysWith) async { if (shareKeysWith == null) return; AppSettings.shareKeysWith.setItem( - Matrix.of(context).store, shareKeysWith.name, ); Matrix.of(context).client.shareKeysWith = shareKeysWith; diff --git a/lib/pages/settings_security/settings_security_view.dart b/lib/pages/settings_security/settings_security_view.dart index b181c9915..039fd97eb 100644 --- a/lib/pages/settings_security/settings_security_view.dart +++ b/lib/pages/settings_security/settings_security_view.dart @@ -63,16 +63,12 @@ class SettingsSecurityView extends StatelessWidget { title: L10n.of(context).sendTypingNotifications, subtitle: L10n.of(context).sendTypingNotificationsDescription, - onChanged: (b) => AppConfig.sendTypingNotifications = b, - storeKey: SettingKeys.sendTypingNotifications, - defaultValue: AppConfig.sendTypingNotifications, + setting: AppSettings.sendTypingNotifications, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).sendReadReceipts, subtitle: L10n.of(context).sendReadReceiptsDescription, - onChanged: (b) => AppConfig.sendPublicReadReceipts = b, - storeKey: SettingKeys.sendPublicReadReceipts, - defaultValue: AppConfig.sendPublicReadReceipts, + setting: AppSettings.sendPublicReadReceipts, ), ListTile( trailing: const Icon(Icons.chevron_right_outlined), diff --git a/lib/pages/settings_style/settings_style.dart b/lib/pages/settings_style/settings_style.dart index 49b0b003c..968759ad4 100644 --- a/lib/pages/settings_style/settings_style.dart +++ b/lib/pages/settings_style/settings_style.dart @@ -18,7 +18,9 @@ class SettingsStyle extends StatefulWidget { class SettingsStyleController extends State { void setChatColor(Color? color) async { - AppConfig.colorSchemeSeed = color; + AppSettings.colorSchemeSeedInt.setItem( + color?.toARGB32() ?? AppSettings.colorSchemeSeedInt.defaultValue, + ); ThemeController.of(context).setPrimaryColor(color); } @@ -156,11 +158,7 @@ class SettingsStyleController extends State { } void changeFontSizeFactor(double d) { - setState(() => AppConfig.fontSizeFactor = d); - Matrix.of(context).store.setString( - SettingKeys.fontSizeFactor, - AppConfig.fontSizeFactor.toString(), - ); + AppSettings.fontSizeFactor.setItem(d); } @override diff --git a/lib/pages/settings_style/settings_style_view.dart b/lib/pages/settings_style/settings_style_view.dart index f4bbd7285..23dbe68cb 100644 --- a/lib/pages/settings_style/settings_style_view.dart +++ b/lib/pages/settings_style/settings_style_view.dart @@ -230,7 +230,7 @@ class SettingsStyleView extends StatelessWidget { style: TextStyle( color: theme.onBubbleColor, fontSize: AppConfig.messageFontSize * - AppConfig.fontSizeFactor, + AppSettings.fontSizeFactor.value, ), ), ), @@ -263,7 +263,7 @@ class SettingsStyleView extends StatelessWidget { style: TextStyle( color: theme.colorScheme.onSurface, fontSize: AppConfig.messageFontSize * - AppConfig.fontSizeFactor, + AppSettings.fontSizeFactor.value, ), ), ), @@ -325,13 +325,15 @@ class SettingsStyleView extends StatelessWidget { ), ListTile( title: Text(L10n.of(context).fontSize), - trailing: Text('× ${AppConfig.fontSizeFactor}'), + trailing: Text( + '× ${AppSettings.fontSizeFactor.value}', + ), ), Slider.adaptive( min: 0.5, max: 2.5, divisions: 20, - value: AppConfig.fontSizeFactor, + value: AppSettings.fontSizeFactor.value, semanticFormatterCallback: (d) => d.toString(), onChanged: controller.changeFontSizeFactor, ), @@ -349,21 +351,15 @@ class SettingsStyleView extends StatelessWidget { ), SettingsSwitchListTile.adaptive( title: L10n.of(context).presencesToggle, - onChanged: (b) => AppConfig.showPresences = b, - storeKey: SettingKeys.showPresences, - defaultValue: AppConfig.showPresences, + setting: AppSettings.showPresences, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).separateChatTypes, - onChanged: (b) => AppConfig.separateChatTypes = b, - storeKey: SettingKeys.separateChatTypes, - defaultValue: AppConfig.separateChatTypes, + setting: AppSettings.separateChatTypes, ), SettingsSwitchListTile.adaptive( title: L10n.of(context).displayNavigationRail, - onChanged: (b) => AppConfig.displayNavigationRail = b, - storeKey: SettingKeys.displayNavigationRail, - defaultValue: AppConfig.displayNavigationRail, + setting: AppSettings.displayNavigationRail, ), ], ), diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart index d25a7a68a..4fa5a52b4 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart @@ -217,8 +217,7 @@ class BackgroundPush { currentPushers.first.lang == 'en' && currentPushers.first.data.url.toString() == gatewayUrl && currentPushers.first.data.format == - AppSettings.pushNotificationsPusherFormat - .getItem(matrix!.store) && + AppSettings.pushNotificationsPusherFormat.value && mapEquals( currentPushers.single.data.additionalProperties, {"data_message": pusherDataMessageFormat}, @@ -258,8 +257,7 @@ class BackgroundPush { lang: 'en', data: PusherData( url: Uri.parse(gatewayUrl!), - format: AppSettings.pushNotificationsPusherFormat - .getItem(matrix!.store), + format: AppSettings.pushNotificationsPusherFormat.value, additionalProperties: {"data_message": pusherDataMessageFormat}, ), kind: 'http', @@ -325,7 +323,7 @@ class BackgroundPush { if (matrix == null) { return; } - if ((matrix?.store.getBool(SettingKeys.showNoGoogle) ?? false) == true) { + if (!AppSettings.showNoGoogle.value) { return; } await loadLocale(); @@ -356,8 +354,7 @@ class BackgroundPush { } } await setupPusher( - gatewayUrl: - AppSettings.pushNotificationsGatewayUrl.getItem(matrix!.store), + gatewayUrl: AppSettings.pushNotificationsGatewayUrl.value, token: _fcmToken, ); } @@ -414,18 +411,18 @@ class BackgroundPush { oldTokens: oldTokens, useDeviceSpecificAppId: true, ); - await matrix?.store.setString(SettingKeys.unifiedPushEndpoint, newEndpoint); - await matrix?.store.setBool(SettingKeys.unifiedPushRegistered, true); + await AppSettings.unifiedPushEndpoint.setItem(newEndpoint); + await AppSettings.unifiedPushRegistered.setItem(true); } Future _upUnregistered(String i) async { upAction = true; Logs().i('[Push] Removing UnifiedPush endpoint...'); - final oldEndpoint = - matrix?.store.getString(SettingKeys.unifiedPushEndpoint); - await matrix?.store.setBool(SettingKeys.unifiedPushRegistered, false); - await matrix?.store.remove(SettingKeys.unifiedPushEndpoint); - if (oldEndpoint?.isNotEmpty ?? false) { + final oldEndpoint = AppSettings.unifiedPushEndpoint.value; + await AppSettings.unifiedPushEndpoint + .setItem(AppSettings.unifiedPushEndpoint.defaultValue); + await AppSettings.unifiedPushRegistered.setItem(false); + if (oldEndpoint.isNotEmpty) { // remove the old pusher await setupPusher( oldTokens: {oldEndpoint}, diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 5c5a07663..9fe1b2dfd 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -11,7 +11,6 @@ import 'package:matrix/matrix.dart'; import 'package:shared_preferences/shared_preferences.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/custom_http_client.dart'; @@ -101,8 +100,8 @@ abstract class ClientManager { String clientName, SharedPreferences store, ) async { - final shareKeysWith = AppSettings.shareKeysWith.getItem(store); - final enableSoftLogout = AppSettings.enableSoftLogout.getItem(store); + final shareKeysWith = AppSettings.shareKeysWith.value; + final enableSoftLogout = AppSettings.enableSoftLogout.value; return Client( clientName, @@ -147,7 +146,7 @@ abstract class ClientManager { await NotificationsClient().notify( title, body: body, - appName: AppConfig.applicationName, + appName: AppSettings.applicationName.value, hints: [ NotificationHint.soundName('message-new-instant'), ], diff --git a/lib/utils/init_with_restore.dart b/lib/utils/init_with_restore.dart index 523b22f9e..feb95e003 100644 --- a/lib/utils/init_with_restore.dart +++ b/lib/utils/init_with_restore.dart @@ -5,6 +5,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:matrix/matrix.dart'; 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_manager.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -57,13 +58,13 @@ extension InitWithRestoreExtension on Client { ? const FlutterSecureStorage() : null; await storage?.delete( - key: '${AppConfig.applicationName}_session_backup_$clientName', + key: '${AppSettings.applicationName.value}_session_backup_$clientName', ); } Future initWithRestore({void Function()? onMigration}) async { final storageKey = - '${AppConfig.applicationName}_session_backup_$clientName'; + '${AppSettings.applicationName.value}_session_backup_$clientName'; final storage = PlatformInfos.isMobile || PlatformInfos.isLinux ? const FlutterSecureStorage() : null; diff --git a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart index 055ce5011..a72666f4e 100644 --- a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart +++ b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart @@ -1,9 +1,12 @@ import 'package:matrix/matrix.dart'; -import '../../config/app_config.dart'; +import 'package:fluffychat/config/setting_keys.dart'; extension VisibleInGuiExtension on List { - List filterByVisibleInGui({String? exceptionEventId}) => where( + List filterByVisibleInGui({ + String? exceptionEventId, + }) => + where( (event) => event.isVisibleInGui || event.eventId == exceptionEventId, ).toList(); } @@ -19,9 +22,9 @@ extension IsStateExtension on Event { // if a reaction has been redacted we also want it to be hidden in the timeline !{EventTypes.Reaction, EventTypes.Redaction}.contains(type) && // if we enabled to hide all redacted events, don't show those - (!AppConfig.hideRedactedEvents || !redacted) && + (!AppSettings.hideRedactedEvents.value || !redacted) && // if we enabled to hide all unknown events, don't show those - (!AppConfig.hideUnknownEvents || isEventTypeKnown); + (!AppSettings.hideUnknownEvents.value || isEventTypeKnown); bool get isState => !{ EventTypes.Message, diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart index 6169cf0f3..293053759 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart @@ -6,7 +6,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:matrix/matrix.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; @@ -52,8 +51,7 @@ Future getDatabaseCipher() async { } void _sendNoEncryptionWarning(Object exception) async { - final store = await SharedPreferences.getInstance(); - final isStored = AppSettings.noEncryptionWarningShown.getItem(store); + final isStored = AppSettings.noEncryptionWarningShown.value; if (isStored == true) return; @@ -63,5 +61,5 @@ void _sendNoEncryptionWarning(Object exception) async { exception.toString(), ); - await AppSettings.noEncryptionWarningShown.setItem(store, true); + await AppSettings.noEncryptionWarningShown.setItem(true); } diff --git a/lib/utils/notification_background_handler.dart b/lib/utils/notification_background_handler.dart index 531d7e19d..aa8ea17dd 100644 --- a/lib/utils/notification_background_handler.dart +++ b/lib/utils/notification_background_handler.dart @@ -6,7 +6,6 @@ import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/utils/client_download_content_extension.dart'; @@ -59,7 +58,7 @@ void notificationTapBackground( await vod.init(); _vodInitialized = true; } - final store = await SharedPreferences.getInstance(); + final store = await AppSettings.init(); final client = (await ClientManager.getClients( initialize: false, store: store, @@ -71,10 +70,6 @@ void notificationTapBackground( waitUntilLoadCompletedLoaded: false, ); - AppConfig.sendPublicReadReceipts = - store.getBool(SettingKeys.sendPublicReadReceipts) ?? - AppConfig.sendPublicReadReceipts; - if (!client.isLogged()) { throw Exception('Notification tab in background but not logged in!'); } @@ -145,7 +140,7 @@ Future notificationTap( await room.setReadMarker( payload.eventId ?? room.lastEvent!.eventId, mRead: payload.eventId ?? room.lastEvent!.eventId, - public: AppConfig.sendPublicReadReceipts, + public: AppSettings.sendPublicReadReceipts.value, ); case FluffyChatNotificationActions.reply: final input = notificationResponse.input; diff --git a/lib/utils/platform_infos.dart b/lib/utils/platform_infos.dart index c180ff86c..bf6589df2 100644 --- a/lib/utils/platform_infos.dart +++ b/lib/utils/platform_infos.dart @@ -7,6 +7,7 @@ import 'package:go_router/go_router.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/l10n/l10n.dart'; import '../config/app_config.dart'; @@ -36,7 +37,7 @@ abstract class PlatformInfos { static bool get platformCanRecord => (isMobile || isMacOS); static String get clientName => - '${AppConfig.applicationName} ${isWeb ? 'web' : Platform.operatingSystem}${kReleaseMode ? '' : 'Debug'}'; + '${AppSettings.applicationName.value} ${isWeb ? 'web' : Platform.operatingSystem}${kReleaseMode ? '' : 'Debug'}'; static Future getVersion() async { var version = kIsWeb ? 'Web' : 'Unknown'; @@ -88,7 +89,7 @@ abstract class PlatformInfos { height: 64, filterQuality: FilterQuality.medium, ), - applicationName: AppConfig.applicationName, + applicationName: AppSettings.applicationName.value, ); } } diff --git a/lib/utils/push_helper.dart b/lib/utils/push_helper.dart index 6a9dd6e4e..70f7a40f5 100644 --- a/lib/utils/push_helper.dart +++ b/lib/utils/push_helper.dart @@ -8,9 +8,9 @@ import 'package:collection/collection.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_shortcuts_new/flutter_shortcuts_new.dart'; import 'package:matrix/matrix.dart'; -import 'package:shared_preferences/shared_preferences.dart'; 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/client_manager.dart'; @@ -50,7 +50,7 @@ Future pushHelper( l10n.incomingMessages, number: notification.counts?.unread, ticker: l10n.unreadChatsInApp( - AppConfig.applicationName, + AppSettings.applicationName.value, (notification.counts?.unread ?? 0).toString(), ), importance: Importance.high, @@ -85,7 +85,7 @@ Future _tryPushHelper( client ??= (await ClientManager.getClients( initialize: false, - store: await SharedPreferences.getInstance(), + store: await AppSettings.init(), )) .first; final event = await client.getEventByPushNotification( diff --git a/lib/widgets/app_lock.dart b/lib/widgets/app_lock.dart index d337358d7..c4682d9f4 100644 --- a/lib/widgets/app_lock.dart +++ b/lib/widgets/app_lock.dart @@ -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 with WidgetsBindingObserver { Future changePincode(String? pincode) async { await const FlutterSecureStorage().write( - key: SettingKeys.appLockKey, + key: 'chat.fluffy.app_lock', value: pincode, ); _pincode = pincode; diff --git a/lib/widgets/config_viewer.dart b/lib/widgets/config_viewer.dart index adfb34407..b0537317c 100644 --- a/lib/widgets/config_viewer.dart +++ b/lib/widgets/config_viewer.dart @@ -21,7 +21,7 @@ class _ConfigViewerState extends State { String initialValue, ) async { if (appSetting is AppSettings) { - await appSetting.setItem(store, !(initialValue == 'true')); + await appSetting.setItem(!(initialValue == 'true')); setState(() {}); return; } @@ -35,13 +35,13 @@ class _ConfigViewerState extends State { if (value == null) return; if (appSetting is AppSettings) { - await appSetting.setItem(store, value); + await appSetting.setItem(value); } if (appSetting is AppSettings) { - await appSetting.setItem(store, int.parse(value)); + await appSetting.setItem(int.parse(value)); } if (appSetting is AppSettings) { - await appSetting.setItem(store, double.parse(value)); + await appSetting.setItem(double.parse(value)); } setState(() {}); @@ -78,16 +78,16 @@ class _ConfigViewerState extends State { final appSetting = AppSettings.values[i]; var value = ''; if (appSetting is AppSettings) { - value = appSetting.getItem(store); + value = appSetting.value; } if (appSetting is AppSettings) { - value = appSetting.getItem(store).toString(); + value = appSetting.value.toString(); } if (appSetting is AppSettings) { - value = appSetting.getItem(store).toString(); + value = appSetting.value.toString(); } if (appSetting is AppSettings) { - value = appSetting.getItem(store).toString(); + value = appSetting.value.toString(); } return ListTile( title: Text(appSetting.name), diff --git a/lib/widgets/fluffy_chat_app.dart b/lib/widgets/fluffy_chat_app.dart index cbe7f088a..8c37c814d 100644 --- a/lib/widgets/fluffy_chat_app.dart +++ b/lib/widgets/fluffy_chat_app.dart @@ -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: diff --git a/lib/widgets/layouts/login_scaffold.dart b/lib/widgets/layouts/login_scaffold.dart index 9b2bc944a..e0cc24577 100644 --- a/lib/widgets/layouts/login_scaffold.dart +++ b/lib/widgets/layouts/login_scaffold.dart @@ -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, diff --git a/lib/widgets/local_notifications_extension.dart b/lib/widgets/local_notifications_extension.dart index 0cdc291ef..0d0069fa4 100644 --- a/lib/widgets/local_notifications_extension.dart +++ b/lib/widgets/local_notifications_extension.dart @@ -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: diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index 3bf20b123..55fd267ad 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -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 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 with WidgetsBindingObserver { super.initState(); WidgetsBinding.instance.addObserver(this); initMatrix(); - if (PlatformInfos.isWeb) { - initConfig().then((_) => initSettings()); - } else { - initSettings(); - } - } - - Future 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 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 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 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); diff --git a/lib/widgets/settings_switch_list_tile.dart b/lib/widgets/settings_switch_list_tile.dart index f49b97598..f625f9e64 100644 --- a/lib/widgets/settings_switch_list_tile.dart +++ b/lib/widgets/settings_switch_list_tile.dart @@ -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 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 { 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(() {}); }, );