refactor: Use AppSettings enum based configuration everywhere and fix load from json on web
This commit is contained in:
parent
4f0ed3e93f
commit
4c357f6249
46 changed files with 359 additions and 404 deletions
58
README.md
58
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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<String> 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<String> 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<String, dynamic> 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'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T> {
|
||||
textMessageMaxLength<int>('textMessageMaxLength', 16384),
|
||||
|
|
@ -44,6 +16,9 @@ enum AppSettings<T> {
|
|||
audioRecordingNoiseSuppress<bool>('audioRecordingNoiseSuppress', true),
|
||||
audioRecordingBitRate<int>('audioRecordingBitRate', 64000),
|
||||
audioRecordingSamplingRate<int>('audioRecordingSamplingRate', 44100),
|
||||
showNoGoogle<bool>('chat.fluffy.show_no_google', false),
|
||||
unifiedPushRegistered<bool>('chat.fluffy.unifiedpush.registered', false),
|
||||
unifiedPushEndpoint<String>('chat.fluffy.unifiedpush.endpoint', ''),
|
||||
pushNotificationsGatewayUrl<String>(
|
||||
'pushNotificationsGatewayUrl',
|
||||
'https://push.fluffychat.im/_matrix/push/v1/notify',
|
||||
|
|
@ -52,6 +27,19 @@ enum AppSettings<T> {
|
|||
'pushNotificationsPusherFormat',
|
||||
'event_id_only',
|
||||
),
|
||||
renderHtml<bool>('chat.fluffy.renderHtml', true),
|
||||
fontSizeFactor<double>('chat.fluffy.font_size_factor', 1.0),
|
||||
hideRedactedEvents<bool>('chat.fluffy.hideRedactedEvents', false),
|
||||
hideUnknownEvents<bool>('chat.fluffy.hideUnknownEvents', true),
|
||||
separateChatTypes<bool>('chat.fluffy.separateChatTypes', false),
|
||||
autoplayImages<bool>('chat.fluffy.autoplay_images', true),
|
||||
sendTypingNotifications<bool>('chat.fluffy.send_typing_notifications', true),
|
||||
sendPublicReadReceipts<bool>('chat.fluffy.send_public_read_receipts', true),
|
||||
swipeRightToLeftToReply<bool>('chat.fluffy.swipeRightToLeftToReply', true),
|
||||
sendOnEnter<bool>('chat.fluffy.send_on_enter', false),
|
||||
showPresences<bool>('chat.fluffy.show_presences', true),
|
||||
displayNavigationRail<bool>('chat.fluffy.display_navigation_rail', false),
|
||||
experimentalVoip<bool>('chat.fluffy.experimental_voip', false),
|
||||
shareKeysWith<String>('chat.fluffy.share_keys_with_2', 'all'),
|
||||
noEncryptionWarningShown<bool>(
|
||||
'chat.fluffy.no_encryption_warning_shown',
|
||||
|
|
@ -61,40 +49,88 @@ enum AppSettings<T> {
|
|||
'chat.fluffy.display_chat_details_column',
|
||||
false,
|
||||
),
|
||||
// AppConfig-mirrored settings
|
||||
applicationName<String>('chat.fluffy.application_name', 'FluffyChat'),
|
||||
defaultHomeserver<String>('chat.fluffy.default_homeserver', 'matrix.org'),
|
||||
privacyUrl<String>(
|
||||
'chat.fluffy.privacy_url',
|
||||
'https://github.com/krille-chan/fluffychat/blob/main/PRIVACY.md',
|
||||
),
|
||||
// colorSchemeSeed stored as ARGB int
|
||||
colorSchemeSeedInt<int>(
|
||||
'chat.fluffy.color_scheme_seed',
|
||||
0xFF5625BA,
|
||||
),
|
||||
enableSoftLogout<bool>('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<SharedPreferences> 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<String, Object?>;
|
||||
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> {
|
||||
bool getItem(SharedPreferences store) => store.getBool(key) ?? defaultValue;
|
||||
bool get value => AppSettings.store.getBool(key) ?? defaultValue;
|
||||
|
||||
Future<void> setItem(SharedPreferences store, bool value) =>
|
||||
store.setBool(key, value);
|
||||
Future<void> setItem(bool value) => AppSettings.store.setBool(key, value);
|
||||
}
|
||||
|
||||
extension AppSettingsStringExtension on AppSettings<String> {
|
||||
String getItem(SharedPreferences store) =>
|
||||
store.getString(key) ?? defaultValue;
|
||||
String get value => AppSettings.store.getString(key) ?? defaultValue;
|
||||
|
||||
Future<void> setItem(SharedPreferences store, String value) =>
|
||||
store.setString(key, value);
|
||||
Future<void> setItem(String value) => AppSettings.store.setString(key, value);
|
||||
}
|
||||
|
||||
extension AppSettingsIntExtension on AppSettings<int> {
|
||||
int getItem(SharedPreferences store) => store.getInt(key) ?? defaultValue;
|
||||
int get value => AppSettings.store.getInt(key) ?? defaultValue;
|
||||
|
||||
Future<void> setItem(SharedPreferences store, int value) =>
|
||||
store.setInt(key, value);
|
||||
Future<void> setItem(int value) => AppSettings.store.setInt(key, value);
|
||||
}
|
||||
|
||||
extension AppSettingsDoubleExtension on AppSettings<double> {
|
||||
double getItem(SharedPreferences store) =>
|
||||
store.getDouble(key) ?? defaultValue;
|
||||
double get value => AppSettings.store.getDouble(key) ?? defaultValue;
|
||||
|
||||
Future<void> setItem(SharedPreferences store, double value) =>
|
||||
store.setDouble(key, value);
|
||||
Future<void> setItem(double value) => AppSettings.store.setDouble(key, value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<void> startGui(List<Client> 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) {
|
||||
|
|
|
|||
|
|
@ -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<ChatPageWithRoom>
|
|||
}
|
||||
|
||||
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<ChatPageWithRoom>
|
|||
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<ChatPageWithRoom>
|
|||
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<ChatPageWithRoom>
|
|||
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<ChatPageWithRoom>
|
|||
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<ChatPageWithRoom>
|
|||
_setReadMarkerFuture = timeline
|
||||
.setReadMarker(
|
||||
eventId: eventId,
|
||||
public: AppConfig.sendPublicReadReceipts,
|
||||
public: AppSettings.sendPublicReadReceipts.value,
|
||||
)
|
||||
.then((_) {
|
||||
_setReadMarkerFuture = null;
|
||||
|
|
@ -542,7 +544,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
Future<void> 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<ChatPageWithRoom>
|
|||
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<ChatPageWithRoom>
|
|||
|
||||
_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<ChatPageWithRoom>
|
|||
}
|
||||
}
|
||||
}
|
||||
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<ChatPageWithRoom>
|
|||
|
||||
void toggleDisplayChatDetailsColumn() async {
|
||||
await AppSettings.displayChatDetailsColumn.setItem(
|
||||
Matrix.of(context).store,
|
||||
!_displayChatDetailsColumn.value,
|
||||
);
|
||||
_displayChatDetailsColumn.value = !_displayChatDetailsColumn.value;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<CuteContent> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
if (AppConfig.autoplayImages && !_isOverlayShown) {
|
||||
if (AppSettings.autoplayImages.value && !_isOverlayShown) {
|
||||
addOverlay();
|
||||
}
|
||||
super.initState();
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<RecordingViewModel> {
|
|||
}
|
||||
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<RecordingViewModel> {
|
|||
|
||||
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 ?? '',
|
||||
|
|
|
|||
|
|
@ -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<ChatList>
|
|||
|
||||
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<ChatList>
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
activeFilter = AppSettings.separateChatTypes.value
|
||||
? ActiveFilter.messages
|
||||
: ActiveFilter.allChats;
|
||||
_initReceiveSharingIntent();
|
||||
_activeSpaceId = widget.activeSpace;
|
||||
|
||||
|
|
@ -713,8 +713,7 @@ class ChatListController extends State<ChatList>
|
|||
context: context,
|
||||
);
|
||||
if (result == OkCancelResult.ok) {
|
||||
await Matrix.of(context).store.setBool(SettingKeys.showPresences, false);
|
||||
AppConfig.showPresences = false;
|
||||
AppSettings.showPresences.setItem(false);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<HomeserverPicker> {
|
|||
bool isLoading = false;
|
||||
|
||||
final TextEditingController homeserverController = TextEditingController(
|
||||
text: AppConfig.defaultHomeserver,
|
||||
text: AppSettings.defaultHomeserver.value,
|
||||
);
|
||||
|
||||
String? error;
|
||||
|
|
@ -211,7 +212,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||
case MoreLoginActions.importBackup:
|
||||
restoreBackup();
|
||||
case MoreLoginActions.privacy:
|
||||
launchUrlString(AppConfig.privacyUrl);
|
||||
launchUrlString(AppSettings.privacyUrl.value);
|
||||
case MoreLoginActions.about:
|
||||
PlatformInfos.showDialog(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ class SettingsSecurityController extends State<SettingsSecurity> {
|
|||
void changeShareKeysWith(ShareKeysWith? shareKeysWith) async {
|
||||
if (shareKeysWith == null) return;
|
||||
AppSettings.shareKeysWith.setItem(
|
||||
Matrix.of(context).store,
|
||||
shareKeysWith.name,
|
||||
);
|
||||
Matrix.of(context).client.shareKeysWith = shareKeysWith;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ class SettingsStyle extends StatefulWidget {
|
|||
|
||||
class SettingsStyleController extends State<SettingsStyle> {
|
||||
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<SettingsStyle> {
|
|||
}
|
||||
|
||||
void changeFontSizeFactor(double d) {
|
||||
setState(() => AppConfig.fontSizeFactor = d);
|
||||
Matrix.of(context).store.setString(
|
||||
SettingKeys.fontSizeFactor,
|
||||
AppConfig.fontSizeFactor.toString(),
|
||||
);
|
||||
AppSettings.fontSizeFactor.setItem(d);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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<void> _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},
|
||||
|
|
|
|||
|
|
@ -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'),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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<void> 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;
|
||||
|
|
|
|||
|
|
@ -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<Event> {
|
||||
List<Event> filterByVisibleInGui({String? exceptionEventId}) => where(
|
||||
List<Event> 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,
|
||||
|
|
|
|||
|
|
@ -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<String?> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<void> 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;
|
||||
|
|
|
|||
|
|
@ -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<String> 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<void> 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<void> _tryPushHelper(
|
|||
|
||||
client ??= (await ClientManager.getClients(
|
||||
initialize: false,
|
||||
store: await SharedPreferences.getInstance(),
|
||||
store: await AppSettings.init(),
|
||||
))
|
||||
.first;
|
||||
final event = await client.getEventByPushNotification(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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(() {});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue