fluffychat merge
This commit is contained in:
commit
913edd9f35
79 changed files with 1120 additions and 1046 deletions
|
|
@ -17,7 +17,6 @@
|
|||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"/>
|
||||
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"
|
||||
android:maxSdkVersion="29" />
|
||||
|
|
@ -161,16 +160,6 @@
|
|||
android:foregroundServiceType="camera|microphone|mediaProjection">
|
||||
</service>
|
||||
|
||||
<service android:name="io.wazo.callkeep.VoiceConnectionService"
|
||||
android:label="Wazo"
|
||||
android:foregroundServiceType="camera|microphone|mediaProjection"
|
||||
android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.telecom.ConnectionService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<!-- From flutter_local_notifications package for notification actions -->
|
||||
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,29 @@
|
|||
{
|
||||
"application_name": "PangeaChat",
|
||||
"application_welcome_message": null,
|
||||
"default_homeserver": "matrix.pangea.chat",
|
||||
"web_base_url": "https://web.pangea.chat",
|
||||
"privacy_url": "https://pangea.chat/privacy",
|
||||
"render_html": false,
|
||||
"hide_redacted_events": false,
|
||||
"hide_unknown_events": false
|
||||
"applicationName": "PangeaChat",
|
||||
"defaultHomeserver": "matrix.pangea.chat",
|
||||
"privacyUrl": "https://pangea.chat/privacy",
|
||||
"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,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,97 +2,41 @@ import 'package:flutter/material.dart';
|
|||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
|
||||
abstract class AppConfig {
|
||||
// #Pangea
|
||||
// static String _applicationName = 'FluffyChat';
|
||||
static String _applicationName = 'Pangea Chat';
|
||||
static String get defaultHomeserver => Environment.synapseURL;
|
||||
// Pangea#
|
||||
// Const and final configuration values (immutable)
|
||||
// #Pangea
|
||||
|
||||
static String get applicationName => _applicationName;
|
||||
static String? _applicationWelcomeMessage;
|
||||
|
||||
static String? get applicationWelcomeMessage => _applicationWelcomeMessage;
|
||||
// #Pangea
|
||||
// static String _defaultHomeserver = 'matrix.org';
|
||||
static String get _defaultHomeserver => Environment.synapseURL;
|
||||
// static const Color primaryColor = Color(0xFF5625BA);
|
||||
// static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||
// static const Color secondaryColor = Color(0xFF41a2bc);
|
||||
static const Color primaryColor = Color(0xFF8560E0);
|
||||
static const Color primaryColorLight = Color(0xFFDBC9FF);
|
||||
static const Color secondaryColor = Color.fromARGB(255, 253, 191, 1);
|
||||
// Pangea#
|
||||
|
||||
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;
|
||||
static const bool hideTypingUsernames = false;
|
||||
|
||||
static const String inviteLinkPrefix = 'https://matrix.to/#/';
|
||||
static const String deepLinkPrefix = 'im.fluffychat://chat/';
|
||||
static const String schemePrefix = 'matrix:';
|
||||
// #Pangea
|
||||
static const double toolbarMaxHeight = 250.0;
|
||||
static const double toolbarMinHeight = 150.0;
|
||||
static const double toolbarMinWidth = 350.0;
|
||||
static const double toolbarMenuHeight = 50.0;
|
||||
static const double defaultHeaderHeight = 56.0;
|
||||
static const double toolbarButtonsHeight = 50.0;
|
||||
static const double toolbarSpacing = 8.0;
|
||||
static const double toolbarIconSize = 24.0;
|
||||
static const double readingAssistanceInputBarHeight = 175.0;
|
||||
static const double reactionsPickerHeight = 48.0;
|
||||
static const double chatInputRowOverlayPadding = 8.0;
|
||||
static const double selectModeInputBarHeight = 0;
|
||||
// reactionsPickerHeight + (chatInputRowOverlayPadding * 2) + toolbarSpacing;
|
||||
static const double practiceModeInputBarHeight =
|
||||
readingAssistanceInputBarHeight +
|
||||
toolbarButtonsHeight +
|
||||
(chatInputRowOverlayPadding * 2) +
|
||||
toolbarSpacing;
|
||||
// static const String pushNotificationsChannelId = 'fluffychat_push';
|
||||
// static const String pushNotificationsAppId = 'chat.fluffy.fluffychat';
|
||||
static const String pushNotificationsChannelId = 'pangeachat_push';
|
||||
static const String pushNotificationsAppId = 'com.talktolearn.chat';
|
||||
// Pangea#
|
||||
static const double borderRadius = 18.0;
|
||||
static const double columnWidth = 360.0;
|
||||
|
||||
static TextStyle messageTextStyle(
|
||||
Event? event,
|
||||
Color textColor,
|
||||
) {
|
||||
final fontSize = messageFontSize * fontSizeFactor;
|
||||
final bigEmotes = event != null &&
|
||||
event.onlyEmotes &&
|
||||
event.numberEmotes > 0 &&
|
||||
event.numberEmotes <= 3;
|
||||
|
||||
return TextStyle(
|
||||
color: textColor,
|
||||
fontSize: bigEmotes ? fontSize * 5 : fontSize,
|
||||
decoration:
|
||||
(event?.redacted ?? false) ? TextDecoration.lineThrough : null,
|
||||
height: 1.3,
|
||||
);
|
||||
}
|
||||
|
||||
// static const Color primaryColor = Color(0xFF5625BA);
|
||||
// static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||
static const Color primaryColor = Color(0xFF8560E0);
|
||||
static const Color primaryColorLight = Color(0xFFDBC9FF);
|
||||
// static const Color secondaryColor = Color(0xFF41a2bc);
|
||||
static const Color secondaryColor = Color.fromARGB(255, 253, 191, 1);
|
||||
static const Color activeToggleColor = Color(0xFF33D057);
|
||||
static const Color success = Color(0xFF33D057);
|
||||
static const Color warning = Color.fromARGB(255, 210, 124, 12);
|
||||
static const Color gold = Color.fromARGB(255, 253, 191, 1);
|
||||
static const Color silver = Color.fromARGB(255, 192, 192, 192);
|
||||
static const Color bronze = Color.fromARGB(255, 205, 127, 50);
|
||||
static const Color goldLight = Color.fromARGB(255, 254, 223, 73);
|
||||
|
||||
static const Color yellowLight = Color.fromARGB(255, 247, 218, 120);
|
||||
static const Color yellowDark = Color.fromARGB(255, 253, 191, 1);
|
||||
|
||||
static const Color error = Colors.red;
|
||||
static const int overlayAnimationDuration = 250;
|
||||
static const int roomCreationTimeoutSeconds = 15;
|
||||
// static String _privacyUrl =
|
||||
// 'https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md';
|
||||
static String _privacyUrl = "https://www.pangeachat.com/privacy";
|
||||
//Pangea#
|
||||
|
||||
static const Set<String> defaultReactions = {'👍', '❤️', '😂', '😮', '😢'};
|
||||
|
||||
static String get privacyUrl => _privacyUrl;
|
||||
// #Pangea
|
||||
// static const String website = 'https://fluffychat.im';
|
||||
static const String website = "https://pangea.chat/";
|
||||
|
|
@ -108,9 +52,7 @@ abstract class AppConfig {
|
|||
// static const String appOpenUrlScheme = 'im.fluffychat';
|
||||
static const String appOpenUrlScheme = 'matrix.pangea.chat';
|
||||
// Pangea#
|
||||
static String _webBaseUrl = 'https://fluffychat.im/web';
|
||||
|
||||
static String get webBaseUrl => _webBaseUrl;
|
||||
static const String sourceCodeUrl =
|
||||
'https://github.com/krille-chan/fluffychat';
|
||||
// #Pangea
|
||||
|
|
@ -118,126 +60,81 @@ abstract class AppConfig {
|
|||
// 'https://github.com/krille-chan/fluffychat/issues';
|
||||
// static const String changelogUrl =
|
||||
// 'https://github.com/krille-chan/fluffychat/blob/main/CHANGELOG.md';
|
||||
// static const String donationUrl = 'https://ko-fi.com/krille';
|
||||
static const String supportUrl = 'https://www.pangeachat.com/faqs';
|
||||
static const String termsOfServiceUrl =
|
||||
'https://www.pangeachat.com/terms-of-service';
|
||||
// Pangea#
|
||||
|
||||
static const Set<String> defaultReactions = {'👍', '❤️', '😂', '😮', '😢'};
|
||||
|
||||
static final Uri newIssueUrl = Uri(
|
||||
scheme: 'https',
|
||||
host: 'github.com',
|
||||
path: '/krille-chan/fluffychat/issues/new',
|
||||
);
|
||||
// #Pangea
|
||||
static const bool enableSentry = true;
|
||||
static const String sentryDns =
|
||||
'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143';
|
||||
// Pangea#
|
||||
static bool renderHtml = true;
|
||||
// #Pangea
|
||||
// static bool hideRedactedEvents = false;
|
||||
static bool hideRedactedEvents = true;
|
||||
// Pangea#
|
||||
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 useActivityImageAsChatBackground = true;
|
||||
static bool showPresences = true;
|
||||
// #Pangea
|
||||
// static bool displayNavigationRail = false;
|
||||
static bool displayNavigationRail = true;
|
||||
// Pangea#
|
||||
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:';
|
||||
// #Pangea
|
||||
// static const String pushNotificationsChannelId = 'fluffychat_push';
|
||||
// static const String pushNotificationsAppId = 'chat.fluffy.fluffychat';
|
||||
static const String pushNotificationsChannelId = 'pangeachat_push';
|
||||
static const String pushNotificationsAppId = 'com.talktolearn.chat';
|
||||
// Pangea#
|
||||
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 final Uri privacyUrl = Uri(
|
||||
scheme: 'https',
|
||||
host: 'github.com',
|
||||
path: '/krille-chan/fluffychat/blob/main/PRIVACY.md',
|
||||
);
|
||||
|
||||
// #Pangea
|
||||
static String googlePlayMangementUrl =
|
||||
"https://play.google.com/store/account/subscriptions";
|
||||
static String googlePlayHistoryUrl =
|
||||
"https://play.google.com/store/account/orderhistory";
|
||||
static String assetsBaseURL =
|
||||
"https://pangea-chat-client-assets.s3.us-east-1.amazonaws.com";
|
||||
static String androidUpdateURL =
|
||||
"https://play.google.com/store/apps/details?id=com.talktolearn.chat";
|
||||
static String iosUpdateURL = "itms-apps://itunes.apple.com/app/id1445118630";
|
||||
static String googlePlayPaymentMethodUrl =
|
||||
"https://play.google.com/store/paymentmethods";
|
||||
static String appleMangementUrl =
|
||||
"https://apps.apple.com/account/subscriptions";
|
||||
static String stripePerMonth =
|
||||
"https://buy.stripe.com/test_bIY6ssd8z5Uz8ec8ww";
|
||||
static String iosPromoCode =
|
||||
"https://apps.apple.com/redeem?ctx=offercodes&id=1445118630&code=";
|
||||
static String androidUpdateURL =
|
||||
"https://play.google.com/store/apps/details?id=com.talktolearn.chat";
|
||||
static String iosUpdateURL = "itms-apps://itunes.apple.com/app/id1445118630";
|
||||
|
||||
static String windowsTTSDownloadInstructions =
|
||||
"https://support.microsoft.com/en-us/topic/download-languages-and-voices-for-immersive-reader-read-mode-and-read-aloud-4c83a8d8-7486-42f7-8e46-2b0fdf753130";
|
||||
static String androidTTSDownloadInstructions =
|
||||
"https://support.google.com/accessibility/android/answer/6006983?hl=en";
|
||||
static String assetsBaseURL =
|
||||
"https://pangea-chat-client-assets.s3.us-east-1.amazonaws.com";
|
||||
|
||||
static String googlePlayMangementUrl =
|
||||
"https://play.google.com/store/account/subscriptions";
|
||||
static String googlePlayHistoryUrl =
|
||||
"https://play.google.com/store/account/orderhistory";
|
||||
static bool useActivityImageAsChatBackground = true;
|
||||
static const int overlayAnimationDuration = 250;
|
||||
static double volume = 1.0;
|
||||
static const Color gold = Color.fromARGB(255, 253, 191, 1);
|
||||
static const Color goldLight = Color.fromARGB(255, 254, 223, 73);
|
||||
static const Color success = Color(0xFF33D057);
|
||||
static const Color error = Colors.red;
|
||||
static const Color warning = Color.fromARGB(255, 210, 124, 12);
|
||||
static const Color activeToggleColor = Color(0xFF33D057);
|
||||
static const Color yellowLight = Color.fromARGB(255, 247, 218, 120);
|
||||
static const Color yellowDark = Color.fromARGB(255, 253, 191, 1);
|
||||
static const double toolbarMaxHeight = 250.0;
|
||||
static const double toolbarMinWidth = 350.0;
|
||||
static const double toolbarMinHeight = 150.0;
|
||||
static const double toolbarMenuHeight = 50.0;
|
||||
static const double readingAssistanceInputBarHeight = 175.0;
|
||||
static String errorSubscriptionId = "pangea_subscription_error";
|
||||
|
||||
static double volume = 1.0;
|
||||
static bool showedActivityMenu = false;
|
||||
// Pangea#
|
||||
static TextStyle messageTextStyle(
|
||||
Event? event,
|
||||
Color textColor,
|
||||
) {
|
||||
final fontSize = messageFontSize * AppSettings.fontSizeFactor.value;
|
||||
final bigEmotes = event != null &&
|
||||
event.onlyEmotes &&
|
||||
event.numberEmotes > 0 &&
|
||||
event.numberEmotes <= 3;
|
||||
|
||||
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'];
|
||||
}
|
||||
// #Pangea
|
||||
// if (json['default_homeserver'] is String) {
|
||||
// _defaultHomeserver = json['default_homeserver'];
|
||||
// }
|
||||
// Pangea#
|
||||
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) {
|
||||
// #Pangea
|
||||
// this is interfering with our PangeaRichText functionality, removing it for now
|
||||
renderHtml = false;
|
||||
// renderHtml = json['render_html'];
|
||||
// Pangea#
|
||||
}
|
||||
if (json['hide_redacted_events'] is bool) {
|
||||
hideRedactedEvents = json['hide_redacted_events'];
|
||||
}
|
||||
if (json['hide_unknown_events'] is bool) {
|
||||
hideUnknownEvents = json['hide_unknown_events'];
|
||||
}
|
||||
return TextStyle(
|
||||
color: textColor,
|
||||
fontSize: bigEmotes ? fontSize * 5 : fontSize,
|
||||
decoration:
|
||||
(event?.redacted ?? false) ? TextDecoration.lineThrough : null,
|
||||
height: 1.3,
|
||||
);
|
||||
}
|
||||
// Pangea#
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ abstract class AppRoutes {
|
|||
// ? TwoColumnLayout(
|
||||
// mainView: ChatList(
|
||||
// activeChat: state.pathParameters['roomid'],
|
||||
// activeSpace: state.uri.queryParameters['spaceId'],
|
||||
// displayNavigationRail:
|
||||
// state.path?.startsWith('/rooms/settings') != true,
|
||||
// ),
|
||||
|
|
@ -292,7 +293,10 @@ abstract class AppRoutes {
|
|||
// Pangea#
|
||||
: ChatList(
|
||||
activeChat: state.pathParameters['roomid'],
|
||||
activeSpaceId: state.pathParameters['spaceid'],
|
||||
// #Pangea
|
||||
// activeSpace: state.uri.queryParameters['spaceId'],
|
||||
activeSpace: state.pathParameters['spaceid'],
|
||||
// Pangea#
|
||||
),
|
||||
),
|
||||
routes: [
|
||||
|
|
|
|||
|
|
@ -1,45 +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';
|
||||
// #Pangea
|
||||
static const String volume = 'pangea.volume';
|
||||
static const String showedActivityMenu =
|
||||
'pangea.showed_activity_menu_tutorial';
|
||||
// Pangea#
|
||||
}
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
|
||||
enum AppSettings<T> {
|
||||
textMessageMaxLength<int>('textMessageMaxLength', 16384),
|
||||
|
|
@ -52,6 +19,9 @@ enum AppSettings<T> {
|
|||
// audioRecordingSamplingRate<int>('audioRecordingSamplingRate', 44100),
|
||||
audioRecordingSamplingRate<int>('audioRecordingSamplingRate', 22050),
|
||||
// Pangea#
|
||||
showNoGoogle<bool>('chat.fluffy.show_no_google', false),
|
||||
unifiedPushRegistered<bool>('chat.fluffy.unifiedpush.registered', false),
|
||||
unifiedPushEndpoint<String>('chat.fluffy.unifiedpush.endpoint', ''),
|
||||
pushNotificationsGatewayUrl<String>(
|
||||
'pushNotificationsGatewayUrl',
|
||||
// #Pangea
|
||||
|
|
@ -65,6 +35,19 @@ enum AppSettings<T> {
|
|||
// 'event_id_only',
|
||||
// ),
|
||||
// Pangea#
|
||||
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',
|
||||
|
|
@ -74,40 +57,95 @@ enum AppSettings<T> {
|
|||
'chat.fluffy.display_chat_details_column',
|
||||
false,
|
||||
),
|
||||
// AppConfig-mirrored settings
|
||||
// #Pangea
|
||||
// applicationName<String>('chat.fluffy.application_name', 'FluffyChat'),
|
||||
// defaultHomeserver<String>('chat.fluffy.default_homeserver', 'matrix.org'),
|
||||
applicationName<String>('chat.fluffy.application_name', 'Pangea Chat'),
|
||||
// Pangea#
|
||||
// colorSchemeSeed stored as ARGB int
|
||||
colorSchemeSeedInt<int>(
|
||||
'chat.fluffy.color_scheme_seed',
|
||||
// #Pangea
|
||||
// 0xFF5625BA,
|
||||
0xFF8560E0,
|
||||
// Pangea#
|
||||
),
|
||||
// #Pangea
|
||||
volume<double>('pangea.value', 1.0),
|
||||
// Pangea#
|
||||
enableSoftLogout<bool>('chat.fluffy.enable_soft_logout', false);
|
||||
|
||||
final String key;
|
||||
final T defaultValue;
|
||||
|
||||
const AppSettings(this.key, this.defaultValue);
|
||||
|
||||
static SharedPreferences get store => _store!;
|
||||
static SharedPreferences? _store;
|
||||
|
||||
static Future<SharedPreferences> init({loadWebConfigFile = true}) async {
|
||||
if (AppSettings._store != null) return AppSettings.store;
|
||||
|
||||
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.name];
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'app_config.dart';
|
||||
|
||||
abstract class FluffyThemes {
|
||||
|
|
@ -49,11 +50,7 @@ abstract class FluffyThemes {
|
|||
]) {
|
||||
final colorScheme = ColorScheme.fromSeed(
|
||||
brightness: brightness,
|
||||
seedColor: seed ??
|
||||
AppConfig.colorSchemeSeed ??
|
||||
Theme.of(context).colorScheme.primary,
|
||||
// primary: AppConfig.primaryColor,
|
||||
// secondary: AppConfig.gold,
|
||||
seedColor: seed ?? Color(AppSettings.colorSchemeSeedInt.value),
|
||||
);
|
||||
final isColumnMode = FluffyThemes.isColumnMode(context);
|
||||
return ThemeData(
|
||||
|
|
|
|||
|
|
@ -3379,6 +3379,39 @@
|
|||
"longPressToRecordVoiceMessage": "Long press to record voice message.",
|
||||
"pause": "Pause",
|
||||
"resume": "Resume",
|
||||
"newSubSpace": "New sub space",
|
||||
"moveToDifferentSpace": "Move to different space",
|
||||
"moveUp": "Move up",
|
||||
"moveDown": "Move down",
|
||||
"removeFromSpaceDescription": "The chat will be removed from the space but still appear in your chat list.",
|
||||
"countChats": "{chats} chats",
|
||||
"@countChats": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
"chats": {
|
||||
"type": "int"
|
||||
}
|
||||
}
|
||||
},
|
||||
"spaceMemberOf": "Space member of {spaces}",
|
||||
"@spaceMemberOf": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
"spaces": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"spaceMemberOfCanKnock": "Space member of {spaces} can knock",
|
||||
"@spaceMemberOfCanKnock": {
|
||||
"type": "String",
|
||||
"placeholders": {
|
||||
"spaces": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"donate": "Donate",
|
||||
"ignore": "Block",
|
||||
"ignoredUsers": "Blocked users",
|
||||
"writeAMessageLangCodes": "Type in {l1} or {l2}...",
|
||||
|
|
@ -3947,6 +3980,9 @@
|
|||
"grammarCopyPOSpropn": "Proper Noun",
|
||||
"grammarCopyPOSnoun": "Noun",
|
||||
"grammarCopyPOSintj": "Interjection",
|
||||
"grammarCopyPOSidiom": "Idiom",
|
||||
"grammarCopyPOSphrasalv": "Phrasal Verb",
|
||||
"grammarCopyPOScompn": "Compound",
|
||||
"grammarCopyPOSx": "Other",
|
||||
"grammarCopyGENDERfem": "Feminine",
|
||||
"grammarCopyPERSON2": "Second Person",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart';
|
||||
|
|
@ -22,8 +21,6 @@ import 'utils/background_push.dart';
|
|||
import 'widgets/fluffy_chat_app.dart';
|
||||
|
||||
void main() async {
|
||||
Logs().i('Welcome to ${AppConfig.applicationName} <3');
|
||||
|
||||
// #Pangea
|
||||
try {
|
||||
await dotenv.load(fileName: ".env");
|
||||
|
|
@ -55,12 +52,14 @@ void main() async {
|
|||
// widget bindings are initialized already.
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final store = await AppSettings.init();
|
||||
Logs().i('Welcome to ${AppSettings.applicationName.value} <3');
|
||||
|
||||
// #Pangea
|
||||
// await vod.init(wasmPath: './assets/assets/vodozemac/');
|
||||
// Pangea#
|
||||
|
||||
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
|
||||
|
|
@ -80,14 +79,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);
|
||||
}
|
||||
|
|
@ -99,7 +98,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);
|
||||
}
|
||||
|
|
@ -152,7 +151,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) {
|
||||
|
|
|
|||
|
|
@ -15,10 +15,8 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:scroll_to_index/scroll_to_index.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.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';
|
||||
|
|
@ -341,7 +339,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) {
|
||||
// #Pangea
|
||||
|
|
@ -394,7 +392,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) {
|
||||
// #Pangea
|
||||
// send();
|
||||
|
|
@ -450,7 +448,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;
|
||||
|
|
@ -588,7 +586,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
|
||||
|
|
@ -596,7 +596,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);
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +774,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
_setReadMarkerFuture = timeline
|
||||
.setReadMarker(
|
||||
eventId: eventId,
|
||||
public: AppConfig.sendPublicReadReceipts,
|
||||
public: AppSettings.sendPublicReadReceipts.value,
|
||||
)
|
||||
.then((_) {
|
||||
_setReadMarkerFuture = null;
|
||||
|
|
@ -938,7 +940,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
// if (sendController.text.trim().isEmpty) return;
|
||||
// Pangea#
|
||||
_storeInputTimeoutTimer?.cancel();
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final prefs = Matrix.of(context).store;
|
||||
prefs.remove('draft_$roomId');
|
||||
var parseCommands = true;
|
||||
|
||||
|
|
@ -1564,7 +1566,9 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
final eventIndex = foundEvent == null
|
||||
? -1
|
||||
: timeline!.events
|
||||
.filterByVisibleInGui(exceptionEventId: eventId)
|
||||
.filterByVisibleInGui(
|
||||
exceptionEventId: eventId,
|
||||
)
|
||||
.indexOf(foundEvent);
|
||||
|
||||
if (eventIndex == -1) {
|
||||
|
|
@ -1884,7 +1888,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);
|
||||
});
|
||||
// #Pangea
|
||||
|
|
@ -1903,7 +1907,7 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
// }
|
||||
// }
|
||||
// Pangea#
|
||||
if (AppConfig.sendTypingNotifications) {
|
||||
if (AppSettings.sendTypingNotifications.value) {
|
||||
typingCoolDown?.cancel();
|
||||
typingCoolDown = Timer(const Duration(seconds: 2), () {
|
||||
typingCoolDown = null;
|
||||
|
|
@ -2392,12 +2396,8 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
inputFocus.unfocus();
|
||||
activityController.toggleShowDropdown();
|
||||
|
||||
if (!AppConfig.showedActivityMenu) {
|
||||
AppConfig.showedActivityMenu = true;
|
||||
Matrix.of(context).store.setBool(
|
||||
SettingKeys.showedActivityMenu,
|
||||
AppConfig.showedActivityMenu,
|
||||
);
|
||||
if (!InstructionsEnum.showedActivityMenu.isToggledOff) {
|
||||
InstructionsEnum.showedActivityMenu.setToggledOff(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2462,7 +2462,6 @@ class ChatController extends State<ChatPageWithRoom>
|
|||
|
||||
void toggleDisplayChatDetailsColumn() async {
|
||||
await AppSettings.displayChatDetailsColumn.setItem(
|
||||
Matrix.of(context).store,
|
||||
!_displayChatDetailsColumn.value,
|
||||
);
|
||||
_displayChatDetailsColumn.value = !_displayChatDetailsColumn.value;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
// import 'package:flutter/material.dart';
|
||||
|
||||
// import 'package:animations/animations.dart';
|
||||
// import 'package:fluffychat/config/app_config.dart';
|
||||
// import 'package:matrix/matrix.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';
|
||||
|
|
@ -7,9 +11,6 @@
|
|||
// import 'package:fluffychat/utils/platform_infos.dart';
|
||||
// import 'package:fluffychat/widgets/avatar.dart';
|
||||
// import 'package:fluffychat/widgets/matrix.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:matrix/matrix.dart';
|
||||
|
||||
// import '../../config/themes.dart';
|
||||
// import 'chat.dart';
|
||||
// import 'input_bar.dart';
|
||||
|
|
@ -296,10 +297,11 @@
|
|||
// 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,
|
||||
|
|
|
|||
|
|
@ -130,7 +130,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(
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class EncryptionButton extends StatelessWidget {
|
|||
.stream
|
||||
.where((s) => s.deviceLists != null),
|
||||
builder: (context, snapshot) {
|
||||
final shouldBeEncrypted = room.joinRules != JoinRules.public;
|
||||
return FutureBuilder<EncryptionHealthState>(
|
||||
future: room.encrypted
|
||||
? room.calcEncryptionHealthState()
|
||||
|
|
@ -46,9 +47,13 @@ class EncryptionButton extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
child: Icon(
|
||||
room.encrypted ? Icons.lock_outlined : Icons.lock_open_outlined,
|
||||
room.encrypted
|
||||
? Icons.lock_outlined
|
||||
: Icons.no_encryption_outlined,
|
||||
size: 20,
|
||||
color: theme.colorScheme.onSurface,
|
||||
color: (shouldBeEncrypted && !room.encrypted)
|
||||
? theme.colorScheme.error
|
||||
: theme.colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
onPressed: () => context.go('/rooms/${room.id}/encryption'),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -5,6 +5,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';
|
||||
|
|
@ -162,14 +163,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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.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/chat.dart';
|
||||
|
|
@ -308,7 +309,7 @@ class Message extends StatelessWidget {
|
|||
child: Icon(Icons.check_outlined),
|
||||
),
|
||||
),
|
||||
direction: AppConfig.swipeRightToLeftToReply
|
||||
direction: AppSettings.swipeRightToLeftToReply.value
|
||||
? SwipeDirection.endToStart
|
||||
: SwipeDirection.startToEnd,
|
||||
onSwipe: (_) => onSwipe(),
|
||||
|
|
@ -350,7 +351,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,
|
||||
),
|
||||
|
|
@ -1137,7 +1138,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/chat.dart';
|
||||
import 'package:fluffychat/pages/chat/events/video_player.dart';
|
||||
|
|
@ -146,7 +147,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:
|
||||
|
|
@ -306,7 +308,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) {
|
||||
|
|
@ -325,14 +327,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
|
||||
// Pangea#
|
||||
? 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';
|
||||
|
|
@ -79,7 +80,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';
|
||||
|
|
@ -148,14 +149,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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
// #Pangea
|
||||
|
|
@ -72,8 +71,6 @@ class RecordingViewModelState extends State<RecordingViewModel> {
|
|||
}
|
||||
if (await AudioRecorder().hasPermission() == false) return;
|
||||
|
||||
final store = Matrix.of(context).store;
|
||||
|
||||
final audioRecorder = _audioRecorder ??= AudioRecorder();
|
||||
setState(() {});
|
||||
|
||||
|
|
@ -109,12 +106,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 ?? '',
|
||||
|
|
|
|||
|
|
@ -27,6 +27,16 @@ class ChatAccessSettingsController extends State<ChatAccessSettings> {
|
|||
bool historyVisibilityLoading = false;
|
||||
bool guestAccessLoading = false;
|
||||
Room get room => Matrix.of(context).client.getRoomById(widget.roomId)!;
|
||||
Set<Room> get knownSpaceParents => {
|
||||
...room.client.rooms.where(
|
||||
(space) =>
|
||||
space.isSpace &&
|
||||
space.spaceChildren.any((child) => child.roomId == room.id),
|
||||
),
|
||||
...room.spaceParents
|
||||
.map((parent) => room.client.getRoomById(parent.roomId ?? ''))
|
||||
.whereType<Room>(),
|
||||
};
|
||||
|
||||
String get roomVersion =>
|
||||
room
|
||||
|
|
@ -45,11 +55,13 @@ class ChatAccessSettingsController extends State<ChatAccessSettings> {
|
|||
// Knock is only supported for rooms up from version 7:
|
||||
if (roomVersionInt != null && roomVersionInt <= 6) {
|
||||
joinRules.remove(JoinRules.knock);
|
||||
joinRules.remove(JoinRules.knockRestricted);
|
||||
}
|
||||
|
||||
// Not yet supported in FluffyChat:
|
||||
joinRules.remove(JoinRules.restricted);
|
||||
joinRules.remove(JoinRules.knockRestricted);
|
||||
if (knownSpaceParents.isEmpty) {
|
||||
joinRules.remove(JoinRules.restricted);
|
||||
joinRules.remove(JoinRules.knockRestricted);
|
||||
}
|
||||
|
||||
// If an unsupported join rule is the current join rule, display it:
|
||||
final currentJoinRule = room.joinRules;
|
||||
|
|
@ -69,7 +81,13 @@ class ChatAccessSettingsController extends State<ChatAccessSettings> {
|
|||
|
||||
try {
|
||||
// #Pangea
|
||||
// await room.setJoinRules(newJoinRules);
|
||||
// await room.setJoinRules(
|
||||
// newJoinRules,
|
||||
// allowConditionRoomId: {JoinRules.restricted, JoinRules.knockRestricted}
|
||||
// .contains(newJoinRules)
|
||||
// ? knownSpaceParents.first.id
|
||||
// : null,
|
||||
// );
|
||||
await room.pangeaSetJoinRules(
|
||||
newJoinRules.toString().replaceAll('JoinRules.', ''),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,10 @@ class ChatAccessSettingsPageView extends StatelessWidget {
|
|||
enabled: !controller.joinRulesLoading &&
|
||||
room.canChangeJoinRules,
|
||||
title: Text(
|
||||
joinRule.localizedString(L10n.of(context)),
|
||||
joinRule.localizedString(
|
||||
L10n.of(context),
|
||||
controller.knownSpaceParents,
|
||||
),
|
||||
),
|
||||
value: joinRule,
|
||||
),
|
||||
|
|
@ -280,7 +283,7 @@ class _AliasListTile extends StatelessWidget {
|
|||
}
|
||||
|
||||
extension JoinRulesDisplayString on JoinRules {
|
||||
String localizedString(L10n l10n) {
|
||||
String localizedString(L10n l10n, Set<Room> spaceParents) {
|
||||
switch (this) {
|
||||
case JoinRules.public:
|
||||
return l10n.anyoneCanJoin;
|
||||
|
|
@ -291,9 +294,17 @@ extension JoinRulesDisplayString on JoinRules {
|
|||
case JoinRules.private:
|
||||
return l10n.noOneCanJoin;
|
||||
case JoinRules.restricted:
|
||||
return l10n.restricted;
|
||||
return l10n.spaceMemberOf(
|
||||
spaceParents
|
||||
.map((space) => space.getLocalizedDisplayname(MatrixLocals(l10n)))
|
||||
.join(', '),
|
||||
);
|
||||
case JoinRules.knockRestricted:
|
||||
return l10n.knockRestricted;
|
||||
return l10n.spaceMemberOfCanKnock(
|
||||
spaceParents
|
||||
.map((space) => space.getLocalizedDisplayname(MatrixLocals(l10n)))
|
||||
.join(', '),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
||||
import 'package:fluffychat/utils/beautify_string_extension.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
|
||||
class ChatEncryptionSettingsView extends StatelessWidget {
|
||||
|
|
@ -58,7 +59,6 @@ class ChatEncryptionSettingsView extends StatelessWidget {
|
|||
size: 128,
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
),
|
||||
const Divider(),
|
||||
if (room.isDirectChat)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
|
|
@ -107,72 +107,73 @@ class ChatEncryptionSettingsView extends StatelessWidget {
|
|||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: deviceKeys.length,
|
||||
itemBuilder: (BuildContext context, int i) =>
|
||||
SwitchListTile(
|
||||
value: !deviceKeys[i].blocked,
|
||||
activeThumbColor: deviceKeys[i].verified
|
||||
? Colors.green
|
||||
: Colors.orange,
|
||||
onChanged: (_) =>
|
||||
controller.toggleDeviceKey(deviceKeys[i]),
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(
|
||||
deviceKeys[i].verified
|
||||
? Icons.verified_outlined
|
||||
: deviceKeys[i].blocked
|
||||
? Icons.block_outlined
|
||||
: Icons.info_outlined,
|
||||
color: deviceKeys[i].verified
|
||||
? Colors.green
|
||||
: deviceKeys[i].blocked
|
||||
? Colors.red
|
||||
: Colors.orange,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
deviceKeys[i].deviceId ??
|
||||
L10n.of(context).unknownDevice,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child: Material(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppConfig.borderRadius,
|
||||
itemBuilder: (BuildContext context, int i) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (i == 0 ||
|
||||
deviceKeys[i].userId !=
|
||||
deviceKeys[i - 1].userId) ...[
|
||||
const Divider(),
|
||||
FutureBuilder(
|
||||
future: room.client
|
||||
.getUserProfile(deviceKeys[i].userId),
|
||||
builder: (context, snapshot) {
|
||||
final displayname =
|
||||
snapshot.data?.displayname ??
|
||||
deviceKeys[i].userId.localpart ??
|
||||
deviceKeys[i].userId;
|
||||
return ListTile(
|
||||
leading: Avatar(
|
||||
name: displayname,
|
||||
mxContent: snapshot.data?.avatarUrl,
|
||||
),
|
||||
side: BorderSide(
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
color: theme.colorScheme.primaryContainer,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Text(
|
||||
deviceKeys[i].userId,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
fontSize: 12,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
title: Text(displayname),
|
||||
subtitle: Text(deviceKeys[i].userId),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Text(
|
||||
deviceKeys[i].ed25519Key?.beautified ??
|
||||
L10n.of(context).unknownEncryptionAlgorithm,
|
||||
style: TextStyle(
|
||||
fontFamily: 'RobotoMono',
|
||||
color: theme.colorScheme.secondary,
|
||||
SwitchListTile(
|
||||
value: !deviceKeys[i].blocked,
|
||||
activeThumbColor: deviceKeys[i].verified
|
||||
? Colors.green
|
||||
: Colors.orange,
|
||||
onChanged: (_) =>
|
||||
controller.toggleDeviceKey(deviceKeys[i]),
|
||||
title: Row(
|
||||
children: [
|
||||
Text(
|
||||
deviceKeys[i].verified
|
||||
? L10n.of(context).verified
|
||||
: deviceKeys[i].blocked
|
||||
? L10n.of(context).blocked
|
||||
: L10n.of(context).unverified,
|
||||
style: TextStyle(
|
||||
color: deviceKeys[i].verified
|
||||
? Colors.green
|
||||
: deviceKeys[i].blocked
|
||||
? Colors.red
|
||||
: Colors.orange,
|
||||
),
|
||||
),
|
||||
const Text(' | ID: '),
|
||||
Text(
|
||||
deviceKeys[i].deviceId ??
|
||||
L10n.of(context).unknownDevice,
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Text(
|
||||
deviceKeys[i].ed25519Key?.beautified ??
|
||||
L10n.of(context).unknownEncryptionAlgorithm,
|
||||
style: TextStyle(
|
||||
fontFamily: 'RobotoMono',
|
||||
color: theme.colorScheme.secondary,
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,7 +11,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/pangea/chat_list/utils/app_version_util.dart';
|
||||
|
|
@ -83,17 +82,13 @@ extension LocalizedActiveFilter on ActiveFilter {
|
|||
class ChatList extends StatefulWidget {
|
||||
static BuildContext? contextForVoip;
|
||||
final String? activeChat;
|
||||
// #Pangea
|
||||
final String? activeSpaceId;
|
||||
// Pangea#
|
||||
final String? activeSpace;
|
||||
final bool displayNavigationRail;
|
||||
|
||||
const ChatList({
|
||||
super.key,
|
||||
required this.activeChat,
|
||||
// #Pangea
|
||||
this.activeSpaceId,
|
||||
// Pangea#
|
||||
this.activeSpace,
|
||||
this.displayNavigationRail = false,
|
||||
});
|
||||
|
||||
|
|
@ -111,15 +106,10 @@ class ChatListController extends State<ChatList>
|
|||
// StreamSubscription? _intentUriStreamSubscription;
|
||||
// Pangea#
|
||||
|
||||
// #Pangea
|
||||
// ActiveFilter activeFilter = AppConfig.separateChatTypes
|
||||
// ? ActiveFilter.messages
|
||||
// : ActiveFilter.allChats;
|
||||
ActiveFilter activeFilter = ActiveFilter.allChats;
|
||||
// Pangea#
|
||||
late ActiveFilter activeFilter;
|
||||
|
||||
// #Pangea
|
||||
String? get activeSpaceId => widget.activeSpaceId;
|
||||
String? get activeSpaceId => widget.activeSpace;
|
||||
// String? _activeSpaceId;
|
||||
// String? get activeSpaceId => _activeSpaceId;
|
||||
|
||||
|
|
@ -535,7 +525,16 @@ class ChatListController extends State<ChatList>
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
// #Pangea
|
||||
// activeFilter = AppSettings.separateChatTypes.value
|
||||
// ? ActiveFilter.messages
|
||||
// : ActiveFilter.allChats;
|
||||
activeFilter = ActiveFilter.allChats;
|
||||
// Pangea#
|
||||
_initReceiveSharingIntent();
|
||||
// #Pangea
|
||||
// _activeSpaceId = widget.activeSpace;
|
||||
// Pangea#
|
||||
|
||||
scrollController.addListener(_onScroll);
|
||||
_waitForFirstSync();
|
||||
|
|
@ -993,8 +992,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(() {});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,10 +42,7 @@ class ChatListViewBody extends StatelessWidget {
|
|||
// spaceId: activeSpace,
|
||||
// onBack: controller.clearActiveSpace,
|
||||
// onChatTab: (room) => controller.onChatTap(room),
|
||||
// onChatContext: (room, context) =>
|
||||
// controller.chatContextAction(room, context),
|
||||
// activeChat: controller.activeChat,
|
||||
// toParentSpace: controller.setActiveSpace,
|
||||
// );
|
||||
return CourseChats(
|
||||
activeSpace,
|
||||
|
|
@ -108,8 +105,8 @@ class ChatListViewBody extends StatelessWidget {
|
|||
// ),
|
||||
// PublicRoomsHorizontalList(publicRooms: publicRooms),
|
||||
// SearchTitle(
|
||||
// title: L10n.of(context).publicSpaces,
|
||||
// icon: const Icon(Icons.workspaces_outlined),
|
||||
// title: L10n.of(context).publicSpaces,
|
||||
// icon: const Icon(Icons.workspaces_outlined),
|
||||
// ),
|
||||
// PublicRoomsHorizontalList(publicRooms: publicSpaces),
|
||||
// SearchTitle(
|
||||
|
|
@ -127,27 +124,28 @@ class ChatListViewBody extends StatelessWidget {
|
|||
// curve: FluffyThemes.animationCurve,
|
||||
// child: userSearchResult == null
|
||||
// ? null
|
||||
// : ListView.builder(
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// itemCount: userSearchResult.results.length,
|
||||
// itemBuilder: (context, i) => _SearchItem(
|
||||
// title:
|
||||
// userSearchResult.results[i].displayName ??
|
||||
// userSearchResult
|
||||
// .results[i].userId.localpart ??
|
||||
// L10n.of(context).unknownDevice,
|
||||
// avatar: userSearchResult.results[i].avatarUrl,
|
||||
// onPressed: () => UserDialog.show(
|
||||
// context: context,
|
||||
// profile: userSearchResult.results[i],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Pangea#
|
||||
// : ListView.builder(
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// itemCount: userSearchResult.results.length,
|
||||
// itemBuilder: (context, i) => _SearchItem(
|
||||
// title:
|
||||
// userSearchResult.results[i].displayName ??
|
||||
// userSearchResult
|
||||
// .results[i].userId.localpart ??
|
||||
// L10n.of(context).unknownDevice,
|
||||
// avatar: userSearchResult.results[i].avatarUrl,
|
||||
// onPressed: () => UserDialog.show(
|
||||
// context: context,
|
||||
// profile: userSearchResult.results[i],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Pangea#
|
||||
],
|
||||
// #Pangea
|
||||
// if (!controller.isSearchMode && AppConfig.showPresences)
|
||||
// if (!controller.isSearchMode &&
|
||||
// AppSettings.showPresences.value)
|
||||
// GestureDetector(
|
||||
// onLongPress: () => controller.dismissStatusList(),
|
||||
// child: StatusMessageList(
|
||||
|
|
@ -184,14 +182,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,
|
||||
// ]
|
||||
|
|
@ -217,24 +215,6 @@ class ChatListViewBody extends StatelessWidget {
|
|||
// title: L10n.of(context).chats,
|
||||
// icon: const Icon(Icons.forum_outlined),
|
||||
// ),
|
||||
if (controller.isSearchMode &&
|
||||
rooms
|
||||
.where(
|
||||
(room) => room
|
||||
.getLocalizedDisplayname(
|
||||
MatrixLocals(L10n.of(context)),
|
||||
)
|
||||
.toLowerCase()
|
||||
.contains(filter),
|
||||
)
|
||||
.isEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.all(16.0),
|
||||
child: Text(
|
||||
L10n.of(context).emptyChatSearch,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
// if (client.prevBatch != null &&
|
||||
// rooms.isEmpty &&
|
||||
// !controller.isSearchMode) ...[
|
||||
|
|
@ -268,7 +248,7 @@ class ChatListViewBody extends StatelessWidget {
|
|||
// padding: const EdgeInsets.all(16.0),
|
||||
// child: Text(
|
||||
// client.rooms.isEmpty
|
||||
// ? L10n.of(context).noChatsFoundHereYet
|
||||
// ? L10n.of(context).noChatsFoundHere
|
||||
// : L10n.of(context).noMoreChatsFound,
|
||||
// textAlign: TextAlign.center,
|
||||
// style: TextStyle(
|
||||
|
|
@ -280,6 +260,24 @@ class ChatListViewBody extends StatelessWidget {
|
|||
// ],
|
||||
// ),
|
||||
// ],
|
||||
if (controller.isSearchMode &&
|
||||
rooms
|
||||
.where(
|
||||
(room) => room
|
||||
.getLocalizedDisplayname(
|
||||
MatrixLocals(L10n.of(context)),
|
||||
)
|
||||
.toLowerCase()
|
||||
.contains(filter),
|
||||
)
|
||||
.isEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsetsGeometry.all(16.0),
|
||||
child: Text(
|
||||
L10n.of(context).emptyChatSearch,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
// Pangea#
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:matrix/matrix.dart';
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pages/chat_list/unread_bubble.dart';
|
||||
import 'package:fluffychat/pangea/chat_list/utils/get_chat_list_item_subtitle.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
|
|
@ -54,11 +55,6 @@ class ChatListItem extends StatelessWidget {
|
|||
final unread = room.isUnread;
|
||||
final directChatMatrixId = room.directChatMatrixID;
|
||||
final isDirectChat = directChatMatrixId != null;
|
||||
final unreadBubbleSize = unread || room.hasNewMessages
|
||||
? room.notificationCount > 0
|
||||
? 20.0
|
||||
: 14.0
|
||||
: 0.0;
|
||||
final hasNotifications = room.notificationCount > 0;
|
||||
final backgroundColor =
|
||||
activeChat ? theme.colorScheme.secondaryContainer : null;
|
||||
|
|
@ -248,7 +244,7 @@ class ChatListItem extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
if (typingText.isEmpty &&
|
||||
ownMessage &&
|
||||
room.lastEvent!.status.isSending) ...[
|
||||
room.lastEvent?.status.isSending == true) ...[
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
|
|
@ -272,13 +268,11 @@ class ChatListItem extends StatelessWidget {
|
|||
Expanded(
|
||||
child: room.isSpace && room.membership == Membership.join
|
||||
? Text(
|
||||
L10n.of(context).countChatsAndCountParticipants(
|
||||
// #Pangea
|
||||
// room.spaceChildren.length,
|
||||
room.spaceChildCount,
|
||||
// Pangea#
|
||||
(room.summary.mJoinedMemberCount ?? 1),
|
||||
),
|
||||
// #Pangea
|
||||
// L10n.of(context)
|
||||
// .countChats(room.spaceChildren.length),
|
||||
L10n.of(context).countChats(room.spaceChildCount),
|
||||
// Pangea#
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
)
|
||||
: typingText.isNotEmpty
|
||||
|
|
@ -367,41 +361,7 @@ class ChatListItem extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
AnimatedContainer(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7),
|
||||
height: unreadBubbleSize,
|
||||
width: !hasNotifications && !unread && !room.hasNewMessages
|
||||
? 0
|
||||
: (unreadBubbleSize - 9) *
|
||||
room.notificationCount.toString().length +
|
||||
9,
|
||||
decoration: BoxDecoration(
|
||||
color: room.highlightCount > 0
|
||||
? theme.colorScheme.error
|
||||
: hasNotifications || room.markedUnread
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
),
|
||||
child: hasNotifications
|
||||
? Text(
|
||||
room.notificationCount.toString(),
|
||||
style: TextStyle(
|
||||
color: room.highlightCount > 0
|
||||
? theme.colorScheme.onError
|
||||
: hasNotifications
|
||||
? theme.colorScheme.onPrimary
|
||||
: theme.colorScheme.onPrimaryContainer,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
UnreadBubble(room: room),
|
||||
],
|
||||
),
|
||||
onTap: onTap,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class ChatListView extends StatelessWidget {
|
|||
children: [
|
||||
// #Pangea
|
||||
// if (FluffyThemes.isColumnMode(context) ||
|
||||
// AppConfig.displayNavigationRail) ...[
|
||||
// AppSettings.displayNavigationRail.value) ...[
|
||||
// SpacesNavigationRail(
|
||||
// activeSpaceId: controller.activeSpaceId,
|
||||
// onGoToChats: controller.clearActiveSpace,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// #Pangea
|
||||
// import 'package:flutter/material.dart';
|
||||
|
||||
// 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/themes.dart';
|
||||
// import 'package:fluffychat/l10n/l10n.dart';
|
||||
// import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
|
|
@ -68,6 +69,17 @@
|
|||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// if (Matrix.of(context).backgroundPush?.firebaseEnabled != true)
|
||||
// PopupMenuItem(
|
||||
// value: SettingsAction.support,
|
||||
// child: Row(
|
||||
// children: [
|
||||
// const Icon(Icons.favorite, color: Colors.red),
|
||||
// const SizedBox(width: 18),
|
||||
// Text(L10n.of(context).donate),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// PopupMenuItem(
|
||||
// value: SettingsAction.settings,
|
||||
// child: Row(
|
||||
|
|
@ -208,6 +220,9 @@
|
|||
// case SettingsAction.invite:
|
||||
// FluffyShare.shareInviteLink(context);
|
||||
// break;
|
||||
// case SettingsAction.support:
|
||||
// launchUrlString(AppConfig.donationUrl);
|
||||
// break;
|
||||
// case SettingsAction.settings:
|
||||
// context.go('/rooms/settings');
|
||||
// break;
|
||||
|
|
@ -227,7 +242,7 @@
|
|||
// newGroup,
|
||||
// setStatus,
|
||||
// invite,
|
||||
// support,
|
||||
// settings,
|
||||
// archive,
|
||||
// }
|
||||
// Pangea#
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
|
@ -8,26 +10,35 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
|
||||
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
||||
import 'package:fluffychat/pages/chat_list/unread_bubble.dart';
|
||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
|
||||
import 'package:fluffychat/utils/stream_extension.dart';
|
||||
import 'package:fluffychat/utils/string_color.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/public_room_dialog.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_modal_action_popup.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart';
|
||||
import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart';
|
||||
import 'package:fluffychat/widgets/avatar.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
import 'package:fluffychat/widgets/hover_builder.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
enum AddRoomType { chat, subspace }
|
||||
|
||||
enum SpaceChildAction { edit, moveToSpace, removeFromSpace }
|
||||
|
||||
enum SpaceActions {
|
||||
settings,
|
||||
invite,
|
||||
members,
|
||||
leave,
|
||||
}
|
||||
|
||||
class SpaceView extends StatefulWidget {
|
||||
final String spaceId;
|
||||
final void Function() onBack;
|
||||
final void Function(String spaceId) toParentSpace;
|
||||
final void Function(Room room) onChatTab;
|
||||
final void Function(Room room, BuildContext context) onChatContext;
|
||||
final String? activeChat;
|
||||
|
||||
const SpaceView({
|
||||
|
|
@ -35,8 +46,6 @@ class SpaceView extends StatefulWidget {
|
|||
required this.onBack,
|
||||
required this.onChatTab,
|
||||
required this.activeChat,
|
||||
required this.toParentSpace,
|
||||
required this.onChatContext,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -58,9 +67,28 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
}
|
||||
|
||||
void _loadHierarchy() async {
|
||||
final room = Matrix.of(context).client.getRoomById(widget.spaceId);
|
||||
final matrix = Matrix.of(context);
|
||||
final room = matrix.client.getRoomById(widget.spaceId);
|
||||
if (room == null) return;
|
||||
|
||||
final cacheKey = 'spaces_history_cache${room.id}';
|
||||
if (_discoveredChildren.isEmpty) {
|
||||
final cachedChildren = matrix.store.getStringList(cacheKey);
|
||||
if (cachedChildren != null) {
|
||||
try {
|
||||
_discoveredChildren.addAll(
|
||||
cachedChildren.map(
|
||||
(jsonString) =>
|
||||
SpaceRoomsChunk$2.fromJson(jsonDecode(jsonString)),
|
||||
),
|
||||
);
|
||||
} catch (e, s) {
|
||||
Logs().e('Unable to json decode spaces hierarchy cache!', e, s);
|
||||
matrix.store.remove(cacheKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
|
@ -74,16 +102,25 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
if (_nextBatch == null) _discoveredChildren.clear();
|
||||
_nextBatch = hierarchy.nextBatch;
|
||||
if (hierarchy.nextBatch == null) {
|
||||
_noMoreRooms = true;
|
||||
}
|
||||
_discoveredChildren.addAll(
|
||||
hierarchy.rooms
|
||||
.where((c) => room.client.getRoomById(c.roomId) == null),
|
||||
hierarchy.rooms.where((room) => room.roomId != widget.spaceId),
|
||||
);
|
||||
_isLoading = false;
|
||||
});
|
||||
|
||||
if (_nextBatch == null) {
|
||||
matrix.store.setStringList(
|
||||
cacheKey,
|
||||
_discoveredChildren
|
||||
.map((child) => jsonEncode(child.toJson()))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logs().w('Unable to load hierarchy', e, s);
|
||||
if (!mounted) return;
|
||||
|
|
@ -111,9 +148,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
),
|
||||
);
|
||||
if (mounted && joined == true) {
|
||||
setState(() {
|
||||
_discoveredChildren.remove(item);
|
||||
});
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +164,10 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
await space?.postLoad();
|
||||
context.push('/rooms/${widget.spaceId}/invite');
|
||||
break;
|
||||
case SpaceActions.members:
|
||||
await space?.postLoad();
|
||||
context.push('/rooms/${widget.spaceId}/details/members');
|
||||
break;
|
||||
case SpaceActions.leave:
|
||||
final confirmed = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
|
|
@ -151,27 +190,11 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
}
|
||||
}
|
||||
|
||||
void _addChatOrSubspace() async {
|
||||
final roomType = await showModalActionPopup(
|
||||
context: context,
|
||||
title: L10n.of(context).addChatOrSubSpace,
|
||||
actions: [
|
||||
AdaptiveModalAction(
|
||||
value: AddRoomType.subspace,
|
||||
label: L10n.of(context).createNewSpace,
|
||||
),
|
||||
AdaptiveModalAction(
|
||||
value: AddRoomType.chat,
|
||||
label: L10n.of(context).createGroup,
|
||||
),
|
||||
],
|
||||
);
|
||||
if (roomType == null) return;
|
||||
|
||||
void _addChatOrSubspace(AddRoomType roomType) async {
|
||||
final names = await showTextInputDialog(
|
||||
context: context,
|
||||
title: roomType == AddRoomType.subspace
|
||||
? L10n.of(context).createNewSpace
|
||||
? L10n.of(context).newSubSpace
|
||||
: L10n.of(context).createGroup,
|
||||
hintText: roomType == AddRoomType.subspace
|
||||
? L10n.of(context).spaceName
|
||||
|
|
@ -196,29 +219,169 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
late final String roomId;
|
||||
final activeSpace = client.getRoomById(widget.spaceId)!;
|
||||
await activeSpace.postLoad();
|
||||
final isPublicSpace = activeSpace.joinRules == JoinRules.public;
|
||||
|
||||
if (roomType == AddRoomType.subspace) {
|
||||
roomId = await client.createSpace(
|
||||
name: names,
|
||||
visibility: activeSpace.joinRules == JoinRules.public
|
||||
? sdk.Visibility.public
|
||||
: sdk.Visibility.private,
|
||||
visibility:
|
||||
isPublicSpace ? sdk.Visibility.public : sdk.Visibility.private,
|
||||
);
|
||||
} else {
|
||||
roomId = await client.createGroupChat(
|
||||
enableEncryption: !isPublicSpace,
|
||||
groupName: names,
|
||||
preset: activeSpace.joinRules == JoinRules.public
|
||||
preset: isPublicSpace
|
||||
? CreateRoomPreset.publicChat
|
||||
: CreateRoomPreset.privateChat,
|
||||
visibility: activeSpace.joinRules == JoinRules.public
|
||||
? sdk.Visibility.public
|
||||
: sdk.Visibility.private,
|
||||
visibility:
|
||||
isPublicSpace ? sdk.Visibility.public : sdk.Visibility.private,
|
||||
initialState: isPublicSpace
|
||||
? null
|
||||
: [
|
||||
StateEvent(
|
||||
content: {
|
||||
'join_rule': 'restricted',
|
||||
'allow': [
|
||||
{
|
||||
'room_id': widget.spaceId,
|
||||
'type': 'm.room_membership',
|
||||
},
|
||||
],
|
||||
},
|
||||
type: EventTypes.RoomJoinRules,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
await activeSpace.setSpaceChild(roomId);
|
||||
},
|
||||
);
|
||||
if (result.error != null) return;
|
||||
setState(() {
|
||||
_nextBatch = null;
|
||||
_discoveredChildren.clear();
|
||||
});
|
||||
_loadHierarchy();
|
||||
}
|
||||
|
||||
void _showSpaceChildEditMenu(BuildContext posContext, String roomId) async {
|
||||
final overlay =
|
||||
Overlay.of(posContext).context.findRenderObject() as RenderBox;
|
||||
|
||||
final button = posContext.findRenderObject() as RenderBox;
|
||||
|
||||
final position = RelativeRect.fromRect(
|
||||
Rect.fromPoints(
|
||||
button.localToGlobal(const Offset(0, -65), ancestor: overlay),
|
||||
button.localToGlobal(
|
||||
button.size.bottomRight(Offset.zero) + const Offset(-50, 0),
|
||||
ancestor: overlay,
|
||||
),
|
||||
),
|
||||
Offset.zero & overlay.size,
|
||||
);
|
||||
|
||||
final action = await showMenu<SpaceChildAction>(
|
||||
context: posContext,
|
||||
position: position,
|
||||
items: [
|
||||
PopupMenuItem(
|
||||
value: SpaceChildAction.moveToSpace,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.move_down_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).moveToDifferentSpace),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: SpaceChildAction.edit,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.edit_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).edit),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: SpaceChildAction.removeFromSpace,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.group_remove_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).removeFromSpace),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
if (action == null) return;
|
||||
if (!mounted) return;
|
||||
final space = Matrix.of(context).client.getRoomById(widget.spaceId);
|
||||
if (space == null) return;
|
||||
switch (action) {
|
||||
case SpaceChildAction.edit:
|
||||
context.push('/rooms/${widget.spaceId}/details');
|
||||
case SpaceChildAction.moveToSpace:
|
||||
final spacesWithPowerLevels = space.client.rooms
|
||||
.where(
|
||||
(room) =>
|
||||
room.isSpace &&
|
||||
room.canChangeStateEvent(EventTypes.SpaceChild) &&
|
||||
room.id != widget.spaceId,
|
||||
)
|
||||
.toList();
|
||||
final newSpace = await showModalActionPopup(
|
||||
context: context,
|
||||
title: L10n.of(context).space,
|
||||
actions: spacesWithPowerLevels
|
||||
.map(
|
||||
(space) => AdaptiveModalAction(
|
||||
value: space,
|
||||
label: space
|
||||
.getLocalizedDisplayname(MatrixLocals(L10n.of(context))),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
if (newSpace == null) return;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
await newSpace.setSpaceChild(newSpace.id);
|
||||
await space.removeSpaceChild(roomId);
|
||||
},
|
||||
);
|
||||
if (result.isError) return;
|
||||
if (!mounted) return;
|
||||
_nextBatch = null;
|
||||
_loadHierarchy();
|
||||
return;
|
||||
|
||||
case SpaceChildAction.removeFromSpace:
|
||||
final consent = await showOkCancelAlertDialog(
|
||||
context: context,
|
||||
title: L10n.of(context).removeFromSpace,
|
||||
message: L10n.of(context).removeFromSpaceDescription,
|
||||
);
|
||||
if (consent != OkCancelResult.ok) return;
|
||||
if (!mounted) return;
|
||||
final result = await showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () => space.removeSpaceChild(roomId),
|
||||
);
|
||||
if (result.isError) return;
|
||||
if (!mounted) return;
|
||||
_nextBatch = null;
|
||||
_loadHierarchy();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -228,6 +391,11 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
final room = Matrix.of(context).client.getRoomById(widget.spaceId);
|
||||
final displayname =
|
||||
room?.getLocalizedDisplayname() ?? L10n.of(context).nothingFound;
|
||||
const avatarSize = Avatar.defaultSize / 1.5;
|
||||
final isAdmin = room?.canChangeStateEvent(
|
||||
EventTypes.SpaceChild,
|
||||
) ==
|
||||
true;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: FluffyThemes.isColumnMode(context)
|
||||
|
|
@ -242,6 +410,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
title: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: Avatar(
|
||||
size: avatarSize,
|
||||
mxContent: room?.avatar,
|
||||
name: displayname,
|
||||
border: BorderSide(width: 1, color: theme.dividerColor),
|
||||
|
|
@ -252,18 +421,38 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
subtitle: room == null
|
||||
? null
|
||||
: Text(
|
||||
L10n.of(context).countChatsAndCountParticipants(
|
||||
room.spaceChildren.length,
|
||||
room.summary.mJoinedMemberCount ?? 1,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (isAdmin)
|
||||
PopupMenuButton<AddRoomType>(
|
||||
icon: const Icon(Icons.add_outlined),
|
||||
onSelected: _addChatOrSubspace,
|
||||
tooltip: L10n.of(context).addChatOrSubSpace,
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
value: AddRoomType.chat,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.group_add_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).newGroup),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: AddRoomType.subspace,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.workspaces_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(L10n.of(context).newSubSpace),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
PopupMenuButton<SpaceActions>(
|
||||
useRootNavigator: true,
|
||||
onSelected: _onSpaceAction,
|
||||
|
|
@ -290,6 +479,21 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: SpaceActions.members,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.group_outlined),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
L10n.of(context).countParticipants(
|
||||
room?.summary.mJoinedMemberCount ?? 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: SpaceActions.leave,
|
||||
child: Row(
|
||||
|
|
@ -305,16 +509,6 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: room?.canChangeStateEvent(
|
||||
EventTypes.SpaceChild,
|
||||
) ==
|
||||
true
|
||||
? FloatingActionButton.extended(
|
||||
onPressed: _addChatOrSubspace,
|
||||
label: Text(L10n.of(context).group),
|
||||
icon: const Icon(Icons.group_add_outlined),
|
||||
)
|
||||
: null,
|
||||
body: room == null
|
||||
? const Center(
|
||||
child: Icon(
|
||||
|
|
@ -327,29 +521,11 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
.where((s) => s.hasRoomUpdate)
|
||||
.rateLimit(const Duration(seconds: 1)),
|
||||
builder: (context, snapshot) {
|
||||
final childrenIds = room.spaceChildren
|
||||
.map((c) => c.roomId)
|
||||
.whereType<String>()
|
||||
.toSet();
|
||||
|
||||
final joinedRooms = room.client.rooms
|
||||
.where((room) => childrenIds.remove(room.id))
|
||||
.toList();
|
||||
|
||||
final joinedParents = room.spaceParents
|
||||
.map((parent) {
|
||||
final roomId = parent.roomId;
|
||||
if (roomId == null) return null;
|
||||
return room.client.getRoomById(roomId);
|
||||
})
|
||||
.whereType<Room>()
|
||||
.toList();
|
||||
final filter = _filterController.text.trim().toLowerCase();
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
floating: true,
|
||||
toolbarHeight: 72,
|
||||
scrolledUnderElevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
automaticallyImplyLeading: false,
|
||||
|
|
@ -359,11 +535,6 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
textInputAction: TextInputAction.search,
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: theme.colorScheme.secondaryContainer,
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
hintText: L10n.of(context).search,
|
||||
hintStyle: TextStyle(
|
||||
|
|
@ -382,83 +553,11 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
),
|
||||
),
|
||||
SliverList.builder(
|
||||
itemCount: joinedParents.length,
|
||||
itemCount: _discoveredChildren.length + 1,
|
||||
itemBuilder: (context, i) {
|
||||
final displayname =
|
||||
joinedParents[i].getLocalizedDisplayname();
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 1,
|
||||
),
|
||||
child: Material(
|
||||
borderRadius:
|
||||
BorderRadius.circular(AppConfig.borderRadius),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: ListTile(
|
||||
minVerticalPadding: 0,
|
||||
leading: Icon(
|
||||
Icons.adaptive.arrow_back_outlined,
|
||||
size: 16,
|
||||
),
|
||||
title: Row(
|
||||
children: [
|
||||
Avatar(
|
||||
mxContent: joinedParents[i].avatar,
|
||||
name: displayname,
|
||||
size: Avatar.defaultSize / 2,
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppConfig.borderRadius / 4,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(child: Text(displayname)),
|
||||
],
|
||||
),
|
||||
onTap: () =>
|
||||
widget.toParentSpace(joinedParents[i].id),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SliverList.builder(
|
||||
itemCount: joinedRooms.length,
|
||||
itemBuilder: (context, i) {
|
||||
final joinedRoom = joinedRooms[i];
|
||||
return ChatListItem(
|
||||
joinedRoom,
|
||||
filter: filter,
|
||||
onTap: () => widget.onChatTab(joinedRoom),
|
||||
onLongPress: (context) => widget.onChatContext(
|
||||
joinedRoom,
|
||||
context,
|
||||
),
|
||||
activeChat: widget.activeChat == joinedRoom.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
SliverList.builder(
|
||||
itemCount: _discoveredChildren.length + 2,
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return SearchTitle(
|
||||
title: L10n.of(context).discover,
|
||||
icon: const Icon(Icons.explore_outlined),
|
||||
);
|
||||
}
|
||||
i--;
|
||||
if (i == _discoveredChildren.length) {
|
||||
if (_noMoreRooms) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
L10n.of(context).noMoreChatsFound,
|
||||
style: const TextStyle(fontSize: 13),
|
||||
),
|
||||
),
|
||||
);
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
|
|
@ -468,11 +567,7 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
child: TextButton(
|
||||
onPressed: _isLoading ? null : _loadHierarchy,
|
||||
child: _isLoading
|
||||
? LinearProgressIndicator(
|
||||
borderRadius: BorderRadius.circular(
|
||||
AppConfig.borderRadius,
|
||||
),
|
||||
)
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: Text(L10n.of(context).loadMore),
|
||||
),
|
||||
);
|
||||
|
|
@ -484,6 +579,10 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
if (!displayname.toLowerCase().contains(filter)) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
var joinedRoom = room.client.getRoomById(item.roomId);
|
||||
if (joinedRoom?.membership == Membership.leave) {
|
||||
joinedRoom = null;
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
|
|
@ -493,51 +592,83 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
borderRadius:
|
||||
BorderRadius.circular(AppConfig.borderRadius),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: ListTile(
|
||||
visualDensity:
|
||||
const VisualDensity(vertical: -0.5),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
onTap: () => _joinChildRoom(item),
|
||||
leading: Avatar(
|
||||
mxContent: item.avatarUrl,
|
||||
name: displayname,
|
||||
borderRadius: item.roomType == 'm.space'
|
||||
? BorderRadius.circular(
|
||||
AppConfig.borderRadius / 2,
|
||||
)
|
||||
color: joinedRoom != null &&
|
||||
widget.activeChat == joinedRoom.id
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: Colors.transparent,
|
||||
child: HoverBuilder(
|
||||
builder: (context, hovered) => ListTile(
|
||||
visualDensity:
|
||||
const VisualDensity(vertical: -0.5),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 8),
|
||||
onTap: joinedRoom != null
|
||||
? () => widget.onChatTab(joinedRoom!)
|
||||
: () => _joinChildRoom(item),
|
||||
onLongPress: isAdmin
|
||||
? () => _showSpaceChildEditMenu(
|
||||
context,
|
||||
item.roomId,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
title: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
displayname,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
leading: hovered && isAdmin
|
||||
? SizedBox.square(
|
||||
dimension: avatarSize,
|
||||
child: IconButton(
|
||||
splashRadius: avatarSize,
|
||||
iconSize: 14,
|
||||
style: IconButton.styleFrom(
|
||||
foregroundColor: theme.colorScheme
|
||||
.onTertiaryContainer,
|
||||
backgroundColor: theme
|
||||
.colorScheme.tertiaryContainer,
|
||||
),
|
||||
onPressed: () =>
|
||||
_showSpaceChildEditMenu(
|
||||
context,
|
||||
item.roomId,
|
||||
),
|
||||
icon: const Icon(Icons.edit_outlined),
|
||||
),
|
||||
)
|
||||
: Avatar(
|
||||
size: avatarSize,
|
||||
mxContent: item.avatarUrl,
|
||||
name: '#',
|
||||
backgroundColor:
|
||||
theme.colorScheme.surfaceContainer,
|
||||
textColor: item.name?.darkColor ??
|
||||
theme.colorScheme.onSurface,
|
||||
border: item.roomType == 'm.space'
|
||||
? BorderSide(
|
||||
color: theme.colorScheme
|
||||
.surfaceContainerHighest,
|
||||
)
|
||||
: null,
|
||||
borderRadius: item.roomType == 'm.space'
|
||||
? BorderRadius.circular(
|
||||
AppConfig.borderRadius / 4,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
title: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Opacity(
|
||||
opacity: joinedRoom == null ? 0.5 : 1,
|
||||
child: Text(
|
||||
displayname,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
item.numJoinedMembers.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.textTheme.bodyMedium!.color,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
const Icon(
|
||||
Icons.people_outlined,
|
||||
size: 14,
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Text(
|
||||
item.topic ??
|
||||
L10n.of(context).countParticipants(
|
||||
item.numJoinedMembers,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
if (joinedRoom != null)
|
||||
UnreadBubble(room: joinedRoom)
|
||||
else
|
||||
const Icon(Icons.chevron_right_outlined),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -552,9 +683,3 @@ class _SpaceViewState extends State<SpaceView> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum SpaceActions {
|
||||
settings,
|
||||
invite,
|
||||
leave,
|
||||
}
|
||||
|
|
|
|||
56
lib/pages/chat_list/unread_bubble.dart
Normal file
56
lib/pages/chat_list/unread_bubble.dart
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
|
||||
class UnreadBubble extends StatelessWidget {
|
||||
final Room room;
|
||||
const UnreadBubble({required this.room, super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final unread = room.isUnread;
|
||||
final hasNotifications = room.notificationCount > 0;
|
||||
final unreadBubbleSize = unread || room.hasNewMessages
|
||||
? room.notificationCount > 0
|
||||
? 20.0
|
||||
: 14.0
|
||||
: 0.0;
|
||||
return AnimatedContainer(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
curve: FluffyThemes.animationCurve,
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 7),
|
||||
height: unreadBubbleSize,
|
||||
width: !hasNotifications && !unread && !room.hasNewMessages
|
||||
? 0
|
||||
: (unreadBubbleSize - 9) * room.notificationCount.toString().length +
|
||||
9,
|
||||
decoration: BoxDecoration(
|
||||
color: room.highlightCount > 0
|
||||
? theme.colorScheme.error
|
||||
: hasNotifications || room.markedUnread
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
),
|
||||
child: hasNotifications
|
||||
? Text(
|
||||
room.notificationCount.toString(),
|
||||
style: TextStyle(
|
||||
color: room.highlightCount > 0
|
||||
? theme.colorScheme.onError
|
||||
: hasNotifications
|
||||
? theme.colorScheme.onPrimary
|
||||
: theme.colorScheme.onPrimaryContainer,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:universal_html/html.dart' as html;
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
|
|
@ -34,7 +34,10 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||
bool isLoading = false;
|
||||
|
||||
final TextEditingController homeserverController = TextEditingController(
|
||||
// #Pangea
|
||||
// text: AppSettings.defaultHomeserver.value,
|
||||
text: AppConfig.defaultHomeserver,
|
||||
// Pangea#
|
||||
);
|
||||
|
||||
String? error;
|
||||
|
|
@ -211,7 +214,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||
case MoreLoginActions.importBackup:
|
||||
restoreBackup();
|
||||
case MoreLoginActions.privacy:
|
||||
launchUrlString(AppConfig.privacyUrl);
|
||||
launchUrl(AppConfig.privacyUrl);
|
||||
case MoreLoginActions.about:
|
||||
PlatformInfos.showDialog(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,9 @@ class SettingsView extends StatelessWidget {
|
|||
displayname,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton.icon(
|
||||
|
|
@ -380,7 +382,7 @@ class SettingsView extends StatelessWidget {
|
|||
// ListTile(
|
||||
// leading: const Icon(Icons.privacy_tip_outlined),
|
||||
// title: Text(L10n.of(context).privacy),
|
||||
// onTap: () => launchUrlString(AppConfig.privacyUrl),
|
||||
// onTap: () => launchUrl(AppConfig.privacyUrl),
|
||||
// ),
|
||||
// ListTile(
|
||||
// leading: const Icon(Icons.info_outline_rounded),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ 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';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:fluffychat/widgets/settings_switch_list_tile.dart';
|
||||
import 'settings_chat.dart';
|
||||
|
|
@ -32,46 +31,33 @@ 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,
|
||||
// ),
|
||||
// Pangea#
|
||||
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,
|
||||
),
|
||||
// #Pangea
|
||||
// if (PlatformInfos.isMobile)
|
||||
// SettingsSwitchListTile.adaptive(
|
||||
// title: L10n.of(context).autoplayImages,
|
||||
// onChanged: (b) => AppConfig.autoplayImages = b,
|
||||
// storeKey: SettingKeys.autoplayImages,
|
||||
// defaultValue: AppConfig.autoplayImages,
|
||||
// setting: AppSettings.autoplayImages,
|
||||
// ),
|
||||
// Pangea#
|
||||
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,
|
||||
),
|
||||
|
||||
// #Pangea
|
||||
SwitchListTile.adaptive(
|
||||
value: AppConfig.useActivityImageAsChatBackground,
|
||||
|
|
@ -110,12 +96,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,
|
||||
// ),
|
||||
// Pangea#
|
||||
],
|
||||
|
|
|
|||
|
|
@ -201,10 +201,7 @@ class SettingsNotificationsController extends State<SettingsNotifications> {
|
|||
void updateVolume(double value) {
|
||||
volumeNotifier.value = value;
|
||||
AppConfig.volume = value;
|
||||
Matrix.of(context).store.setDouble(
|
||||
SettingKeys.volume,
|
||||
value,
|
||||
);
|
||||
AppSettings.volume.setItem(value);
|
||||
}
|
||||
|
||||
Future<void> requestNotificationPermission() async {
|
||||
|
|
|
|||
|
|
@ -156,7 +156,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),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/user/style_settings_repo.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/utils/account_config.dart';
|
||||
import 'package:fluffychat/utils/file_selector.dart';
|
||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||
|
|
@ -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,17 +158,7 @@ class SettingsStyleController extends State<SettingsStyle> {
|
|||
}
|
||||
|
||||
void changeFontSizeFactor(double d) {
|
||||
setState(() => AppConfig.fontSizeFactor = d);
|
||||
// #Pangea
|
||||
// Matrix.of(context).store.setString(
|
||||
// SettingKeys.fontSizeFactor,
|
||||
// AppConfig.fontSizeFactor.toString(),
|
||||
// );
|
||||
StyleSettingsRepo.setFontSizeFactor(
|
||||
Matrix.of(context).client.userID!,
|
||||
AppConfig.fontSizeFactor,
|
||||
);
|
||||
// Pangea#
|
||||
AppSettings.fontSizeFactor.setItem(d);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:dynamic_color/dynamic_color.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/pages/chat/events/state_message.dart';
|
||||
|
|
@ -228,7 +229,7 @@ class SettingsStyleView extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
color: theme.onBubbleColor,
|
||||
fontSize: AppConfig.messageFontSize *
|
||||
AppConfig.fontSizeFactor,
|
||||
AppSettings.fontSizeFactor.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -261,7 +262,7 @@ class SettingsStyleView extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
color: theme.colorScheme.onSurface,
|
||||
fontSize: AppConfig.messageFontSize *
|
||||
AppConfig.fontSizeFactor,
|
||||
AppSettings.fontSizeFactor.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -323,13 +324,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,
|
||||
),
|
||||
|
|
@ -348,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,
|
||||
// ),
|
||||
// Pangea#
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pages/chat/chat.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
|
|
@ -10,7 +9,7 @@ import 'package:fluffychat/widgets/matrix.dart';
|
|||
|
||||
extension ActivityMenuLogic on ChatController {
|
||||
bool get shouldShowActivityInstructions {
|
||||
if (AppConfig.showedActivityMenu ||
|
||||
if (InstructionsEnum.showedActivityMenu.isToggledOff ||
|
||||
InstructionsEnum.activityStatsMenu.isToggledOff ||
|
||||
MatrixState.pAnyState.isOverlayOpen(RegExp(r"^word-zoom-card-.*$")) ||
|
||||
timeline == null ||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import 'package:collection/collection.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/pangea/activity_sessions/activity_role_model.dart';
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ class ActivityRolesEvent extends StatelessWidget {
|
|||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12 * AppConfig.fontSizeFactor,
|
||||
fontSize: 12 * AppSettings.fontSizeFactor.value,
|
||||
decoration:
|
||||
event.redacted ? TextDecoration.lineThrough : null,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
||||
|
|
@ -118,7 +119,7 @@ class LemmaUseExampleMessages extends StatelessWidget {
|
|||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onPrimaryFixed,
|
||||
fontSize: AppConfig.fontSizeFactor *
|
||||
fontSize: AppSettings.fontSizeFactor.value *
|
||||
AppConfig.messageFontSize,
|
||||
),
|
||||
children: example.textSpans,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:intl/intl.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/pangea/analytics_downloads/analytics_summary_enum.dart';
|
||||
|
|
@ -426,7 +427,8 @@ class AnalyticsDownloadDialogState extends State<AnalyticsDownloadDialog> {
|
|||
Text(
|
||||
L10n.of(context).fileType,
|
||||
style: TextStyle(
|
||||
fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize,
|
||||
fontSize: AppSettings.fontSizeFactor.value *
|
||||
AppConfig.messageFontSize,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
|
||||
class TextLoadingShimmer extends StatelessWidget {
|
||||
final double width;
|
||||
|
|
@ -24,8 +25,8 @@ class TextLoadingShimmer extends StatelessWidget {
|
|||
borderRadius: BorderRadius.circular(4.0),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
height:
|
||||
height ?? (AppConfig.messageFontSize * AppConfig.fontSizeFactor),
|
||||
height: height ??
|
||||
(AppConfig.messageFontSize * AppSettings.fontSizeFactor.value),
|
||||
width: width,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.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/pangea/analytics_details_popup/morph_meaning_widget.dart';
|
||||
|
|
@ -270,7 +271,8 @@ class _ExampleMessageWidget extends StatelessWidget {
|
|||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onPrimaryFixed,
|
||||
fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize,
|
||||
fontSize: AppSettings.fontSizeFactor.value *
|
||||
AppConfig.messageFontSize,
|
||||
),
|
||||
children: snapshot.data!,
|
||||
),
|
||||
|
|
@ -464,8 +466,8 @@ class _ErrorBlankWidgetState extends State<_ErrorBlankWidget> {
|
|||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onPrimaryFixed,
|
||||
fontSize:
|
||||
AppConfig.fontSizeFactor * AppConfig.messageFontSize,
|
||||
fontSize: AppSettings.fontSizeFactor.value *
|
||||
AppConfig.messageFontSize,
|
||||
),
|
||||
children: [
|
||||
if (trimmedBefore) const TextSpan(text: '…'),
|
||||
|
|
@ -491,7 +493,7 @@ class _ErrorBlankWidgetState extends State<_ErrorBlankWidget> {
|
|||
translation,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onPrimaryFixed,
|
||||
fontSize: AppConfig.fontSizeFactor *
|
||||
fontSize: AppSettings.fontSizeFactor.value *
|
||||
AppConfig.messageFontSize,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
||||
class BotStyle {
|
||||
|
|
@ -16,7 +17,7 @@ class BotStyle {
|
|||
final TextStyle botStyle = TextStyle(
|
||||
fontWeight: bold ? FontWeight.w700 : null,
|
||||
fontSize: AppConfig.messageFontSize *
|
||||
AppConfig.fontSizeFactor *
|
||||
AppSettings.fontSizeFactor.value *
|
||||
(big == true ? 1.2 : 1),
|
||||
fontStyle: italics ? FontStyle.italic : null,
|
||||
color: setColor ? Theme.of(context).colorScheme.primary : null,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
import 'package:animations/animations.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';
|
||||
|
|
@ -201,10 +201,11 @@ class PangeaChatInputRow 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,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,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/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/course_chats/open_roles_indicator.dart';
|
||||
|
|
@ -25,7 +25,9 @@ class ChatListItemSubtitle extends StatelessWidget {
|
|||
!event.redacted &&
|
||||
event.type == EventTypes.Message &&
|
||||
event.messageType == MessageTypes.Text &&
|
||||
!(AppConfig.renderHtml && !event.redacted && event.isRichMessage);
|
||||
!(AppSettings.renderHtml.value &&
|
||||
!event.redacted &&
|
||||
event.isRichMessage);
|
||||
}
|
||||
|
||||
Future<PangeaMessageEvent> _getPangeaMessageEvent(
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import 'package:get_storage/get_storage.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
|
|
@ -67,7 +66,7 @@ class PangeaController {
|
|||
subscriptionController.reinitialize();
|
||||
|
||||
StyleSettingsRepo.settings(userID!).then((settings) {
|
||||
AppConfig.fontSizeFactor = settings.fontSizeFactor;
|
||||
AppSettings.fontSizeFactor.setItem(settings.fontSizeFactor);
|
||||
AppConfig.useActivityImageAsChatBackground =
|
||||
settings.useActivityImageBackground;
|
||||
});
|
||||
|
|
@ -136,18 +135,6 @@ class PangeaController {
|
|||
futures.add(GetStorage(key).erase());
|
||||
}
|
||||
|
||||
if (AppConfig.showedActivityMenu) {
|
||||
futures.add(
|
||||
SharedPreferences.getInstance().then((prefs) async {
|
||||
AppConfig.showedActivityMenu = false;
|
||||
prefs.setBool(
|
||||
SettingKeys.showedActivityMenu,
|
||||
AppConfig.showedActivityMenu,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await Future.wait(futures);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ enum InstructionsEnum {
|
|||
dismissSupportChat,
|
||||
shimmerNewToken,
|
||||
shimmerTranslation,
|
||||
showedActivityMenu,
|
||||
}
|
||||
|
||||
extension InstructionsEnumExtension on InstructionsEnum {
|
||||
|
|
@ -69,6 +70,7 @@ extension InstructionsEnumExtension on InstructionsEnum {
|
|||
case InstructionsEnum.dismissSupportChat:
|
||||
case InstructionsEnum.shimmerNewToken:
|
||||
case InstructionsEnum.shimmerTranslation:
|
||||
case InstructionsEnum.showedActivityMenu:
|
||||
ErrorHandler.logError(
|
||||
e: Exception("No title for this instruction"),
|
||||
m: 'InstructionsEnumExtension.title',
|
||||
|
|
@ -133,6 +135,7 @@ extension InstructionsEnumExtension on InstructionsEnum {
|
|||
case InstructionsEnum.dismissSupportChat:
|
||||
case InstructionsEnum.shimmerNewToken:
|
||||
case InstructionsEnum.shimmerTranslation:
|
||||
case InstructionsEnum.showedActivityMenu:
|
||||
return "";
|
||||
case InstructionsEnum.disableLanguageTools:
|
||||
return l10n.disableLanguageToolsDesc;
|
||||
|
|
|
|||
|
|
@ -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/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/pangea_logo_svg.dart';
|
||||
|
|
@ -78,7 +78,7 @@ class LoginOrSignupViewState extends State<LoginOrSignupView> {
|
|||
forceColor: theme.colorScheme.onSurface,
|
||||
),
|
||||
Text(
|
||||
AppConfig.applicationName,
|
||||
AppSettings.applicationName.value,
|
||||
style: theme.textTheme.headlineSmall
|
||||
?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import 'dart:typed_data';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/widgets/mxc_image.dart';
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ class PangeaLoginScaffold extends StatelessWidget {
|
|||
),
|
||||
if (showAppName)
|
||||
Text(
|
||||
AppConfig.applicationName,
|
||||
AppSettings.applicationName.value,
|
||||
style: Theme.of(context).textTheme.displaySmall,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:excel/excel.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/pangea/analytics_downloads/space_analytics_summary_enum.dart';
|
||||
|
|
@ -289,7 +290,8 @@ class DownloadAnalyticsDialogState extends State<DownloadAnalyticsDialog> {
|
|||
Text(
|
||||
L10n.of(context).fileType,
|
||||
style: TextStyle(
|
||||
fontSize: AppConfig.fontSizeFactor * AppConfig.messageFontSize,
|
||||
fontSize: AppSettings.fontSizeFactor.value *
|
||||
AppConfig.messageFontSize,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ class _MainView extends StatelessWidget {
|
|||
if (path == null) {
|
||||
return ChatList(
|
||||
activeChat: state.pathParameters['roomid'],
|
||||
activeSpaceId: state.pathParameters['spaceid'],
|
||||
activeSpace: state.pathParameters['spaceid'],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ class _MainView extends StatelessWidget {
|
|||
|
||||
return ChatList(
|
||||
activeChat: state.pathParameters['roomid'],
|
||||
activeSpaceId: state.pathParameters['spaceid'],
|
||||
activeSpace: state.pathParameters['spaceid'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ class MessageSelectionPositionerState extends State<MessageSelectionPositioner>
|
|||
widget.event.senderId == widget.event.room.client.userID;
|
||||
|
||||
bool get showDetails =>
|
||||
AppSettings.displayChatDetailsColumn.getItem(Matrix.of(context).store) &&
|
||||
AppSettings.displayChatDetailsColumn.value &&
|
||||
FluffyThemes.isThreeColumnMode(context) &&
|
||||
widget.chatController.room.membership == Membership.join;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,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/pages/chat/events/audio_player.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
|
@ -79,8 +80,8 @@ class MessageAudioCardState extends State<MessageAudioCard> {
|
|||
senderId: widget.messageEvent.senderId,
|
||||
matrixFile: audioFile,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
fontSize:
|
||||
AppConfig.messageFontSize * AppConfig.fontSizeFactor,
|
||||
fontSize: AppConfig.messageFontSize *
|
||||
AppSettings.fontSizeFactor.value,
|
||||
linkColor: Theme.of(context).brightness == Brightness.light
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Theme.of(context).colorScheme.onPrimary,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ class BackgroundPush {
|
|||
}
|
||||
|
||||
final pendingTests = <String, Completer<void>>{};
|
||||
bool firebaseEnabled = false;
|
||||
|
||||
//<GOOGLE_SERVICES>final firebase = FcmSharedIsolate();
|
||||
|
||||
|
|
@ -77,6 +78,7 @@ class BackgroundPush {
|
|||
bool upAction = false;
|
||||
|
||||
void _init() async {
|
||||
//<GOOGLE_SERVICES>firebaseEnabled = true;
|
||||
try {
|
||||
// #Pangea
|
||||
// Handle notifications when app is opened from terminated/background state
|
||||
|
|
@ -346,8 +348,7 @@ class BackgroundPush {
|
|||
currentPushers.first.data.url.toString() == gatewayUrl &&
|
||||
currentPushers.first.data.format ==
|
||||
// #Pangea
|
||||
// AppSettings.pushNotificationsPusherFormat
|
||||
// .getItem(matrix!.store) &&
|
||||
// AppSettings.pushNotificationsPusherFormat.value &&
|
||||
null &&
|
||||
// Pangea#
|
||||
mapEquals(
|
||||
|
|
@ -393,8 +394,7 @@ class BackgroundPush {
|
|||
data: PusherData(
|
||||
url: Uri.parse(gatewayUrl!),
|
||||
// #Pangea
|
||||
// format: AppSettings.pushNotificationsPusherFormat
|
||||
// .getItem(matrix!.store),
|
||||
// format: AppSettings.pushNotificationsPusherFormat.value,
|
||||
// Pangea#
|
||||
additionalProperties: {"data_message": pusherDataMessageFormat},
|
||||
),
|
||||
|
|
@ -468,7 +468,7 @@ class BackgroundPush {
|
|||
if (matrix == null) {
|
||||
return;
|
||||
}
|
||||
if ((matrix?.store.getBool(SettingKeys.showNoGoogle) ?? false) == true) {
|
||||
if (!AppSettings.showNoGoogle.value) {
|
||||
return;
|
||||
}
|
||||
await loadLocale();
|
||||
|
|
@ -499,15 +499,19 @@ class BackgroundPush {
|
|||
}
|
||||
}
|
||||
await setupPusher(
|
||||
gatewayUrl:
|
||||
AppSettings.pushNotificationsGatewayUrl.getItem(matrix!.store),
|
||||
gatewayUrl: AppSettings.pushNotificationsGatewayUrl.value,
|
||||
token: _fcmToken,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> setupUp() async {
|
||||
await UnifiedPushUi(matrix!.context, ["default"], UPFunctions())
|
||||
.registerAppWithDialog();
|
||||
await UnifiedPushUi(
|
||||
context: matrix!.context,
|
||||
instances: ["default"],
|
||||
unifiedPushFunctions: UPFunctions(),
|
||||
showNoDistribDialog: false,
|
||||
onNoDistribDialogDismissed: () {}, // TODO: Implement me
|
||||
).registerAppWithDialog();
|
||||
}
|
||||
|
||||
Future<void> _newUpEndpoint(PushEndpoint newPushEndpoint, String i) async {
|
||||
|
|
@ -552,18 +556,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/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
|
|
@ -109,8 +108,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,
|
||||
|
|
@ -185,7 +184,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,13 +1,16 @@
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart';
|
||||
import '../../config/app_config.dart';
|
||||
|
||||
extension VisibleInGuiExtension on List<Event> {
|
||||
List<Event> filterByVisibleInGui({String? exceptionEventId}) => where(
|
||||
List<Event> filterByVisibleInGui({
|
||||
String? exceptionEventId,
|
||||
}) =>
|
||||
where(
|
||||
// #Pangea
|
||||
// (event) => event.isVisibleInGui || event.eventId == exceptionEventId,
|
||||
(event) =>
|
||||
|
|
@ -28,18 +31,16 @@ 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
|
||||
// #Pangea
|
||||
// (!AppConfig.hideUnknownEvents || isEventTypeKnown);
|
||||
(!AppConfig.hideUnknownEvents || pangeaIsEventTypeKnown) &&
|
||||
(!isState || importantStateEvents.contains(type)) &&
|
||||
// (!AppSettings.hideUnknownEvents.value || isEventTypeKnown);
|
||||
(!AppSettings.hideUnknownEvents.value || pangeaIsEventTypeKnown) &&
|
||||
content.tryGet(ModelKey.transcription) == null &&
|
||||
// if sending of transcription fails,
|
||||
// don't show it as a errored audio event in timeline.
|
||||
((unsigned?['extra_content']
|
||||
as Map<String, dynamic>?)?[ModelKey.transcription] ==
|
||||
null);
|
||||
null) &&
|
||||
(!isState || importantStateEvents.contains(type));
|
||||
// Pangea#
|
||||
|
||||
bool get isState => !{
|
||||
|
|
@ -74,6 +75,7 @@ extension IsStateExtension on Event {
|
|||
PangeaEventTypes.activityRole,
|
||||
].contains(type);
|
||||
|
||||
// we're filtering out some state events that we don't want to render
|
||||
static const Set<String> importantStateEvents = {
|
||||
EventTypes.Encryption,
|
||||
EventTypes.RoomCreate,
|
||||
|
|
|
|||
|
|
@ -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:sentry_flutter/sentry_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
|
||||
|
|
@ -89,8 +88,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;
|
||||
|
||||
|
|
@ -108,5 +106,5 @@ void _sendNoEncryptionWarning(Object exception) async {
|
|||
// );
|
||||
// Pangea#
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:package_info_plus/package_info_plus.dart';
|
|||
import 'package:universal_html/html.dart' as html;
|
||||
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';
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ abstract class PlatformInfos {
|
|||
// Pangea#
|
||||
|
||||
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';
|
||||
|
|
@ -101,7 +102,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/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/utils/client_download_content_extension.dart';
|
||||
|
|
@ -60,7 +60,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,
|
||||
|
|
@ -98,7 +98,7 @@ Future<void> _tryPushHelper(
|
|||
|
||||
client ??= (await ClientManager.getClients(
|
||||
initialize: false,
|
||||
store: await SharedPreferences.getInstance(),
|
||||
store: await AppSettings.init(),
|
||||
))
|
||||
.first;
|
||||
final event = await client.getEventByPushNotification(
|
||||
|
|
@ -300,25 +300,27 @@ Future<void> _tryPushHelper(
|
|||
importance: Importance.high,
|
||||
priority: Priority.max,
|
||||
groupKey: event.room.spaceParents.firstOrNull?.roomId ?? 'rooms',
|
||||
actions: <AndroidNotificationAction>[
|
||||
AndroidNotificationAction(
|
||||
FluffyChatNotificationActions.reply.name,
|
||||
l10n.reply,
|
||||
inputs: [
|
||||
AndroidNotificationActionInput(
|
||||
label: l10n.writeAMessage,
|
||||
),
|
||||
],
|
||||
cancelNotification: false,
|
||||
allowGeneratedReplies: true,
|
||||
semanticAction: SemanticAction.reply,
|
||||
),
|
||||
AndroidNotificationAction(
|
||||
FluffyChatNotificationActions.markAsRead.name,
|
||||
l10n.markAsRead,
|
||||
semanticAction: SemanticAction.markAsRead,
|
||||
),
|
||||
],
|
||||
actions: event.type == EventTypes.RoomMember
|
||||
? null
|
||||
: <AndroidNotificationAction>[
|
||||
AndroidNotificationAction(
|
||||
FluffyChatNotificationActions.reply.name,
|
||||
l10n.reply,
|
||||
inputs: [
|
||||
AndroidNotificationActionInput(
|
||||
label: l10n.writeAMessage,
|
||||
),
|
||||
],
|
||||
cancelNotification: false,
|
||||
allowGeneratedReplies: true,
|
||||
semanticAction: SemanticAction.reply,
|
||||
),
|
||||
AndroidNotificationAction(
|
||||
FluffyChatNotificationActions.markAsRead.name,
|
||||
l10n.markAsRead,
|
||||
semanticAction: SemanticAction.markAsRead,
|
||||
),
|
||||
],
|
||||
);
|
||||
const iOSPlatformChannelSpecifics = DarwinNotificationDetails();
|
||||
final platformChannelSpecifics = NotificationDetails(
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ class PublicRoomDialog extends StatelessWidget {
|
|||
final result = await showFutureLoadingDialog<String>(
|
||||
context: context,
|
||||
future: () async {
|
||||
if (chunk != null && client.getRoomById(chunk.roomId) != null) {
|
||||
if (chunk != null &&
|
||||
client.getRoomById(chunk.roomId) != null &&
|
||||
client.getRoomById(chunk.roomId)?.membership != Membership.leave) {
|
||||
return chunk.roomId;
|
||||
}
|
||||
final roomId = chunk != null && knock
|
||||
|
|
@ -64,6 +66,8 @@ class PublicRoomDialog extends StatelessWidget {
|
|||
if (chunk?.roomType != 'm.space' &&
|
||||
!client.getRoomById(result.result!)!.isSpace) {
|
||||
context.go('/rooms/$roomId');
|
||||
} else {
|
||||
context.go('/rooms?spaceId=$roomId');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ Future<String?> showTextInputDialog({
|
|||
// Pangea#
|
||||
maxLength: maxLength,
|
||||
keyboardType: keyboardType,
|
||||
obscureText: obscureText,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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,6 +21,8 @@ class Avatar extends StatelessWidget {
|
|||
final BorderRadius? borderRadius;
|
||||
final IconData? icon;
|
||||
final BorderSide? border;
|
||||
final Color? backgroundColor;
|
||||
final Color? textColor;
|
||||
// #Pangea
|
||||
final bool useRive;
|
||||
final bool showPresence;
|
||||
|
|
@ -42,6 +44,8 @@ class Avatar extends StatelessWidget {
|
|||
this.borderRadius,
|
||||
this.border,
|
||||
this.icon,
|
||||
this.backgroundColor,
|
||||
this.textColor,
|
||||
// #Pangea
|
||||
this.useRive = false,
|
||||
this.showPresence = true,
|
||||
|
|
@ -80,7 +84,6 @@ class Avatar extends StatelessWidget {
|
|||
side: border ?? BorderSide.none,
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
// #Pangea
|
||||
// child: MxcImage(
|
||||
child: (userId ?? presenceUserId) == BotName.byEnvironment
|
||||
? BotFace(
|
||||
|
|
@ -88,6 +91,7 @@ class Avatar extends StatelessWidget {
|
|||
expression: BotExpression.idle,
|
||||
useRive: useRive,
|
||||
)
|
||||
// #Pangea
|
||||
: !(mxContent.toString().startsWith('mxc://'))
|
||||
? ImageByUrl(
|
||||
imageUrl: mxContent,
|
||||
|
|
@ -101,6 +105,7 @@ class Avatar extends StatelessWidget {
|
|||
),
|
||||
borderRadius: borderRadius,
|
||||
)
|
||||
// Pangea#
|
||||
: MxcImage(
|
||||
// Pangea#
|
||||
client: client,
|
||||
|
|
@ -114,7 +119,8 @@ class Avatar extends StatelessWidget {
|
|||
placeholder: (_) => noPic
|
||||
? Container(
|
||||
decoration: BoxDecoration(
|
||||
color: name?.lightColorAvatar,
|
||||
color:
|
||||
backgroundColor ?? name?.lightColorAvatar,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
|
|
@ -122,7 +128,7 @@ class Avatar extends StatelessWidget {
|
|||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontFamily: 'RobotoMono',
|
||||
color: Colors.white,
|
||||
color: textColor ?? Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: (size / 2.5).roundToDouble(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import 'package:provider/provider.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/pangea/common/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/pangea/languages/locale_provider.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';
|
||||
|
||||
|
|
@ -53,7 +53,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:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
|
|
@ -132,7 +133,7 @@ class _PrivacyButtons extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => launchUrlString(AppConfig.privacyUrl),
|
||||
onPressed: () => launchUrl(AppConfig.privacyUrl),
|
||||
child: Text(
|
||||
L10n.of(context).privacy,
|
||||
style: shadowTextStyle,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'package:permission_handler/permission_handler.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/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/utils/client_download_content_extension.dart';
|
||||
|
|
@ -122,7 +123,7 @@ extension LocalNotificationsExtension on MatrixState {
|
|||
title,
|
||||
body: body,
|
||||
replacesId: linuxNotificationIds[roomId] ?? 0,
|
||||
appName: AppConfig.applicationName,
|
||||
appName: AppSettings.applicationName.value,
|
||||
appIcon: 'fluffychat',
|
||||
actions: [
|
||||
NotificationAction(
|
||||
|
|
@ -147,7 +148,7 @@ extension LocalNotificationsExtension on MatrixState {
|
|||
event.room.setReadMarker(
|
||||
event.eventId,
|
||||
mRead: event.eventId,
|
||||
public: AppConfig.sendPublicReadReceipts,
|
||||
public: AppSettings.sendPublicReadReceipts.value,
|
||||
);
|
||||
break;
|
||||
case DesktopNotificationActions.openChat:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:app_links/app_links.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';
|
||||
|
|
@ -19,13 +18,13 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||
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/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_data/analytics_data_service.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/languages/locale_provider.dart';
|
||||
import 'package:fluffychat/pangea/user/style_settings_repo.dart';
|
||||
import 'package:fluffychat/utils/client_manager.dart';
|
||||
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart';
|
||||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
|
|
@ -34,7 +33,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';
|
||||
|
|
@ -192,7 +190,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
|
||||
|
|
@ -283,11 +281,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
initMatrix();
|
||||
if (PlatformInfos.isWeb) {
|
||||
initConfig().then((_) => initSettings());
|
||||
} else {
|
||||
initSettings();
|
||||
}
|
||||
// #Pangea
|
||||
Sentry.configureScope(
|
||||
(scope) => scope.setUser(
|
||||
|
|
@ -369,19 +362,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
}
|
||||
// Pangea#
|
||||
|
||||
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) {
|
||||
final c = getClientByName(name);
|
||||
if (c == null) {
|
||||
|
|
@ -528,7 +508,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
);
|
||||
}
|
||||
if (result == OkCancelResult.cancel) {
|
||||
await store.setBool(SettingKeys.showNoGoogle, true);
|
||||
await AppSettings.showNoGoogle.setItem(true);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
@ -538,7 +518,7 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
}
|
||||
|
||||
void createVoipPlugin() async {
|
||||
if (store.getBool(SettingKeys.experimentalVoip) == false) {
|
||||
if (AppSettings.experimentalVoip.value) {
|
||||
voipPlugin = null;
|
||||
return;
|
||||
}
|
||||
|
|
@ -560,72 +540,6 @@ class MatrixState extends State<Matrix> with WidgetsBindingObserver {
|
|||
}
|
||||
}
|
||||
|
||||
void initSettings() {
|
||||
// #Pangea
|
||||
// AppConfig.fontSizeFactor =
|
||||
// double.tryParse(store.getString(SettingKeys.fontSizeFactor) ?? '') ??
|
||||
// AppConfig.fontSizeFactor;
|
||||
if (client.isLogged()) {
|
||||
StyleSettingsRepo.settings(client.userID!).then((settings) {
|
||||
AppConfig.fontSizeFactor = settings.fontSizeFactor;
|
||||
AppConfig.useActivityImageAsChatBackground =
|
||||
settings.useActivityImageBackground;
|
||||
});
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
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;
|
||||
|
||||
// #Pangea
|
||||
AppConfig.volume = store.getDouble(SettingKeys.volume) ?? AppConfig.volume;
|
||||
|
||||
AppConfig.showedActivityMenu =
|
||||
store.getBool(SettingKeys.showedActivityMenu) ??
|
||||
AppConfig.showedActivityMenu;
|
||||
// Pangea#
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
|
|
|
|||
|
|
@ -73,15 +73,8 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
.where((s) => s.hasRoomUpdate)
|
||||
.rateLimit(const Duration(seconds: 1)),
|
||||
builder: (context, _) {
|
||||
final allSpaces = client.rooms.where((room) => room.isSpace);
|
||||
final rootSpaces = allSpaces
|
||||
.where(
|
||||
(space) => !allSpaces.any(
|
||||
(parentSpace) => parentSpace.spaceChildren
|
||||
.any((child) => child.roomId == space.id),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final allSpaces =
|
||||
client.rooms.where((room) => room.isSpace).toList();
|
||||
|
||||
// #Pangea
|
||||
// return SizedBox(
|
||||
|
|
@ -99,8 +92,8 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
child: ListView.builder(
|
||||
scrollDirection: Axis.vertical,
|
||||
// #Pangea
|
||||
// itemCount: rootSpaces.length + 2,
|
||||
itemCount: rootSpaces.length + 3,
|
||||
// itemCount: allSpaces.length + 2,
|
||||
itemCount: allSpaces.length + 3,
|
||||
// Pangea#
|
||||
itemBuilder: (context, i) {
|
||||
// #Pangea
|
||||
|
|
@ -189,7 +182,7 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
i--;
|
||||
if (i == rootSpaces.length) {
|
||||
if (i == allSpaces.length) {
|
||||
return NaviRailItem(
|
||||
// #Pangea
|
||||
// isSelected: false,
|
||||
|
|
@ -226,9 +219,9 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
// Pangea#
|
||||
);
|
||||
}
|
||||
final space = rootSpaces[i];
|
||||
final space = allSpaces[i];
|
||||
final displayname =
|
||||
rootSpaces[i].getLocalizedDisplayname(
|
||||
allSpaces[i].getLocalizedDisplayname(
|
||||
MatrixLocals(L10n.of(context)),
|
||||
);
|
||||
final spaceChildrenIds =
|
||||
|
|
@ -239,10 +232,10 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
// #Pangea
|
||||
backgroundColor: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(0),
|
||||
// onTap: () => onGoToSpaceId(rootSpaces[i].id),
|
||||
// onTap: () => onGoToSpaceId(allSpaces[i].id),
|
||||
onTap: () {
|
||||
collapse();
|
||||
final room = client.getRoomById(rootSpaces[i].id);
|
||||
final room = client.getRoomById(allSpaces[i].id);
|
||||
if (room != null) {
|
||||
chatListHandleSpaceTap(
|
||||
context,
|
||||
|
|
@ -250,7 +243,7 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
);
|
||||
} else {
|
||||
context.go(
|
||||
"/rooms/spaces/${rootSpaces[i].id}/details",
|
||||
"/rooms/spaces/${allSpaces[i].id}/details",
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -259,7 +252,7 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
spaceChildrenIds.contains(room.id),
|
||||
// #Pangea
|
||||
// icon: Avatar(
|
||||
// mxContent: rootSpaces[i].avatar,
|
||||
// mxContent: allSpaces[i].avatar,
|
||||
// name: displayname,
|
||||
// border: BorderSide(
|
||||
// width: 1,
|
||||
|
|
@ -271,7 +264,7 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
// ),
|
||||
icon: b.Badge(
|
||||
showBadge:
|
||||
rootSpaces[i].membership == Membership.invite,
|
||||
allSpaces[i].membership == Membership.invite,
|
||||
badgeStyle: b.BadgeStyle(
|
||||
badgeColor: Theme.of(context).colorScheme.error,
|
||||
elevation: 4,
|
||||
|
|
@ -290,7 +283,7 @@ class SpacesNavigationRail extends StatelessWidget {
|
|||
child: ClipPath(
|
||||
clipper: MapClipper(),
|
||||
child: Avatar(
|
||||
mxContent: rootSpaces[i].avatar,
|
||||
mxContent: allSpaces[i].avatar,
|
||||
name: displayname,
|
||||
border: BorderSide(
|
||||
width: 1,
|
||||
|
|
|
|||
|
|
@ -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(() {});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- record_macos (1.1.0):
|
||||
- FlutterMacOS
|
||||
- screen_retriever_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- share_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
|
|
@ -64,7 +66,12 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- wakelock_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- webcrypto (0.1.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- WebRTC-SDK (137.7151.04)
|
||||
- window_manager (0.5.0):
|
||||
- FlutterMacOS
|
||||
- window_to_front (0.0.1):
|
||||
- FlutterMacOS
|
||||
|
||||
|
|
@ -89,6 +96,7 @@ DEPENDENCIES:
|
|||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- record_macos (from `Flutter/ephemeral/.symlinks/plugins/record_macos/macos`)
|
||||
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sqlcipher_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/sqlcipher_flutter_libs/macos`)
|
||||
|
|
@ -96,6 +104,8 @@ DEPENDENCIES:
|
|||
- video_compress (from `Flutter/ephemeral/.symlinks/plugins/video_compress/macos`)
|
||||
- video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||
- webcrypto (from `Flutter/ephemeral/.symlinks/plugins/webcrypto/darwin`)
|
||||
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
|
||||
- window_to_front (from `Flutter/ephemeral/.symlinks/plugins/window_to_front/macos`)
|
||||
|
||||
SPEC REPOS:
|
||||
|
|
@ -144,6 +154,8 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
|
||||
record_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/record_macos/macos
|
||||
screen_retriever_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos
|
||||
share_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
||||
shared_preferences_foundation:
|
||||
|
|
@ -158,6 +170,10 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin
|
||||
wakelock_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
||||
webcrypto:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/webcrypto/darwin
|
||||
window_manager:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
|
||||
window_to_front:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_to_front/macos
|
||||
|
||||
|
|
@ -182,6 +198,7 @@ SPEC CHECKSUMS:
|
|||
package_info_plus: f0052d280d17aa382b932f399edf32507174e870
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
record_macos: 43194b6c06ca6f8fa132e2acea72b202b92a0f5b
|
||||
screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f
|
||||
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
SQLCipher: eb79c64049cb002b4e9fcb30edb7979bf4706dfc
|
||||
|
|
@ -190,7 +207,9 @@ SPEC CHECKSUMS:
|
|||
video_compress: 752b161da855df2492dd1a8fa899743cc8fe9534
|
||||
video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
|
||||
wakelock_plus: 917609be14d812ddd9e9528876538b2263aaa03b
|
||||
webcrypto: a5f5eb3e375cf0a99993e207e97cdcab5c94ce2e
|
||||
WebRTC-SDK: 40d4f5ba05cadff14e4db5614aec402a633f007e
|
||||
window_manager: b729e31d38fb04905235df9ea896128991cad99e
|
||||
window_to_front: 9e76fd432e36700a197dac86a0011e49c89abe0a
|
||||
|
||||
PODFILE CHECKSUM: d0975b16fbdecb73b109d8fbc88aa77ffe4c7a8d
|
||||
|
|
|
|||
18
pubspec.lock
18
pubspec.lock
|
|
@ -45,10 +45,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: animations
|
||||
sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb
|
||||
sha256: a8031b276f0a7986ac907195f10ca7cd04ecf2a8a566bd6dbe03018a9b02b427
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
version: "2.1.0"
|
||||
ansicolor:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1342,14 +1342,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
js_interop:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js_interop
|
||||
sha256: "7ec859c296958ccea34dc770504bd3ff4ae52fdd9e7eeb2bacc7081ad476a1f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.1"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1516,7 +1508,7 @@ packages:
|
|||
path: "/Users/ggurdin/pangea/matrix-dart-sdk"
|
||||
relative: false
|
||||
source: path
|
||||
version: "2.0.1"
|
||||
version: "3.0.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2558,10 +2550,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: unifiedpush_ui
|
||||
sha256: cf86f0214f37debd41f25c0425c8489df85e27f9f8784fed571eb7a86d39ba11
|
||||
sha256: "1b36b2aa0bc6b61577e2661c1183bd3442969ecf77b4c78174796d324f66dd1d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
version: "0.2.0"
|
||||
universal_html:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ environment:
|
|||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
||||
dependencies:
|
||||
animations: ^2.0.11
|
||||
animations: ^2.1.0
|
||||
app_links: ^6.4.1
|
||||
archive: ^4.0.7
|
||||
async: ^2.11.0
|
||||
|
|
@ -91,7 +91,7 @@ dependencies:
|
|||
swipe_to_action: ^0.3.0
|
||||
tor_detector_web: ^1.1.0
|
||||
unifiedpush: ^6.2.0
|
||||
unifiedpush_ui: ^0.1.0
|
||||
unifiedpush_ui: ^0.2.0
|
||||
universal_html: ^2.2.4
|
||||
url_launcher: ^6.3.2
|
||||
video_compress: ^3.1.4
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue