diff --git a/lib/config/routes.dart b/lib/config/routes.dart index f33d9044b..6aa4c9c55 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -43,18 +43,16 @@ abstract class AppRoutes { static FutureOr loggedInRedirect( BuildContext context, GoRouterState state, - ) => - Matrix.of(context).widget.clients.any((client) => client.isLogged()) - ? '/rooms' - : null; + ) => Matrix.of(context).widget.clients.any((client) => client.isLogged()) + ? '/rooms' + : null; static FutureOr loggedOutRedirect( BuildContext context, GoRouterState state, - ) => - Matrix.of(context).widget.clients.any((client) => client.isLogged()) - ? null - : '/home'; + ) => Matrix.of(context).widget.clients.any((client) => client.isLogged()) + ? null + : '/home'; AppRoutes(); @@ -63,8 +61,8 @@ abstract class AppRoutes { path: '/', redirect: (context, state) => Matrix.of(context).widget.clients.any((client) => client.isLogged()) - ? '/rooms' - : '/home', + ? '/rooms' + : '/home', ), GoRoute( path: '/home', @@ -88,19 +86,13 @@ abstract class AppRoutes { ), GoRoute( path: '/logs', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const LogViewer(), - ), + pageBuilder: (context, state) => + defaultPageBuilder(context, state, const LogViewer()), ), GoRoute( path: '/configs', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const ConfigViewer(), - ), + pageBuilder: (context, state) => + defaultPageBuilder(context, state, const ConfigViewer()), ), GoRoute( path: '/backup', @@ -108,9 +100,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - BootstrapDialog( - wipe: state.uri.queryParameters['wipe'] == 'true', - ), + BootstrapDialog(wipe: state.uri.queryParameters['wipe'] == 'true'), ), ), ShellRoute( @@ -150,11 +140,8 @@ abstract class AppRoutes { routes: [ GoRoute( path: 'archive', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const Archive(), - ), + pageBuilder: (context, state) => + defaultPageBuilder(context, state, const Archive()), routes: [ GoRoute( path: ':roomid', @@ -173,20 +160,14 @@ abstract class AppRoutes { ), GoRoute( path: 'newprivatechat', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const NewPrivateChat(), - ), + pageBuilder: (context, state) => + defaultPageBuilder(context, state, const NewPrivateChat()), redirect: loggedOutRedirect, ), GoRoute( path: 'newgroup', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - const NewGroup(), - ), + pageBuilder: (context, state) => + defaultPageBuilder(context, state, const NewGroup()), redirect: loggedOutRedirect, ), GoRoute( @@ -376,9 +357,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - ChatSearchPage( - roomId: state.pathParameters['roomid']!, - ), + ChatSearchPage(roomId: state.pathParameters['roomid']!), ), redirect: loggedOutRedirect, ), @@ -407,9 +386,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - ChatDetails( - roomId: state.pathParameters['roomid']!, - ), + ChatDetails(roomId: state.pathParameters['roomid']!), ), routes: [ GoRoute( @@ -459,9 +436,7 @@ abstract class AppRoutes { pageBuilder: (context, state) => defaultPageBuilder( context, state, - EmotesSettings( - roomId: state.pathParameters['roomid'], - ), + EmotesSettings(roomId: state.pathParameters['roomid']), ), redirect: loggedOutRedirect, ), @@ -480,23 +455,21 @@ abstract class AppRoutes { BuildContext context, GoRouterState state, Widget child, - ) => - NoTransitionPage( - key: state.pageKey, - restorationId: state.pageKey.value, - child: child, - ); + ) => NoTransitionPage( + key: state.pageKey, + restorationId: state.pageKey.value, + child: child, + ); static Page defaultPageBuilder( BuildContext context, GoRouterState state, Widget child, - ) => - FluffyThemes.isColumnMode(context) - ? noTransitionPageBuilder(context, state, child) - : MaterialPage( - key: state.pageKey, - restorationId: state.pageKey.value, - child: child, - ); + ) => FluffyThemes.isColumnMode(context) + ? noTransitionPageBuilder(context, state, child) + : MaterialPage( + key: state.pageKey, + restorationId: state.pageKey.value, + child: child, + ); } diff --git a/lib/config/setting_keys.dart b/lib/config/setting_keys.dart index 44c42a38b..1b19ac795 100644 --- a/lib/config/setting_keys.dart +++ b/lib/config/setting_keys.dart @@ -46,18 +46,12 @@ enum AppSettings { 'chat.fluffy.no_encryption_warning_shown', false, ), - displayChatDetailsColumn( - 'chat.fluffy.display_chat_details_column', - false, - ), + displayChatDetailsColumn('chat.fluffy.display_chat_details_column', false), // AppConfig-mirrored settings applicationName('chat.fluffy.application_name', 'FluffyChat'), defaultHomeserver('chat.fluffy.default_homeserver', 'matrix.org'), // colorSchemeSeed stored as ARGB int - colorSchemeSeedInt( - 'chat.fluffy.color_scheme_seed', - 0xFF5625BA, - ), + colorSchemeSeedInt('chat.fluffy.color_scheme_seed', 0xFF5625BA), emojiSuggestionLocale('emoji_suggestion_locale', ''), enableSoftLogout('chat.fluffy.enable_soft_logout', false); @@ -75,10 +69,9 @@ enum AppSettings { final store = AppSettings._store = await SharedPreferences.getInstance(); // Migrate wrong datatype for fontSizeFactor - final fontSizeFactorString = - Result(() => store.getString(AppSettings.fontSizeFactor.key)) - .asValue - ?.value; + final fontSizeFactorString = Result( + () => store.getString(AppSettings.fontSizeFactor.key), + ).asValue?.value; if (fontSizeFactorString != null) { Logs().i('Migrate wrong datatype for fontSizeFactor!'); await store.remove(AppSettings.fontSizeFactor.key); @@ -93,8 +86,9 @@ enum AppSettings { } if (kIsWeb && loadWebConfigFile) { try { - final configJsonString = - utf8.decode((await http.get(Uri.parse('config.json'))).bodyBytes); + final configJsonString = utf8.decode( + (await http.get(Uri.parse('config.json'))).bodyBytes, + ); final configJson = json.decode(configJsonString) as Map; for (final setting in AppSettings.values) { diff --git a/lib/config/themes.dart b/lib/config/themes.dart index b409dc247..122eef918 100644 --- a/lib/config/themes.dart +++ b/lib/config/themes.dart @@ -20,10 +20,7 @@ abstract class FluffyThemes { static bool isThreeColumnMode(BuildContext context) => MediaQuery.sizeOf(context).width > FluffyThemes.columnWidth * 3.5; - static LinearGradient backgroundGradient( - BuildContext context, - int alpha, - ) { + static LinearGradient backgroundGradient(BuildContext context, int alpha) { final colorScheme = Theme.of(context).colorScheme; return LinearGradient( begin: Alignment.topCenter, @@ -91,12 +88,14 @@ abstract class FluffyThemes { ), appBarTheme: AppBarTheme( toolbarHeight: isColumnMode ? 72 : 56, - shadowColor: - isColumnMode ? colorScheme.surfaceContainer.withAlpha(128) : null, + shadowColor: isColumnMode + ? colorScheme.surfaceContainer.withAlpha(128) + : null, surfaceTintColor: isColumnMode ? colorScheme.surface : null, backgroundColor: isColumnMode ? colorScheme.surface : null, - actionsPadding: - isColumnMode ? const EdgeInsets.symmetric(horizontal: 16.0) : null, + actionsPadding: isColumnMode + ? const EdgeInsets.symmetric(horizontal: 16.0) + : null, systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: brightness.reversed, @@ -107,10 +106,7 @@ abstract class FluffyThemes { ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( - side: BorderSide( - width: 1, - color: colorScheme.primary, - ), + side: BorderSide(width: 1, color: colorScheme.primary), shape: RoundedRectangleBorder( side: BorderSide(color: colorScheme.primary), borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), @@ -157,8 +153,8 @@ extension BubbleColorTheme on ThemeData { : colorScheme.onPrimaryContainer; Color get secondaryBubbleColor => HSLColor.fromColor( - brightness == Brightness.light - ? colorScheme.tertiary - : colorScheme.tertiaryContainer, - ).withSaturation(0.5).toColor(); + brightness == Brightness.light + ? colorScheme.tertiary + : colorScheme.tertiaryContainer, + ).withSaturation(0.5).toColor(); } diff --git a/lib/main.dart b/lib/main.dart index 9f14baea1..d173f77e9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -78,8 +78,9 @@ Future startGui(List clients, SharedPreferences store) async { String? pin; if (PlatformInfos.isMobile) { try { - pin = - await const FlutterSecureStorage().read(key: 'chat.fluffy.app_lock'); + pin = await const FlutterSecureStorage().read( + key: 'chat.fluffy.app_lock', + ); } catch (e, s) { Logs().d('Unable to read PIN from Secure storage', e, s); } diff --git a/lib/pages/archive/archive_view.dart b/lib/pages/archive/archive_view.dart index f9446c26f..5ef4176f2 100644 --- a/lib/pages/archive/archive_view.dart +++ b/lib/pages/archive/archive_view.dart @@ -60,8 +60,9 @@ class ArchiveView extends StatelessWidget { itemBuilder: (BuildContext context, int i) => ChatListItem( controller.archive[i], onForget: () => controller.forgetRoomAction(i), - onTap: () => context - .go('/rooms/archive/${controller.archive[i].id}'), + onTap: () => context.go( + '/rooms/archive/${controller.archive[i].id}', + ), ), ); } diff --git a/lib/pages/bootstrap/bootstrap_dialog.dart b/lib/pages/bootstrap/bootstrap_dialog.dart index 7d91593c0..f518fb5d5 100644 --- a/lib/pages/bootstrap/bootstrap_dialog.dart +++ b/lib/pages/bootstrap/bootstrap_dialog.dart @@ -23,10 +23,7 @@ import '../key_verification/key_verification_dialog.dart'; class BootstrapDialog extends StatefulWidget { final bool wipe; - const BootstrapDialog({ - super.key, - this.wipe = false, - }); + const BootstrapDialog({super.key, this.wipe = false}); @override BootstrapDialogState createState() => BootstrapDialogState(); @@ -148,7 +145,7 @@ class BootstrapDialogState extends State { builder: (context, snapshot) { final status = snapshot.data; return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ CircularProgressIndicator.adaptive(value: status?.progress), if (status != null) Text(status.calcLocalizedString(context)), @@ -177,8 +174,9 @@ class BootstrapDialogState extends State { ), body: Center( child: ConstrainedBox( - constraints: - const BoxConstraints(maxWidth: FluffyThemes.columnWidth * 1.5), + constraints: const BoxConstraints( + maxWidth: FluffyThemes.columnWidth * 1.5, + ), child: ListView( padding: const EdgeInsets.all(16.0), children: [ @@ -193,10 +191,7 @@ class BootstrapDialogState extends State { ), subtitle: Text(L10n.of(context).chatBackupDescription), ), - const Divider( - height: 32, - thickness: 1, - ), + const Divider(height: 32, thickness: 1), TextField( minLines: 2, maxLines: 4, @@ -220,8 +215,9 @@ class BootstrapDialogState extends State { }); }, title: Text(_getSecureStorageLocalizedName()), - subtitle: - Text(L10n.of(context).storeInSecureStorageDescription), + subtitle: Text( + L10n.of(context).storeInSecureStorageDescription, + ), ), const SizedBox(height: 16), CheckboxListTile.adaptive( @@ -241,16 +237,16 @@ class BootstrapDialogState extends State { label: Text(L10n.of(context).next), onPressed: (_recoveryKeyCopied || _storeInSecureStorage == true) - ? () { - if (_storeInSecureStorage == true) { - const FlutterSecureStorage().write( - key: _secureStorageKey, - value: key, - ); - } - setState(() => _recoveryKeyStored = true); - } - : null, + ? () { + if (_storeInSecureStorage == true) { + const FlutterSecureStorage().write( + key: _secureStorageKey, + value: key, + ); + } + setState(() => _recoveryKeyStored = true); + } + : null, ), ], ), @@ -303,8 +299,9 @@ class BootstrapDialogState extends State { padding: const EdgeInsets.all(16.0), children: [ ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8.0), + contentPadding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), trailing: Icon( Icons.info_outlined, color: theme.colorScheme.primary, @@ -370,7 +367,9 @@ class BootstrapDialogState extends State { ); try { await bootstrap - .client.encryption!.crossSigning + .client + .encryption! + .crossSigning .selfSign(recoveryKey: key); Logs().d('Successful selfsigned'); } catch (e, s) { @@ -383,13 +382,14 @@ class BootstrapDialogState extends State { } } on InvalidPassphraseException catch (e) { setState( - () => _recoveryKeyInputError = - e.toLocalizedString(context), + () => _recoveryKeyInputError = e + .toLocalizedString(context), ); } on FormatException catch (_) { setState( - () => _recoveryKeyInputError = - L10n.of(context).wrongRecoveryKey, + () => _recoveryKeyInputError = L10n.of( + context, + ).wrongRecoveryKey, ); } catch (e, s) { ErrorReporter( @@ -397,8 +397,8 @@ class BootstrapDialogState extends State { 'Unable to open SSSS with recovery key', ).onErrorCallback(e, s); setState( - () => _recoveryKeyInputError = - e.toLocalizedString(context), + () => _recoveryKeyInputError = e + .toLocalizedString(context), ); } finally { setState( @@ -428,8 +428,9 @@ class BootstrapDialogState extends State { final consent = await showOkCancelAlertDialog( context: context, title: L10n.of(context).verifyOtherDevice, - message: L10n.of(context) - .verifyOtherDeviceDescription, + message: L10n.of( + context, + ).verifyOtherDeviceDescription, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, ); @@ -452,17 +453,18 @@ class BootstrapDialogState extends State { final waitForSecret = Completer(); final secretsSub = client - .encryption!.ssss.onSecretStored.stream - .listen(( - event, - ) async { - if (await client.encryption!.keyManager - .isCached() && - await client.encryption!.crossSigning - .isCached()) { - waitForSecret.complete(); - } - }); + .encryption! + .ssss + .onSecretStored + .stream + .listen((event) async { + if (await client.encryption!.keyManager + .isCached() && + await client.encryption!.crossSigning + .isCached()) { + waitForSecret.complete(); + } + }); final result = await showFutureLoadingDialog( context: context, @@ -542,7 +544,7 @@ class BootstrapDialogState extends State { case BootstrapState.done: titleText = L10n.of(context).everythingReady; body = Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon( Icons.check_circle_rounded, @@ -576,13 +578,9 @@ class BootstrapDialogState extends State { child: Padding( padding: const EdgeInsets.all(20.0), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - body, - const SizedBox(height: 8), - ...buttons, - ], + mainAxisSize: .min, + crossAxisAlignment: .stretch, + children: [body, const SizedBox(height: 8), ...buttons], ), ), ), diff --git a/lib/pages/chat/add_widget_tile_view.dart b/lib/pages/chat/add_widget_tile_view.dart index 9877ac576..c69968d6a 100644 --- a/lib/pages/chat/add_widget_tile_view.dart +++ b/lib/pages/chat/add_widget_tile_view.dart @@ -19,20 +19,21 @@ class AddWidgetTileView extends StatelessWidget { CupertinoSegmentedControl( groupValue: controller.widgetType, padding: const EdgeInsets.all(8), - children: { - 'm.etherpad': Text(L10n.of(context).widgetEtherpad), - 'm.jitsi': Text(L10n.of(context).widgetJitsi), - 'm.video': Text(L10n.of(context).widgetVideo), - 'm.custom': Text(L10n.of(context).widgetCustom), - }.map( - (key, value) => MapEntry( - key, - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: value, + children: + { + 'm.etherpad': Text(L10n.of(context).widgetEtherpad), + 'm.jitsi': Text(L10n.of(context).widgetJitsi), + 'm.video': Text(L10n.of(context).widgetVideo), + 'm.custom': Text(L10n.of(context).widgetCustom), + }.map( + (key, value) => MapEntry( + key, + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: value, + ), + ), ), - ), - ), onValueChanged: controller.setWidgetType, ), Padding( diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index c33f59436..61f2dec97 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -182,14 +182,14 @@ class ChatController extends State } void enterThread(String eventId) => setState(() { - activeThreadId = eventId; - selectedEvents.clear(); - }); + activeThreadId = eventId; + selectedEvents.clear(); + }); void closeThread() => setState(() { - activeThreadId = null; - selectedEvents.clear(); - }); + activeThreadId = null; + selectedEvents.clear(); + }); void recreateChat() async { final room = this.room; @@ -266,9 +266,7 @@ class ChatController extends State closeIconColor: theme.colorScheme.onErrorContainer, content: Text( L10n.of(context).otherPartyNotLoggedIn, - style: TextStyle( - color: theme.colorScheme.onErrorContainer, - ), + style: TextStyle(color: theme.colorScheme.onErrorContainer), ), showCloseIcon: true, ), @@ -306,11 +304,9 @@ class ChatController extends State } return KeyEventResult.handled; } else if (evt.logicalKey.keyLabel == 'Enter' && evt is KeyDownEvent) { - final currentLineNum = sendController.text - .substring( - 0, - sendController.selection.baseOffset, - ) + final currentLineNum = + sendController.text + .substring(0, sendController.selection.baseOffset) .split('\n') .length - 1; @@ -357,10 +353,11 @@ class ChatController extends State sendingClient = Matrix.of(context).client; final lastEventThreadId = room.lastEvent?.relationshipType == RelationshipTypes.thread - ? room.lastEvent?.relationshipEventId - : null; - readMarkerEventId = - room.hasNewMessages ? lastEventThreadId ?? room.fullyRead : ''; + ? room.lastEvent?.relationshipEventId + : null; + readMarkerEventId = room.hasNewMessages + ? lastEventThreadId ?? room.fullyRead + : ''; WidgetsBinding.instance.addObserver(this); _tryLoadTimeline(); if (kIsWeb) { @@ -402,11 +399,11 @@ class ChatController extends State var readMarkerEventIndex = readMarkerEventId.isEmpty ? -1 : timeline!.events - .filterByVisibleInGui( - exceptionEventId: readMarkerEventId, - threadId: activeThreadId, - ) - .indexWhere((e) => e.eventId == readMarkerEventId); + .filterByVisibleInGui( + exceptionEventId: readMarkerEventId, + threadId: activeThreadId, + ) + .indexWhere((e) => e.eventId == readMarkerEventId); // Read marker is existing but not found in first events. Try a single // requestHistory call before opening timeline on event context: @@ -441,12 +438,12 @@ class ChatController extends State String? scrollUpBannerEventId; void discardScrollUpBannerEventId() => setState(() { - scrollUpBannerEventId = null; - }); + scrollUpBannerEventId = null; + }); void _showScrollUpMaterialBanner(String eventId) => setState(() { - scrollUpBannerEventId = eventId; - }); + scrollUpBannerEventId = eventId; + }); void updateView() { if (!mounted) return; @@ -463,9 +460,7 @@ class ChatController extends State animateInEventIndex = i; } - Future _getTimeline({ - String? eventContextId, - }) async { + Future _getTimeline({String? eventContextId}) async { await Matrix.of(context).client.roomsLoading; await Matrix.of(context).client.accountDataLoading; if (eventContextId != null && @@ -534,12 +529,12 @@ class ChatController extends State // ignore: unawaited_futures _setReadMarkerFuture = timeline .setReadMarker( - eventId: eventId, - public: AppSettings.sendPublicReadReceipts.value, - ) + eventId: eventId, + public: AppSettings.sendPublicReadReceipts.value, + ) .then((_) { - _setReadMarkerFuture = null; - }); + _setReadMarkerFuture = null; + }); if (eventId == null || eventId == timeline.room.lastEvent?.eventId) { Matrix.of(context).backgroundPush?.cancelNotification(roomId); } @@ -579,8 +574,8 @@ class ChatController extends State } void setActiveClient(Client c) => setState(() { - Matrix.of(context).setActiveClient(c); - }); + Matrix.of(context).setActiveClient(c); + }); Future send() async { if (sendController.text.trim().isEmpty) return; @@ -627,11 +622,7 @@ class ChatController extends State } void sendFileAction({FileSelectorType type = FileSelectorType.any}) async { - final files = await selectFiles( - context, - allowMultiple: true, - type: type, - ); + final files = await selectFiles(context, allowMultiple: true, type: type); if (files.isEmpty) return; await showAdaptiveDialog( context: context, @@ -722,31 +713,26 @@ class ChatController extends State setState(() { replyEvent = null; }); - room.sendFileEvent( - file, - inReplyTo: replyEvent, - threadRootEventId: activeThreadId, - extraContent: { - 'info': { - ...file.info, - 'duration': duration, - }, - 'org.matrix.msc3245.voice': {}, - 'org.matrix.msc1767.audio': { - 'duration': duration, - 'waveform': waveform, - }, - }, - ).catchError((e) { - scaffoldMessenger.showSnackBar( - SnackBar( - content: Text( - (e as Object).toLocalizedString(context), - ), - ), - ); - return null; - }); + room + .sendFileEvent( + file, + inReplyTo: replyEvent, + threadRootEventId: activeThreadId, + extraContent: { + 'info': {...file.info, 'duration': duration}, + 'org.matrix.msc3245.voice': {}, + 'org.matrix.msc1767.audio': { + 'duration': duration, + 'waveform': waveform, + }, + }, + ) + .catchError((e) { + scaffoldMessenger.showSnackBar( + SnackBar(content: Text((e as Object).toLocalizedString(context))), + ); + return null; + }); return; } @@ -785,7 +771,9 @@ class ChatController extends State } for (final event in selectedEvents) { if (copyString.isNotEmpty) copyString += '\n\n'; - copyString += event.getDisplayEvent(timeline!).calcLocalizedBodyFallback( + copyString += event + .getDisplayEvent(timeline!) + .calcLocalizedBodyFallback( MatrixLocals(L10n.of(context)), withSenderNamePrefix: true, ); @@ -813,14 +801,8 @@ class ChatController extends State value: -100, label: L10n.of(context).extremeOffensive, ), - AdaptiveModalAction( - value: -50, - label: L10n.of(context).offensive, - ), - AdaptiveModalAction( - value: 0, - label: L10n.of(context).inoffensive, - ), + AdaptiveModalAction(value: -50, label: L10n.of(context).offensive), + AdaptiveModalAction(value: 0, label: L10n.of(context).inoffensive), ], ); if (score == null) return; @@ -835,11 +817,11 @@ class ChatController extends State final result = await showFutureLoadingDialog( context: context, future: () => Matrix.of(context).client.reportEvent( - event.roomId!, - event.eventId, - reason: reason, - score: score, - ), + event.roomId!, + event.eventId, + reason: reason, + score: score, + ), ); if (result.error != null) return; setState(() { @@ -905,9 +887,10 @@ class ChatController extends State return; } final room = client.getRoomById(roomId)!; - await Event.fromJson(event.toJson(), room).redactEvent( - reason: reason, - ); + await Event.fromJson( + event.toJson(), + room, + ).redactEvent(reason: reason); } } else { await event.cancelSend(); @@ -957,8 +940,9 @@ class ChatController extends State !selectedEvents.first.status.isSent) { return false; } - return currentRoomBundle - .any((cl) => selectedEvents.first.senderId == cl!.userID); + return currentRoomBundle.any( + (cl) => selectedEvents.first.senderId == cl!.userID, + ); } void forwardEventsAction() async { @@ -966,9 +950,9 @@ class ChatController extends State final timeline = this.timeline; if (timeline == null) return; - final forwardEvents = List.from(selectedEvents) - .map((event) => event.getDisplayEvent(timeline)) - .toList(); + final forwardEvents = List.from( + selectedEvents, + ).map((event) => event.getDisplayEvent(timeline)).toList(); await showScaffoldDialog( context: context, @@ -1004,29 +988,29 @@ class ChatController extends State inputFocus.requestFocus(); } - void scrollToEventId( - String eventId, { - bool highlightEvent = true, - }) async { - final foundEvent = - timeline!.events.firstWhereOrNull((event) => event.eventId == eventId); + void scrollToEventId(String eventId, {bool highlightEvent = true}) async { + final foundEvent = timeline!.events.firstWhereOrNull( + (event) => event.eventId == eventId, + ); final eventIndex = foundEvent == null ? -1 : timeline!.events - .filterByVisibleInGui( - exceptionEventId: eventId, - threadId: activeThreadId, - ) - .indexOf(foundEvent); + .filterByVisibleInGui( + exceptionEventId: eventId, + threadId: activeThreadId, + ) + .indexOf(foundEvent); if (eventIndex == -1) { setState(() { timeline = null; _scrolledUp = false; loadTimelineFuture = _getTimeline(eventContextId: eventId).onError( - ErrorReporter(context, 'Unable to load timeline after scroll to ID') - .onErrorCallback, + ErrorReporter( + context, + 'Unable to load timeline after scroll to ID', + ).onErrorCallback, ); }); await loadTimelineFuture; @@ -1054,8 +1038,10 @@ class ChatController extends State timeline = null; _scrolledUp = false; loadTimelineFuture = _getTimeline().onError( - ErrorReporter(context, 'Unable to load timeline after scroll down') - .onErrorCallback, + ErrorReporter( + context, + 'Unable to load timeline after scroll down', + ).onErrorCallback, ); }); await loadTimelineFuture; @@ -1093,9 +1079,9 @@ class ChatController extends State } void clearSelectedEvents() => setState(() { - selectedEvents.clear(); - showEmojiPicker = false; - }); + selectedEvents.clear(); + showEmojiPicker = false; + }); void clearSingleSelectedEvent() { if (selectedEvents.length <= 1) { @@ -1115,12 +1101,13 @@ class ChatController extends State setState(() { pendingText = sendController.text; editEvent = selectedEvents.first; - sendController.text = - editEvent!.getDisplayEvent(timeline!).calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)), - withSenderNamePrefix: false, - hideReply: true, - ); + sendController.text = editEvent! + .getDisplayEvent(timeline!) + .calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)), + withSenderNamePrefix: false, + hideReply: true, + ); selectedEvents.clear(); }); inputFocus.requestFocus(); @@ -1145,22 +1132,15 @@ class ChatController extends State if (!mounted) return; context.go('/rooms/${result.result!}'); - await showFutureLoadingDialog( - context: context, - future: room.leave, - ); + await showFutureLoadingDialog(context: context, future: room.leave); } void onSelectMessage(Event event) { if (!event.redacted) { if (selectedEvents.contains(event)) { - setState( - () => selectedEvents.remove(event), - ); + setState(() => selectedEvents.remove(event)); } else { - setState( - () => selectedEvents.add(event), - ); + setState(() => selectedEvents.add(event)); } selectedEvents.sort( (a, b) => a.originServerTs.compareTo(b.originServerTs), @@ -1243,7 +1223,8 @@ class ChatController extends State void pinEvent() { final pinnedEventIds = room.pinnedEventIds; final selectedEventIds = selectedEvents.map((e) => e.eventId).toSet(); - final unpin = selectedEventIds.length == 1 && + final unpin = + selectedEventIds.length == 1 && pinnedEventIds.contains(selectedEventIds.single); if (unpin) { pinnedEventIds.removeWhere(selectedEventIds.contains); @@ -1353,20 +1334,20 @@ class ChatController extends State try { await voipPlugin!.voip.inviteToCall(room, callType); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(e.toLocalizedString(context))), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } } void cancelReplyEventAction() => setState(() { - if (editEvent != null) { - sendController.text = pendingText; - pendingText = ''; - } - replyEvent = null; - editEvent = null; - }); + if (editEvent != null) { + sendController.text = pendingText; + pendingText = ''; + } + replyEvent = null; + editEvent = null; + }); late final ValueNotifier _displayChatDetailsColumn; @@ -1382,38 +1363,30 @@ class ChatController extends State final theme = Theme.of(context); return Row( children: [ - Expanded( - child: ChatView(this), - ), + Expanded(child: ChatView(this)), ValueListenableBuilder( valueListenable: _displayChatDetailsColumn, builder: (context, displayChatDetailsColumn, _) => !FluffyThemes.isThreeColumnMode(context) || - room.membership != Membership.join || - !displayChatDetailsColumn - ? const SizedBox( - height: double.infinity, - width: 0, - ) - : Container( - width: FluffyThemes.columnWidth, - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - border: Border( - left: BorderSide( - width: 1, - color: theme.dividerColor, - ), - ), - ), - child: ChatDetails( - roomId: roomId, - embeddedCloseButton: IconButton( - icon: const Icon(Icons.close), - onPressed: toggleDisplayChatDetailsColumn, - ), - ), + room.membership != Membership.join || + !displayChatDetailsColumn + ? const SizedBox(height: double.infinity, width: 0) + : Container( + width: FluffyThemes.columnWidth, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + border: Border( + left: BorderSide(width: 1, color: theme.dividerColor), ), + ), + child: ChatDetails( + roomId: roomId, + embeddedCloseButton: IconButton( + icon: const Icon(Icons.close), + onPressed: toggleDisplayChatDetailsColumn, + ), + ), + ), ), ], ); diff --git a/lib/pages/chat/chat_app_bar_title.dart b/lib/pages/chat/chat_app_bar_title.dart index f56091333..cce3a0d88 100644 --- a/lib/pages/chat/chat_app_bar_title.dart +++ b/lib/pages/chat/chat_app_bar_title.dart @@ -34,8 +34,8 @@ class ChatAppBarTitle extends StatelessWidget { onTap: controller.isArchived ? null : () => FluffyThemes.isThreeColumnMode(context) - ? controller.toggleDisplayChatDetailsColumn() - : context.go('/rooms/${room.id}/details'), + ? controller.toggleDisplayChatDetailsColumn() + : context.go('/rooms/${room.id}/details'), child: Row( children: [ Hero( @@ -51,22 +51,22 @@ class ChatAppBarTitle extends StatelessWidget { const SizedBox(width: 12), Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: .start, children: [ Text( room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), maxLines: 1, overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 16, - ), + style: const TextStyle(fontSize: 16), ), StreamBuilder( stream: room.client.onSyncStatus.stream, builder: (context, snapshot) { - final status = room.client.onSyncStatus.value ?? + final status = + room.client.onSyncStatus.value ?? const SyncStatusUpdate(SyncStatus.waitingForResponse); - final hide = FluffyThemes.isColumnMode(context) || + final hide = + FluffyThemes.isColumnMode(context) || (room.client.onSync.value != null && status.status != SyncStatus.error && room.client.prevBatch != null); @@ -91,8 +91,9 @@ class ChatAppBarTitle extends StatelessWidget { if (lastActiveTimestamp != null) { return Text( L10n.of(context).lastActiveAgo( - lastActiveTimestamp - .localizedTimeShort(context), + lastActiveTimestamp.localizedTimeShort( + context, + ), ), style: style, ); diff --git a/lib/pages/chat/chat_emoji_picker.dart b/lib/pages/chat/chat_emoji_picker.dart index c5fcdef62..be845bddd 100644 --- a/lib/pages/chat/chat_emoji_picker.dart +++ b/lib/pages/chat/chat_emoji_picker.dart @@ -52,8 +52,9 @@ class ChatEmojiPicker extends StatelessWidget { ), categoryViewConfig: CategoryViewConfig( backspaceColor: theme.colorScheme.primary, - iconColor: - theme.colorScheme.primary.withAlpha(128), + iconColor: theme.colorScheme.primary.withAlpha( + 128, + ), iconColorSelected: theme.colorScheme.primary, indicatorColor: theme.colorScheme.primary, backgroundColor: theme.colorScheme.surface, diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index 1ed35f3be..6cecb8b25 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -16,10 +16,7 @@ import 'package:fluffychat/utils/platform_infos.dart'; class ChatEventList extends StatelessWidget { final ChatController controller; - const ChatEventList({ - super.key, - required this.controller, - }); + const ChatEventList({super.key, required this.controller}); @override Widget build(BuildContext context) { @@ -30,10 +27,7 @@ class ChatEventList extends StatelessWidget { } final theme = Theme.of(context); - final colors = [ - theme.secondaryBubbleColor, - theme.bubbleColor, - ]; + final colors = [theme.secondaryBubbleColor, theme.bubbleColor]; final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0; @@ -83,11 +77,8 @@ class ChatEventList extends StatelessWidget { ); } return Column( - mainAxisSize: MainAxisSize.min, - children: [ - SeenByRow(controller), - TypingIndicators(controller), - ], + mainAxisSize: .min, + children: [SeenByRow(controller), TypingIndicators(controller)], ); } @@ -101,8 +92,9 @@ class ChatEventList extends StatelessWidget { !event.isCollapsedState && event.isVisibleInGui, ); if (visibleIndex > timeline.events.length - 50) { - WidgetsBinding.instance - .addPostFrameCallback(controller.requestHistory); + WidgetsBinding.instance.addPostFrameCallback( + controller.requestHistory, + ); } return Center( child: AnimatedSwitcher( @@ -126,7 +118,8 @@ class ChatEventList extends StatelessWidget { // The message at this index: final event = events[i]; - final animateIn = animateInEventIndex != null && + final animateIn = + animateInEventIndex != null && timeline.events.length > animateInEventIndex && event == timeline.events[animateInEventIndex]; @@ -134,10 +127,12 @@ class ChatEventList extends StatelessWidget { final previousEvent = i > 0 ? events[i - 1] : null; // Collapsed state event - final canExpand = event.isCollapsedState && + final canExpand = + event.isCollapsedState && nextEvent?.isCollapsedState == true && previousEvent?.isCollapsedState != true; - final isCollapsed = event.isCollapsedState && + final isCollapsed = + event.isCollapsedState && previousEvent?.isCollapsedState == true && !controller.expandedEventIds.contains(event.eventId); @@ -161,11 +156,12 @@ class ChatEventList extends StatelessWidget { scrollToEventId: (String eventId) => controller.scrollToEventId(eventId), longPressSelect: controller.selectedEvents.isNotEmpty, - selected: controller.selectedEvents - .any((e) => e.eventId == event.eventId), + selected: controller.selectedEvents.any( + (e) => e.eventId == event.eventId, + ), singleSelected: controller.selectedEvents.singleOrNull?.eventId == - event.eventId, + event.eventId, onEdit: () => controller.editSelectedEventAction(), timeline: timeline, displayReadMarker: @@ -181,9 +177,9 @@ class ChatEventList extends StatelessWidget { : null, onExpand: canExpand ? () => controller.expandEventsFrom( - event, - !controller.expandedEventIds.contains(event.eventId), - ) + event, + !controller.expandedEventIds.contains(event.eventId), + ) : null, ), ); diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index 5b9193032..57eb5f27b 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -53,12 +53,13 @@ class ChatInputRow extends StatelessWidget { ); } return Row( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: .end, + mainAxisAlignment: .spaceBetween, children: controller.selectMode ? [ - if (controller.selectedEvents - .every((event) => event.status == EventStatus.error)) + if (controller.selectedEvents.every( + (event) => event.status == EventStatus.error, + )) SizedBox( height: height, child: TextButton( @@ -90,36 +91,36 @@ class ChatInputRow extends StatelessWidget { ), controller.selectedEvents.length == 1 ? controller.selectedEvents.first - .getDisplayEvent(controller.timeline!) - .status - .isSent - ? SizedBox( - height: height, - child: TextButton( - style: selectedTextButtonStyle, - onPressed: controller.replyAction, - child: Row( - children: [ - Text(L10n.of(context).reply), - const Icon(Icons.keyboard_arrow_right), - ], + .getDisplayEvent(controller.timeline!) + .status + .isSent + ? SizedBox( + height: height, + child: TextButton( + style: selectedTextButtonStyle, + onPressed: controller.replyAction, + child: Row( + children: [ + Text(L10n.of(context).reply), + const Icon(Icons.keyboard_arrow_right), + ], + ), ), - ), - ) - : SizedBox( - height: height, - child: TextButton( - style: selectedTextButtonStyle, - onPressed: controller.sendAgainAction, - child: Row( - children: [ - Text(L10n.of(context).tryToSendAgain), - const SizedBox(width: 4), - const Icon(Icons.send_outlined, size: 16), - ], + ) + : SizedBox( + height: height, + child: TextButton( + style: selectedTextButtonStyle, + onPressed: controller.sendAgainAction, + child: Row( + children: [ + Text(L10n.of(context).tryToSendAgain), + const SizedBox(width: 4), + const Icon(Icons.send_outlined, size: 16), + ], + ), ), - ), - ) + ) : const SizedBox.shrink(), ] : [ @@ -127,8 +128,9 @@ class ChatInputRow extends StatelessWidget { AnimatedContainer( duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, - width: - controller.sendController.text.isNotEmpty ? 0 : height, + width: controller.sendController.text.isNotEmpty + ? 0 + : height, height: height, alignment: Alignment.center, decoration: const BoxDecoration(), @@ -190,8 +192,9 @@ class ChatInputRow extends StatelessWidget { theme.colorScheme.onPrimaryContainer, foregroundColor: theme.colorScheme.primaryContainer, - child: - const Icon(Icons.video_camera_back_outlined), + child: const Icon( + Icons.video_camera_back_outlined, + ), ), title: Text(L10n.of(context).sendVideo), contentPadding: const EdgeInsets.all(0), @@ -270,19 +273,20 @@ class ChatInputRow extends StatelessWidget { tooltip: L10n.of(context).emojis, color: theme.colorScheme.onPrimaryContainer, icon: PageTransitionSwitcher( - transitionBuilder: ( - Widget child, - Animation primaryAnimation, - Animation secondaryAnimation, - ) { - return SharedAxisTransition( - animation: primaryAnimation, - secondaryAnimation: secondaryAnimation, - transitionType: SharedAxisTransitionType.scaled, - fillColor: Colors.transparent, - child: child, - ); - }, + transitionBuilder: + ( + Widget child, + Animation primaryAnimation, + Animation secondaryAnimation, + ) { + return SharedAxisTransition( + animation: primaryAnimation, + secondaryAnimation: secondaryAnimation, + transitionType: SharedAxisTransitionType.scaled, + fillColor: Colors.transparent, + child: child, + ); + }, child: Icon( controller.showEmojiPicker ? Icons.keyboard @@ -313,9 +317,9 @@ class ChatInputRow extends StatelessWidget { keyboardType: TextInputType.multiline, textInputAction: AppSettings.sendOnEnter.value == true && - PlatformInfos.isMobile - ? TextInputAction.send - : null, + PlatformInfos.isMobile + ? TextInputAction.send + : null, onSubmitted: controller.onInputBarSubmitted, onSubmitImage: controller.sendImageFromClipBoard, focusNode: controller.inputFocus, @@ -335,14 +339,18 @@ class ChatInputRow extends StatelessWidget { filled: false, ), onChanged: controller.onInputBarChanged, - suggestionEmojis: getDefaultEmojiLocale( - AppSettings.emojiSuggestionLocale.value.isNotEmpty - ? Locale(AppSettings.emojiSuggestionLocale.value) - : Localizations.localeOf(context), - ).fold( - [], - (emojis, category) => emojis..addAll(category.emoji), - ), + suggestionEmojis: + getDefaultEmojiLocale( + AppSettings.emojiSuggestionLocale.value.isNotEmpty + ? Locale( + AppSettings.emojiSuggestionLocale.value, + ) + : Localizations.localeOf(context), + ).fold( + [], + (emojis, category) => + emojis..addAll(category.emoji), + ), ), ), ), @@ -350,19 +358,21 @@ class ChatInputRow extends StatelessWidget { height: height, width: height, alignment: Alignment.center, - child: PlatformInfos.platformCanRecord && + child: + PlatformInfos.platformCanRecord && controller.sendController.text.isEmpty ? IconButton( tooltip: L10n.of(context).voiceMessage, onPressed: () => ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - L10n.of(context) - .longPressToRecordVoiceMessage, + SnackBar( + content: Text( + L10n.of( + context, + ).longPressToRecordVoiceMessage, + ), + ), ), - ), - ), onLongPress: () => recordingViewModel .startRecording(controller.room), style: IconButton.styleFrom( @@ -394,9 +404,9 @@ class _ChatAccountPicker extends StatelessWidget { const _ChatAccountPicker(this.controller); void _popupMenuButtonSelected(String mxid, BuildContext context) { - final client = Matrix.of(context) - .currentBundle! - .firstWhere((cl) => cl!.userID == mxid, orElse: () => null); + final client = Matrix.of( + context, + ).currentBundle!.firstWhere((cl) => cl!.userID == mxid, orElse: () => null); if (client == null) { Logs().w('Attempted to switch to a non-existing client $mxid'); return; @@ -423,7 +433,8 @@ class _ChatAccountPicker extends StatelessWidget { builder: (context, snapshot) => ListTile( leading: Avatar( mxContent: snapshot.data?.avatarUrl, - name: snapshot.data?.displayName ?? + name: + snapshot.data?.displayName ?? client.userID!.localpart, size: 20, ), @@ -436,7 +447,8 @@ class _ChatAccountPicker extends StatelessWidget { .toList(), child: Avatar( mxContent: snapshot.data?.avatarUrl, - name: snapshot.data?.displayName ?? + name: + snapshot.data?.displayName ?? Matrix.of(context).client.userID!.localpart, size: 20, ), diff --git a/lib/pages/chat/chat_view.dart b/lib/pages/chat/chat_view.dart index 60f9d4a05..0cddbb01d 100644 --- a/lib/pages/chat/chat_view.dart +++ b/lib/pages/chat/chat_view.dart @@ -49,8 +49,9 @@ class ChatView extends StatelessWidget { IconButton( icon: const Icon(Icons.message_outlined), tooltip: L10n.of(context).replyInThread, - onPressed: () => controller - .enterThread(controller.selectedEvents.single.eventId), + onPressed: () => controller.enterThread( + controller.selectedEvents.single.eventId, + ), ), IconButton( icon: const Icon(Icons.copy_outlined), @@ -83,7 +84,7 @@ class ChatView extends StatelessWidget { onTap: controller.pinEvent, value: null, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.push_pin_outlined), const SizedBox(width: 12), @@ -96,7 +97,7 @@ class ChatView extends StatelessWidget { onTap: () => controller.saveSelectedEvent(context), value: null, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.download_outlined), const SizedBox(width: 12), @@ -107,7 +108,7 @@ class ChatView extends StatelessWidget { PopupMenuItem( value: _EventContextAction.info, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.info_outlined), const SizedBox(width: 12), @@ -119,12 +120,9 @@ class ChatView extends StatelessWidget { PopupMenuItem( value: _EventContextAction.report, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ - const Icon( - Icons.shield_outlined, - color: Colors.red, - ), + const Icon(Icons.shield_outlined, color: Colors.red), const SizedBox(width: 12), Text(L10n.of(context).reportMessage), ], @@ -166,7 +164,8 @@ class ChatView extends StatelessWidget { final accountConfig = Matrix.of(context).client.applicationAccountConfig; return PopScope( - canPop: controller.selectedEvents.isEmpty && + canPop: + controller.selectedEvents.isEmpty && !controller.showEmojiPicker && controller.activeThreadId == null, onPopInvokedWithResult: (pop, _) async { @@ -207,8 +206,8 @@ class ChatView extends StatelessWidget { ), backgroundColor: controller.selectedEvents.isEmpty ? controller.activeThreadId != null - ? theme.colorScheme.secondaryContainer - : null + ? theme.colorScheme.secondaryContainer + : null : theme.colorScheme.tertiaryContainer, automaticallyImplyLeading: false, leading: controller.selectMode @@ -219,36 +218,31 @@ class ChatView extends StatelessWidget { color: theme.colorScheme.onTertiaryContainer, ) : activeThreadId != null - ? IconButton( - icon: const Icon(Icons.close), - onPressed: controller.closeThread, - tooltip: L10n.of(context).backToMainChat, - color: theme.colorScheme.onSecondaryContainer, - ) - : FluffyThemes.isColumnMode(context) - ? null - : StreamBuilder( - stream: Matrix.of(context) - .client - .onSync - .stream - .where( - (syncUpdate) => syncUpdate.hasRoomUpdate, - ), - builder: (context, _) => UnreadRoomsBadge( - filter: (r) => r.id != controller.roomId, - badgePosition: - BadgePosition.topEnd(end: 8, top: 4), - child: const Center(child: BackButton()), - ), - ), + ? IconButton( + icon: const Icon(Icons.close), + onPressed: controller.closeThread, + tooltip: L10n.of(context).backToMainChat, + color: theme.colorScheme.onSecondaryContainer, + ) + : FluffyThemes.isColumnMode(context) + ? null + : StreamBuilder( + stream: Matrix.of(context).client.onSync.stream.where( + (syncUpdate) => syncUpdate.hasRoomUpdate, + ), + builder: (context, _) => UnreadRoomsBadge( + filter: (r) => r.id != controller.roomId, + badgePosition: BadgePosition.topEnd(end: 8, top: 4), + child: const Center(child: BackButton()), + ), + ), titleSpacing: FluffyThemes.isColumnMode(context) ? 24 : 0, title: ChatAppBarTitle(controller), actions: _appBarActions(context), bottom: PreferredSize( preferredSize: Size.fromHeight(appbarBottomHeight), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ PinnedEvents(controller), if (activeThreadId != null) @@ -285,9 +279,7 @@ class ChatView extends StatelessWidget { title: L10n.of(context).jumpToLastReadMessage, trailing: TextButton( onPressed: () { - controller.scrollToEventId( - scrollUpBannerEventId, - ); + controller.scrollToEventId(scrollUpBannerEventId); controller.discardScrollUpBannerEventId(); }, child: Text(L10n.of(context).jump), @@ -299,7 +291,8 @@ class ChatView extends StatelessWidget { ), floatingActionButtonLocation: FloatingActionButtonLocation.miniCenterFloat, - floatingActionButton: controller.showScrollDownButton && + floatingActionButton: + controller.showScrollDownButton && controller.selectedEvents.isEmpty ? Padding( padding: const EdgeInsets.only(bottom: 56.0), @@ -348,10 +341,7 @@ class ChatView extends StatelessWidget { ), ), if (controller.showScrollDownButton) - Divider( - height: 1, - color: theme.dividerColor, - ), + Divider(height: 1, color: theme.dividerColor), if (controller.room.isExtinct) Container( margin: EdgeInsets.all(bottomSheetPadding), @@ -380,14 +370,11 @@ class ChatView extends StatelessWidget { ), child: controller.room.isAbandonedDMRoom == true ? Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, + mainAxisAlignment: .spaceEvenly, children: [ TextButton.icon( style: TextButton.styleFrom( - padding: const EdgeInsets.all( - 16, - ), + padding: const EdgeInsets.all(16), foregroundColor: theme.colorScheme.error, ), @@ -395,15 +382,11 @@ class ChatView extends StatelessWidget { Icons.archive_outlined, ), onPressed: controller.leaveChat, - label: Text( - L10n.of(context).leave, - ), + label: Text(L10n.of(context).leave), ), TextButton.icon( style: TextButton.styleFrom( - padding: const EdgeInsets.all( - 16, - ), + padding: const EdgeInsets.all(16), ), icon: const Icon( Icons.forum_outlined, @@ -416,7 +399,7 @@ class ChatView extends StatelessWidget { ], ) : Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ ReplyDisplay(controller), ChatInputRow(controller), @@ -432,10 +415,7 @@ class ChatView extends StatelessWidget { Container( color: theme.scaffoldBackgroundColor.withAlpha(230), alignment: Alignment.center, - child: const Icon( - Icons.upload_outlined, - size: 100, - ), + child: const Icon(Icons.upload_outlined, size: 100), ), ], ), diff --git a/lib/pages/chat/encryption_button.dart b/lib/pages/chat/encryption_button.dart index a18e10609..594ec4e4b 100644 --- a/lib/pages/chat/encryption_button.dart +++ b/lib/pages/chat/encryption_button.dart @@ -15,11 +15,9 @@ class EncryptionButton extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); return StreamBuilder( - stream: Matrix.of(context) - .client - .onSync - .stream - .where((s) => s.deviceLists != null), + stream: Matrix.of( + context, + ).client.onSync.stream.where((s) => s.deviceLists != null), builder: (context, snapshot) { final shouldBeEncrypted = room.joinRules != JoinRules.public; return FutureBuilder( diff --git a/lib/pages/chat/event_info_dialog.dart b/lib/pages/chat/event_info_dialog.dart index c027e1fb8..9dd0e7bb5 100644 --- a/lib/pages/chat/event_info_dialog.dart +++ b/lib/pages/chat/event_info_dialog.dart @@ -12,21 +12,16 @@ import 'package:fluffychat/widgets/avatar.dart'; extension EventInfoDialogExtension on Event { void showInfoDialog(BuildContext context) => showAdaptiveBottomSheet( - context: context, - builder: (context) => - EventInfoDialog(l10n: L10n.of(context), event: this), - ); + context: context, + builder: (context) => EventInfoDialog(l10n: L10n.of(context), event: this), + ); } class EventInfoDialog extends StatelessWidget { final Event event; final L10n l10n; - const EventInfoDialog({ - required this.event, - required this.l10n, - super.key, - }); + const EventInfoDialog({required this.event, required this.l10n, super.key}); String prettyJson(MatrixEvent event) { const decoder = JsonDecoder(); @@ -79,9 +74,7 @@ class EventInfoDialog extends StatelessWidget { scrollDirection: Axis.horizontal, child: SelectableText( prettyJson(MatrixEvent.fromJson(event.toJson())), - style: TextStyle( - color: theme.colorScheme.onSurface, - ), + style: TextStyle(color: theme.colorScheme.onSurface), ), ), ), @@ -98,9 +91,7 @@ class EventInfoDialog extends StatelessWidget { scrollDirection: Axis.horizontal, child: SelectableText( prettyJson(originalSource), - style: TextStyle( - color: theme.colorScheme.onSurface, - ), + style: TextStyle(color: theme.colorScheme.onSurface), ), ), ), diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index b4730649f..ffccea6c2 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -100,12 +100,13 @@ class AudioPlayerState extends State { onPressed: () { audioPlayer.pause(); audioPlayer.dispose(); - matrix.voiceMessageEventId.value = - matrix.audioPlayer = null; + matrix.voiceMessageEventId.value = matrix.audioPlayer = + null; WidgetsBinding.instance.addPostFrameCallback((_) { - ScaffoldMessenger.of(matrix.context) - .clearMaterialBanners(); + ScaffoldMessenger.of( + matrix.context, + ).clearMaterialBanners(); }); }, icon: const Icon(Icons.close_outlined), @@ -128,8 +129,8 @@ class AudioPlayerState extends State { }); final currentPlayer = matrix.voiceMessageEventId.value != widget.event.eventId - ? null - : matrix.audioPlayer; + ? null + : matrix.audioPlayer; if (currentPlayer != null) { if (currentPlayer.isAtEndPosition) { currentPlayer.seek(Duration.zero); @@ -158,8 +159,9 @@ class AudioPlayerState extends State { ? (progress) { final progressPercentage = progress / fileSize; setState(() { - _downloadProgress = - progressPercentage < 1 ? progressPercentage : null; + _downloadProgress = progressPercentage < 1 + ? progressPercentage + : null; }); } : null, @@ -190,11 +192,9 @@ class AudioPlayerState extends State { }); } catch (e, s) { Logs().v('Could not download audio file', e, s); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(e.toLocalizedString(context)), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); rethrow; } if (!context.mounted) return; @@ -209,9 +209,8 @@ class AudioPlayerState extends State { } audioPlayer.play().onError( - ErrorReporter(context, 'Unable to play audio message') - .onErrorCallback, - ); + ErrorReporter(context, 'Unable to play audio message').onErrorCallback, + ); } void _toggleSpeed() async { @@ -289,8 +288,9 @@ class AudioPlayerState extends State { return ValueListenableBuilder( valueListenable: matrix.voiceMessageEventId, builder: (context, eventId, _) { - final audioPlayer = - eventId != widget.event.eventId ? null : matrix.audioPlayer; + final audioPlayer = eventId != widget.event.eventId + ? null + : matrix.audioPlayer; final fileDescription = widget.event.fileDescription; @@ -317,15 +317,15 @@ class AudioPlayerState extends State { return Padding( padding: const EdgeInsets.all(12.0), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ ConstrainedBox( constraints: const BoxConstraints( maxWidth: FluffyThemes.columnWidth, ), child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ SizedBox( width: buttonSize, @@ -366,9 +366,11 @@ class AudioPlayerState extends State { ), child: Row( children: [ - for (var i = 0; - i < AudioPlayerWidget.wavesCount; - i++) + for ( + var i = 0; + i < AudioPlayerWidget.wavesCount; + i++ + ) Expanded( child: Container( height: 32, @@ -376,13 +378,14 @@ class AudioPlayerState extends State { child: Container( margin: const EdgeInsets.symmetric( - horizontal: 1, - ), + horizontal: 1, + ), decoration: BoxDecoration( color: i < wavePosition ? widget.color - : widget.color - .withAlpha(128), + : widget.color.withAlpha( + 128, + ), borderRadius: BorderRadius.circular(64), ), @@ -396,7 +399,8 @@ class AudioPlayerState extends State { SizedBox( height: 32, child: Slider( - thumbColor: widget.event.senderId == + thumbColor: + widget.event.senderId == widget.event.room.client.userID ? theme.colorScheme.onPrimary : theme.colorScheme.primary, @@ -425,10 +429,7 @@ class AudioPlayerState extends State { width: 36, child: Text( statusText, - style: TextStyle( - color: widget.color, - fontSize: 12, - ), + style: TextStyle(color: widget.color, fontSize: 12), ), ), const SizedBox(width: 8), @@ -442,11 +443,13 @@ class AudioPlayerState extends State { ), secondChild: Material( color: widget.color.withAlpha(64), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), child: InkWell( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), onTap: _toggleSpeed, child: SizedBox( width: 32, @@ -481,8 +484,9 @@ class AudioPlayerState extends State { ), child: Linkify( text: fileDescription, - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), style: TextStyle( color: widget.color, fontSize: widget.fontSize, diff --git a/lib/pages/chat/events/cute_events.dart b/lib/pages/chat/events/cute_events.dart index 91648e082..604537711 100644 --- a/lib/pages/chat/events/cute_events.dart +++ b/lib/pages/chat/events/cute_events.dart @@ -37,13 +37,10 @@ class _CuteContentState extends State { return GestureDetector( onTap: addOverlay, child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: .min, + mainAxisAlignment: .center, children: [ - Text( - widget.event.text, - style: const TextStyle(fontSize: 150), - ), + Text(widget.event.text, style: const TextStyle(fontSize: 150)), if (label != null) Text(label), ], ), @@ -112,10 +109,7 @@ class _CuteEventOverlayState extends State with TickerProviderStateMixin { final List items = List.generate( 50, - (index) => Size( - Random().nextDouble(), - 4 + (Random().nextDouble() * 4), - ), + (index) => Size(Random().nextDouble(), 4 + (Random().nextDouble() * 4)), ); AnimationController? controller; @@ -150,14 +144,13 @@ class _CuteEventOverlayState extends State .map( (position) => Positioned( left: position.width * width, - bottom: (height * + bottom: + (height * .25 * position.height * (controller?.value ?? 0)) - _CuteOverlayContent.size, - child: _CuteOverlayContent( - emoji: widget.emoji, - ), + child: _CuteOverlayContent(emoji: widget.emoji), ), ) .toList(), @@ -186,10 +179,7 @@ class _CuteOverlayContent extends StatelessWidget { Widget build(BuildContext context) { return SizedBox.square( dimension: size, - child: Text( - emoji, - style: const TextStyle(fontSize: 48), - ), + child: Text(emoji, style: const TextStyle(fontSize: 48)), ); } } diff --git a/lib/pages/chat/events/html_message.dart b/lib/pages/chat/events/html_message.dart index a023e412d..3f82806b5 100644 --- a/lib/pages/chat/events/html_message.dart +++ b/lib/pages/chat/events/html_message.dart @@ -141,7 +141,8 @@ class HtmlMessage extends StatelessWidget { if (node is! dom.Element) { return TextSpan(text: node.text); } - final style = atomOneDarkTheme[node.className.split('-').last] ?? + final style = + atomOneDarkTheme[node.className.split('-').last] ?? atomOneDarkTheme['root']; return TextSpan( @@ -151,11 +152,7 @@ class HtmlMessage extends StatelessWidget { } /// Transforms a Node to an InlineSpan. - InlineSpan _renderHtml( - dom.Node node, - BuildContext context, { - int depth = 1, - }) { + InlineSpan _renderHtml(dom.Node node, BuildContext context, {int depth = 1}) { // We must not render elements nested more than 100 elements deep: if (depth >= 100) return const TextSpan(); @@ -245,9 +242,9 @@ class HtmlMessage extends StatelessWidget { final isCheckbox = node.className == 'task-list-item'; final checkboxIndex = isCheckbox ? node.rootElement - .getElementsByClassName('task-list-item') - .indexOf(node) + - 1 + .getElementsByClassName('task-list-item') + .indexOf(node) + + 1 : null; final checkedByReaction = !isCheckbox ? null @@ -283,7 +280,8 @@ class HtmlMessage extends StatelessWidget { activeColor: textColor.withAlpha(64), value: staticallyChecked || checkedByReaction != null, - onChanged: eventId == null || + onChanged: + eventId == null || checkboxIndex == null || staticallyChecked || !room.canSendDefaultMessages || @@ -292,25 +290,21 @@ class HtmlMessage extends StatelessWidget { room.client.userID) ? null : (_) => showFutureLoadingDialog( - context: context, - future: () => checkedByReaction != null - ? room.redactEvent( - checkedByReaction.eventId, - ) - : room.checkCheckbox( - eventId, - checkboxIndex, - ), - ), + context: context, + future: () => checkedByReaction != null + ? room.redactEvent( + checkedByReaction.eventId, + ) + : room.checkCheckbox( + eventId, + checkboxIndex, + ), + ), ), ), ), ), - ..._renderWithLineBreaks( - node.nodes, - context, - depth: depth, - ), + ..._renderWithLineBreaks(node.nodes, context, depth: depth), ], style: TextStyle(fontSize: fontSize, color: textColor), ), @@ -322,12 +316,7 @@ class HtmlMessage extends StatelessWidget { child: Container( padding: const EdgeInsets.only(left: 8.0), decoration: BoxDecoration( - border: Border( - left: BorderSide( - color: textColor, - width: 5, - ), - ), + border: Border(left: BorderSide(color: textColor, width: 5)), ), child: Text.rich( TextSpan( @@ -347,7 +336,8 @@ class HtmlMessage extends StatelessWidget { ); case 'code': final isInline = node.parent?.localName != 'pre'; - final lang = node.className + final lang = + node.className .split(' ') .singleWhereOrNull( (className) => className.startsWith('language-'), @@ -355,8 +345,9 @@ class HtmlMessage extends StatelessWidget { ?.split('language-') .last ?? 'md'; - final highlightedHtml = - highlight.parse(node.text, language: lang).toHtml(); + final highlightedHtml = highlight + .parse(node.text, language: lang) + .toHtml(); final element = parser.parse(highlightedHtml).body; if (element == null) { return const TextSpan(text: 'Unable to render code block!'); @@ -372,14 +363,9 @@ class HtmlMessage extends StatelessWidget { child: Padding( padding: isInline ? const EdgeInsets.symmetric(horizontal: 4.0) - : const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 4.0, - ), + : const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), child: Text.rich( - TextSpan( - children: [_renderCodeBlockNode(element)], - ), + TextSpan(children: [_renderCodeBlockNode(element)]), selectionColor: hightlightTextColor.withAlpha(128), ), ), @@ -448,10 +434,7 @@ class HtmlMessage extends StatelessWidget { ), ], ), - style: TextStyle( - fontSize: fontSize, - color: textColor, - ), + style: TextStyle(fontSize: fontSize, color: textColor), ), ), ), @@ -489,17 +472,13 @@ class HtmlMessage extends StatelessWidget { default: return TextSpan( style: switch (node.localName) { - 'body' => TextStyle( - fontSize: fontSize, - color: textColor, - ), + 'body' => TextStyle(fontSize: fontSize, color: textColor), 'a' => linkStyle, 'strong' => const TextStyle(fontWeight: FontWeight.bold), 'em' || 'i' => const TextStyle(fontStyle: FontStyle.italic), - 'del' || - 's' || - 'strikethrough' => - const TextStyle(decoration: TextDecoration.lineThrough), + 'del' || 's' || 'strikethrough' => const TextStyle( + decoration: TextDecoration.lineThrough, + ), 'u' => const TextStyle(decoration: TextDecoration.underline), 'h1' => TextStyle(fontSize: fontSize * 1.6, height: 2), 'h2' => TextStyle(fontSize: fontSize * 1.5, height: 2), @@ -508,22 +487,19 @@ class HtmlMessage extends StatelessWidget { 'h5' => TextStyle(fontSize: fontSize * 1.2, height: 1.75), 'h6' => TextStyle(fontSize: fontSize * 1.1, height: 1.5), 'span' => TextStyle( - color: node.attributes['color']?.hexToColor ?? - node.attributes['data-mx-color']?.hexToColor ?? - textColor, - backgroundColor: - node.attributes['data-mx-bg-color']?.hexToColor, - ), - 'sup' => - const TextStyle(fontFeatures: [FontFeature.superscripts()]), + color: + node.attributes['color']?.hexToColor ?? + node.attributes['data-mx-color']?.hexToColor ?? + textColor, + backgroundColor: node.attributes['data-mx-bg-color']?.hexToColor, + ), + 'sup' => const TextStyle( + fontFeatures: [FontFeature.superscripts()], + ), 'sub' => const TextStyle(fontFeatures: [FontFeature.subscripts()]), _ => null, }, - children: _renderWithLineBreaks( - node.nodes, - context, - depth: depth, - ), + children: _renderWithLineBreaks(node.nodes, context, depth: depth), ); } } @@ -533,10 +509,7 @@ class HtmlMessage extends StatelessWidget { final element = parser.parse(html).body ?? dom.Element.html(''); return Text.rich( _renderHtml(element, context), - style: TextStyle( - fontSize: fontSize, - color: textColor, - ), + style: TextStyle(fontSize: fontSize, color: textColor), maxLines: limitHeight ? 64 : null, overflow: TextOverflow.fade, selectionColor: textColor.withAlpha(128), @@ -568,13 +541,9 @@ class MatrixPill extends StatelessWidget { splashColor: Colors.transparent, onTap: UrlLauncher(outerContext, uri).launchUrl, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ - Avatar( - mxContent: avatar, - name: name, - size: 16, - ), + Avatar(mxContent: avatar, name: name, size: 16), const SizedBox(width: 6), Text( name, diff --git a/lib/pages/chat/events/image_bubble.dart b/lib/pages/chat/events/image_bubble.dart index 305b83ba8..b42674636 100644 --- a/lib/pages/chat/events/image_bubble.dart +++ b/lib/pages/chat/events/image_bubble.dart @@ -46,8 +46,8 @@ class ImageBubble extends StatelessWidget { Widget _buildPlaceholder(BuildContext context) { final String blurHashString = event.infoMap['xyz.amorgan.blurhash'] is String - ? event.infoMap['xyz.amorgan.blurhash'] - : 'LEHV6nWB2yk8pyo0adR*.7kCMdnj'; + ? event.infoMap['xyz.amorgan.blurhash'] + : 'LEHV6nWB2yk8pyo0adR*.7kCMdnj'; return SizedBox( width: width, height: height, @@ -68,11 +68,8 @@ class ImageBubble extends StatelessWidget { if (!tapToView) return; showDialog( context: context, - builder: (_) => ImageViewer( - event, - timeline: timeline, - outerContext: context, - ), + builder: (_) => + ImageViewer(event, timeline: timeline, outerContext: context), ); } @@ -94,7 +91,7 @@ class ImageBubble extends StatelessWidget { } return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, spacing: 8, children: [ Material( @@ -131,22 +128,21 @@ class ImageBubble extends StatelessWidget { SizedBox( width: width, child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Linkify( text: fileDescription, textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 5a915d0a5..9943eb6fe 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -107,10 +107,12 @@ class Message extends StatelessWidget { final alignment = ownMessage ? Alignment.topRight : Alignment.topLeft; var color = theme.colorScheme.surfaceContainerHigh; - final displayTime = event.type == EventTypes.RoomCreate || + final displayTime = + event.type == EventTypes.RoomCreate || nextEvent == null || !event.originServerTs.sameEnvironment(nextEvent!.originServerTs); - final nextEventSameSender = nextEvent != null && + final nextEventSameSender = + nextEvent != null && { EventTypes.Message, EventTypes.Sticker, @@ -119,7 +121,8 @@ class Message extends StatelessWidget { nextEvent!.senderId == event.senderId && !displayTime; - final previousEventSameSender = previousEvent != null && + final previousEventSameSender = + previousEvent != null && { EventTypes.Message, EventTypes.Sticker, @@ -128,17 +131,19 @@ class Message extends StatelessWidget { previousEvent!.senderId == event.senderId && previousEvent!.originServerTs.sameEnvironment(event.originServerTs); - final textColor = - ownMessage ? theme.onBubbleColor : theme.colorScheme.onSurface; + final textColor = ownMessage + ? theme.onBubbleColor + : theme.colorScheme.onSurface; final linkColor = ownMessage ? theme.brightness == Brightness.light - ? theme.colorScheme.primaryFixed - : theme.colorScheme.onTertiaryContainer + ? theme.colorScheme.primaryFixed + : theme.colorScheme.onTertiaryContainer : theme.colorScheme.primary; - final rowMainAxisAlignment = - ownMessage ? MainAxisAlignment.end : MainAxisAlignment.start; + final rowMainAxisAlignment = ownMessage + ? MainAxisAlignment.end + : MainAxisAlignment.start; final displayEvent = event.getDisplayEvent(timeline); const hardCorner = Radius.circular(4); @@ -146,12 +151,15 @@ class Message extends StatelessWidget { final borderRadius = BorderRadius.only( topLeft: !ownMessage && nextEventSameSender ? hardCorner : roundedCorner, topRight: ownMessage && nextEventSameSender ? hardCorner : roundedCorner, - bottomLeft: - !ownMessage && previousEventSameSender ? hardCorner : roundedCorner, - bottomRight: - ownMessage && previousEventSameSender ? hardCorner : roundedCorner, + bottomLeft: !ownMessage && previousEventSameSender + ? hardCorner + : roundedCorner, + bottomRight: ownMessage && previousEventSameSender + ? hardCorner + : roundedCorner, ); - final noBubble = ({ + final noBubble = + ({ MessageTypes.Video, MessageTypes.Image, MessageTypes.Sticker, @@ -165,8 +173,9 @@ class Message extends StatelessWidget { event.numberEmotes <= 3); if (ownMessage) { - color = - displayEvent.status.isError ? Colors.redAccent : theme.bubbleColor; + color = displayEvent.status.isError + ? Colors.redAccent + : theme.bubbleColor; } final resetAnimateIn = this.resetAnimateIn; @@ -176,10 +185,7 @@ class Message extends StatelessWidget { if (singleSelected) { sentReactions.addAll( event - .aggregatedEvents( - timeline, - RelationshipTypes.reaction, - ) + .aggregatedEvents(timeline, RelationshipTypes.reaction) .where( (event) => event.senderId == event.room.client.userID && @@ -194,11 +200,15 @@ class Message extends StatelessWidget { ); } - final showReceiptsRow = - event.hasAggregatedEvents(timeline, RelationshipTypes.reaction); + final showReceiptsRow = event.hasAggregatedEvents( + timeline, + RelationshipTypes.reaction, + ); - final threadChildren = - event.aggregatedEvents(timeline, RelationshipTypes.thread); + final threadChildren = event.aggregatedEvents( + timeline, + RelationshipTypes.thread, + ); final showReactionPicker = singleSelected && event.room.canSendDefaultMessages; @@ -210,9 +220,7 @@ class Message extends StatelessWidget { key: ValueKey(event.eventId), background: const Padding( padding: EdgeInsets.symmetric(horizontal: 12.0), - child: Center( - child: Icon(Icons.check_outlined), - ), + child: Center(child: Icon(Icons.check_outlined)), ), direction: AppSettings.swipeRightToLeftToReply.value ? SwipeDirection.endToStart @@ -229,9 +237,8 @@ class Message extends StatelessWidget { bottom: previousEventSameSender ? 1.0 : 4.0, ), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - ownMessage ? CrossAxisAlignment.end : CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: ownMessage ? .end : .start, children: [ if (displayTime || selected) Padding( @@ -242,8 +249,9 @@ class Message extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(top: 4.0), child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius * 2), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius * 2, + ), color: theme.colorScheme.surface.withAlpha(128), child: Padding( padding: const EdgeInsets.symmetric( @@ -305,13 +313,13 @@ class Message extends StatelessWidget { ), color: selected || highlightMarker ? theme.colorScheme.secondaryContainer - .withAlpha(128) + .withAlpha(128) : Colors.transparent, ), ), ), Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: .start, mainAxisAlignment: rowMainAxisAlignment, children: [ if (longPressSelect && !event.redacted) @@ -336,18 +344,17 @@ class Message extends StatelessWidget { child: SizedBox( width: 16, height: 16, - child: event.status == - EventStatus.error + child: + event.status == EventStatus.error ? const Icon( Icons.error, color: Colors.red, ) : event.fileSendingStatus != null - ? const CircularProgressIndicator - .adaptive( - strokeWidth: 1, - ) - : null, + ? const CircularProgressIndicator.adaptive( + strokeWidth: 1, + ) + : null, ), ), ) @@ -355,17 +362,18 @@ class Message extends StatelessWidget { FutureBuilder( future: event.fetchSenderUser(), builder: (context, snapshot) { - final user = snapshot.data ?? + final user = + snapshot.data ?? event.senderFromMemoryOrFallback; return Avatar( mxContent: user.avatarUrl, name: user.calcDisplayname(), onTap: () => showMemberActionsPopupMenu( - context: context, - user: user, - onMention: onMention, - ), + context: context, + user: user, + onMention: onMention, + ), presenceUserId: user.stateKey, presenceBackgroundColor: wallpaperMode ? Colors.transparent @@ -375,9 +383,8 @@ class Message extends StatelessWidget { ), Expanded( child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + crossAxisAlignment: .start, + mainAxisSize: .min, children: [ if (!nextEventSameSender) Padding( @@ -385,16 +392,16 @@ class Message extends StatelessWidget { left: 8.0, bottom: 4, ), - child: ownMessage || + child: + ownMessage || event.room.isDirectChat ? const SizedBox(height: 12) : FutureBuilder( - future: - event.fetchSenderUser(), - builder: - (context, snapshot) { - final displayname = snapshot - .data + future: event + .fetchSenderUser(), + builder: (context, snapshot) { + final displayname = + snapshot.data ?.calcDisplayname() ?? event .senderFromMemoryOrFallback @@ -405,29 +412,30 @@ class Message extends StatelessWidget { fontSize: 11, fontWeight: FontWeight.bold, - color: (theme.brightness == + color: + (theme.brightness == Brightness .light ? displayname - .color + .color : displayname - .lightColorText), + .lightColorText), shadows: !wallpaperMode - ? null - : [ - const Shadow( - offset: - Offset( + ? null + : [ + const Shadow( + offset: + Offset( 0.0, 0.0, ), - blurRadius: - 3, - color: Colors - .black, - ), - ], + blurRadius: + 3, + color: Colors + .black, + ), + ], ), maxLines: 1, overflow: TextOverflow @@ -438,25 +446,25 @@ class Message extends StatelessWidget { ), Container( alignment: alignment, - padding: - const EdgeInsets.only(left: 8), + padding: const EdgeInsets.only( + left: 8, + ), child: GestureDetector( onLongPress: longPressSelect ? null : () { - HapticFeedback - .heavyImpact(); + HapticFeedback.heavyImpact(); onSelect(event); }, child: AnimatedOpacity( opacity: animateIn ? 0 : event.messageType == - MessageTypes - .BadEncrypted || - event.status.isSending - ? 0.5 - : 1, + MessageTypes + .BadEncrypted || + event.status.isSending + ? 0.5 + : 1, duration: FluffyThemes .animationDuration, curve: @@ -471,7 +479,8 @@ class Message extends StatelessWidget { clipBehavior: Clip.antiAlias, child: BubbleBackground( colors: colors, - ignore: noBubble || + ignore: + noBubble || !ownMessage || MediaQuery.highContrastOf( context, @@ -482,24 +491,24 @@ class Message extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), + AppConfig + .borderRadius, + ), ), constraints: const BoxConstraints( - maxWidth: FluffyThemes - .columnWidth * - 1.5, - ), + maxWidth: + FluffyThemes + .columnWidth * + 1.5, + ), child: Column( - mainAxisSize: - MainAxisSize.min, + mainAxisSize: .min, crossAxisAlignment: CrossAxisAlignment .start, children: [ - if (event - .inReplyToEventId( + if (event.inReplyToEventId( includingFallback: false, ) != @@ -507,21 +516,23 @@ class Message extends StatelessWidget { FutureBuilder( future: event .getReplyEvent( - timeline, - ), - builder: ( - BuildContext + timeline, + ), + builder: + ( + BuildContext context, - snapshot, - ) { - final replyEvent = - snapshot + snapshot, + ) { + final replyEvent = + snapshot .hasData ? snapshot - .data! + .data! : Event( eventId: - event.inReplyToEventId() ?? '\$fake_event_id', + event.inReplyToEventId() ?? + '\$fake_event_id', content: { 'msgtype': 'm.text', @@ -539,45 +550,42 @@ class Message extends StatelessWidget { originServerTs: DateTime.now(), ); - return Padding( - padding: - const EdgeInsets - .only( - left: 16, - right: 16, - top: 8, - ), - child: Material( - color: Colors - .transparent, - borderRadius: - ReplyContent - .borderRadius, - child: - InkWell( - borderRadius: - ReplyContent - .borderRadius, - onTap: () => - scrollToEventId( - replyEvent - .eventId, - ), - child: - AbsorbPointer( - child: - ReplyContent( - replyEvent, - ownMessage: - ownMessage, - timeline: - timeline, + return Padding( + padding: + const EdgeInsets.only( + left: + 16, + right: + 16, + top: + 8, + ), + child: Material( + color: Colors + .transparent, + borderRadius: + ReplyContent + .borderRadius, + child: InkWell( + borderRadius: + ReplyContent.borderRadius, + onTap: () => scrollToEventId( + replyEvent + .eventId, + ), + child: AbsorbPointer( + child: ReplyContent( + replyEvent, + ownMessage: + ownMessage, + timeline: + timeline, + ), + ), ), ), - ), - ), - ); - }, + ); + }, ), MessageContent( displayEvent, @@ -591,18 +599,17 @@ class Message extends StatelessWidget { ), if (event .hasAggregatedEvents( - timeline, - RelationshipTypes - .edit, - )) + timeline, + RelationshipTypes + .edit, + )) Padding( padding: - const EdgeInsets - .only( - bottom: 8.0, - left: 16.0, - right: 16.0, - ), + const EdgeInsets.only( + bottom: 8.0, + left: 16.0, + right: 16.0, + ), child: Row( mainAxisSize: MainAxisSize @@ -614,22 +621,21 @@ class Message extends StatelessWidget { .edit_outlined, color: textColor .withAlpha( - 164, - ), + 164, + ), size: 14, ), Text( displayEvent .originServerTs .localizedTimeShort( - context, - ), - style: - TextStyle( + context, + ), + style: TextStyle( color: textColor .withAlpha( - 164, - ), + 164, + ), fontSize: 11, ), @@ -657,46 +663,43 @@ class Message extends StatelessWidget { ? Padding( padding: const EdgeInsets.all( - 4.0, - ), + 4.0, + ), child: Material( elevation: 4, borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), + AppConfig + .borderRadius, + ), shadowColor: theme - .colorScheme.surface + .colorScheme + .surface .withAlpha(128), - child: - SingleChildScrollView( + child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( - mainAxisSize: - MainAxisSize.min, + mainAxisSize: .min, children: [ - ...AppConfig - .defaultReactions - .map( - (emoji) => - IconButton( + ...AppConfig.defaultReactions.map( + ( + emoji, + ) => IconButton( padding: EdgeInsets .zero, icon: Center( - child: - Opacity( - opacity: sentReactions - .contains( - emoji, - ) + child: Opacity( + opacity: + sentReactions.contains( + emoji, + ) ? 0.33 : 1, child: Text( emoji, - style: - const TextStyle( + style: const TextStyle( fontSize: 20, ), @@ -708,19 +711,20 @@ class Message extends StatelessWidget { ), onPressed: sentReactions - .contains( - emoji, - ) - ? null - : () { - onSelect( - event, - ); - event.room.sendReaction( - event.eventId, - emoji, - ); - }, + .contains( + emoji, + ) + ? null + : () { + onSelect( + event, + ); + event.room.sendReaction( + event + .eventId, + emoji, + ); + }, ), ), IconButton( @@ -731,72 +735,55 @@ class Message extends StatelessWidget { tooltip: L10n.of( context, ).customReaction, - onPressed: - () async { - final emoji = - await showAdaptiveBottomSheet< - String>( + onPressed: () async { + final emoji = await showAdaptiveBottomSheet( context: context, - builder: - (context) => - Scaffold( - appBar: - AppBar( - title: - Text( - L10n.of(context) - .customReaction, - ), - leading: - CloseButton( - onPressed: - () => - Navigator.of( + builder: (context) => Scaffold( + appBar: AppBar( + title: Text( + L10n.of( context, - ).pop( - null, - ), + ).customReaction, + ), + leading: CloseButton( + onPressed: () => Navigator.of( + context, + ).pop(null), ), ), - body: - SizedBox( + body: SizedBox( height: double .infinity, - child: - EmojiPicker( - onEmojiSelected: ( - _, - emoji, - ) => - Navigator.of( - context, - ).pop( - emoji - .emoji, - ), - config: - Config( - locale: - Localizations.localeOf(context), - emojiViewConfig: - const EmojiViewConfig( + child: EmojiPicker( + onEmojiSelected: + ( + _, + emoji, + ) => + Navigator.of( + context, + ).pop( + emoji.emoji, + ), + config: Config( + locale: Localizations.localeOf( + context, + ), + emojiViewConfig: const EmojiViewConfig( backgroundColor: Colors.transparent, ), - bottomActionBarConfig: - const BottomActionBarConfig( + bottomActionBarConfig: const BottomActionBarConfig( enabled: false, ), - categoryViewConfig: - CategoryViewConfig( + categoryViewConfig: CategoryViewConfig( initCategory: Category.SMILEYS, backspaceColor: theme.colorScheme.primary, - iconColor: - theme.colorScheme.primary.withAlpha( + iconColor: theme.colorScheme.primary.withAlpha( 128, ), iconColorSelected: @@ -806,10 +793,8 @@ class Message extends StatelessWidget { backgroundColor: theme.colorScheme.surface, ), - skinToneConfig: - SkinToneConfig( - dialogBackgroundColor: - Color.lerp( + skinToneConfig: SkinToneConfig( + dialogBackgroundColor: Color.lerp( theme.colorScheme.surface, theme.colorScheme.primaryContainer, 0.75, @@ -828,17 +813,18 @@ class Message extends StatelessWidget { } if (sentReactions .contains( - emoji, - )) { + emoji, + )) { return; } onSelect(event); await event.room .sendReaction( - event.eventId, - emoji, - ); + event + .eventId, + emoji, + ); }, ), ], @@ -904,10 +890,7 @@ class Message extends StatelessWidget { onPressed: () => enterThread(event.eventId), icon: const Icon(Icons.message), label: Text( - '${L10n.of(context).countReplies(threadChildren.length)} | ${threadChildren.first.calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)), - withSenderNamePrefix: true, - )}', + '${L10n.of(context).countReplies(threadChildren.length)} | ${threadChildren.first.calcLocalizedBodyFallback(MatrixLocals(L10n.of(context)), withSenderNamePrefix: true)}', maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -933,8 +916,9 @@ class Message extends StatelessWidget { vertical: 2, ), decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 3), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 3, + ), color: theme.colorScheme.surface.withAlpha(128), ), child: Text( @@ -1005,8 +989,10 @@ class BubblePainter extends CustomPainter { final scrollableRect = Offset.zero & scrollableBox.size; final bubbleBox = context.findRenderObject() as RenderBox; - final origin = - bubbleBox.localToGlobal(Offset.zero, ancestor: scrollableBox); + final origin = bubbleBox.localToGlobal( + Offset.zero, + ancestor: scrollableBox, + ); final paint = Paint() ..shader = ui.Gradient.linear( scrollableRect.topCenter, diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index 833291068..792c63814 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -50,9 +50,7 @@ class MessageContent extends StatelessWidget { if (event.content['can_request_session'] != true) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - event.calcLocalizedBodyFallback(MatrixLocals(l10n)), - ), + content: Text(event.calcLocalizedBodyFallback(MatrixLocals(l10n))), ), ); return; @@ -91,11 +89,7 @@ class MessageContent extends StatelessWidget { trailing: const Icon(Icons.lock_outlined), ), const Divider(), - Text( - event.calcLocalizedBodyFallback( - MatrixLocals(l10n), - ), - ), + Text(event.calcLocalizedBodyFallback(MatrixLocals(l10n))), ], ), ), @@ -116,8 +110,9 @@ class MessageContent extends StatelessWidget { case MessageTypes.Image: case MessageTypes.Sticker: if (event.redacted) continue textmessage; - final maxSize = - event.messageType == MessageTypes.Sticker ? 128.0 : 256.0; + final maxSize = event.messageType == MessageTypes.Sticker + ? 128.0 + : 256.0; final w = event.content .tryGetMap('info') ?.tryGet('w'); @@ -152,12 +147,12 @@ class MessageContent extends StatelessWidget { return CuteContent(event); case MessageTypes.Audio: if (PlatformInfos.isMobile || - PlatformInfos.isMacOS || - PlatformInfos.isWeb - // Disabled until https://github.com/bleonard252/just_audio_mpv/issues/3 - // is fixed - // || PlatformInfos.isLinux - ) { + PlatformInfos.isMacOS || + PlatformInfos.isWeb + // Disabled until https://github.com/bleonard252/just_audio_mpv/issues/3 + // is fixed + // || PlatformInfos.isLinux + ) { return AudioPlayerWidget( event, color: textColor, @@ -193,8 +188,9 @@ class MessageContent extends StatelessWidget { fontSize: fontSize, ); case MessageTypes.Location: - final geoUri = - Uri.tryParse(event.content.tryGet('geo_uri')!); + final geoUri = Uri.tryParse( + event.content.tryGet('geo_uri')!, + ); if (geoUri != null && geoUri.scheme == 'geo') { final latlong = geoUri.path .split(';') @@ -206,7 +202,7 @@ class MessageContent extends StatelessWidget { latlong.first != null && latlong.last != null) { return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ MapBubble( latitude: latlong.first!, @@ -215,8 +211,10 @@ class MessageContent extends StatelessWidget { const SizedBox(height: 6), OutlinedButton.icon( icon: Icon(Icons.location_on_outlined, color: textColor), - onPressed: - UrlLauncher(context, geoUri.toString()).launchUrl, + onPressed: UrlLauncher( + context, + geoUri.toString(), + ).launchUrl, label: Text( L10n.of(context).openInMaps, style: TextStyle(color: textColor), @@ -248,25 +246,25 @@ class MessageContent extends StatelessWidget { html = '* $html'; } - final bigEmotes = event.onlyEmotes && + final bigEmotes = + event.onlyEmotes && event.numberEmotes > 0 && event.numberEmotes <= 3; return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: HtmlMessage( html: html, textColor: textColor, room: event.room, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize * (bigEmotes ? 5 : 1), limitHeight: !selected, linkStyle: TextStyle( color: linkColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, @@ -352,16 +350,14 @@ class RedactionWidget extends StatelessWidget { future: event.redactedBecause?.fetchSenderUser(), builder: (context, snapshot) { final reason = event.redactedBecause?.content.tryGet('reason'); - final redactedBy = snapshot.data?.calcDisplayname() ?? + final redactedBy = + snapshot.data?.calcDisplayname() ?? event.redactedBecause?.senderId.localpart ?? L10n.of(context).user; return _ButtonContent( label: reason == null ? L10n.of(context).redactedBy(redactedBy) - : L10n.of(context).redactedByBecause( - redactedBy, - reason, - ), + : L10n.of(context).redactedByBecause(redactedBy, reason), icon: '🗑️', textColor: buttonTextColor.withAlpha(128), onPressed: () => onInfoTab!(event), @@ -390,18 +386,12 @@ class _ButtonContent extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: InkWell( onTap: onPressed, child: Text( '$icon $label', - style: TextStyle( - color: textColor, - fontSize: fontSize, - ), + style: TextStyle(color: textColor, fontSize: fontSize), ), ), ); diff --git a/lib/pages/chat/events/message_download_content.dart b/lib/pages/chat/events/message_download_content.dart index 18b5c0b07..46d5167ca 100644 --- a/lib/pages/chat/events/message_download_content.dart +++ b/lib/pages/chat/events/message_download_content.dart @@ -27,15 +27,15 @@ class MessageDownloadContent extends StatelessWidget { final filetype = (filename.contains('.') ? filename.split('.').last.toUpperCase() : event.content - .tryGetMap('info') - ?.tryGet('mimetype') - ?.toUpperCase() ?? - 'UNKNOWN'); + .tryGetMap('info') + ?.tryGet('mimetype') + ?.toUpperCase() ?? + 'UNKNOWN'); final sizeString = event.sizeString ?? '?MB'; final fileDescription = event.fileDescription; return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, spacing: 8, children: [ Material( @@ -47,7 +47,7 @@ class MessageDownloadContent extends StatelessWidget { width: 400, padding: const EdgeInsets.all(16.0), child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, spacing: 16, children: [ CircleAvatar( @@ -56,8 +56,8 @@ class MessageDownloadContent extends StatelessWidget { ), Flexible( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + crossAxisAlignment: .start, + mainAxisSize: .min, children: [ Text( filename, @@ -93,13 +93,15 @@ class MessageDownloadContent extends StatelessWidget { textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, diff --git a/lib/pages/chat/events/message_reactions.dart b/lib/pages/chat/events/message_reactions.dart index dede458aa..5f5b4aa2b 100644 --- a/lib/pages/chat/events/message_reactions.dart +++ b/lib/pages/chat/events/message_reactions.dart @@ -17,8 +17,10 @@ class MessageReactions extends StatelessWidget { @override Widget build(BuildContext context) { - final allReactionEvents = - event.aggregatedEvents(timeline, RelationshipTypes.reaction); + final allReactionEvents = event.aggregatedEvents( + timeline, + RelationshipTypes.reaction, + ); final reactionMap = {}; final client = Matrix.of(context).client; @@ -113,7 +115,7 @@ class _Reaction extends StatelessWidget { Widget content; if (reactionKey.startsWith('mxc://')) { content = Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ MxcImage( uri: Uri.parse(reactionKey), @@ -190,17 +192,14 @@ class _AdaptableReactorsDialog extends StatelessWidget { final Client? client; final _ReactionEntry? reactionEntry; - const _AdaptableReactorsDialog({ - this.client, - this.reactionEntry, - }); + const _AdaptableReactorsDialog({this.client, this.reactionEntry}); Future show(BuildContext context) => showAdaptiveDialog( - context: context, - builder: (context) => this, - barrierDismissible: true, - useRootNavigator: false, - ); + context: context, + builder: (context) => this, + barrierDismissible: true, + useRootNavigator: false, + ); @override Widget build(BuildContext context) { @@ -226,9 +225,6 @@ class _AdaptableReactorsDialog extends StatelessWidget { final title = Center(child: Text(reactionEntry!.key)); - return AlertDialog.adaptive( - title: title, - content: body, - ); + return AlertDialog.adaptive(title: title, content: body); } } diff --git a/lib/pages/chat/events/poll.dart b/lib/pages/chat/events/poll.dart index af948d70f..e6baeb7ce 100644 --- a/lib/pages/chat/events/poll.dart +++ b/lib/pages/chat/events/poll.dart @@ -24,10 +24,8 @@ class PollWidget extends StatelessWidget { super.key, }); - void _endPoll(BuildContext context) => showFutureLoadingDialog( - context: context, - future: () => event.endPoll(), - ); + void _endPoll(BuildContext context) => + showFutureLoadingDialog(context: context, future: () => event.endPoll()); void _toggleVote( BuildContext context, @@ -60,20 +58,19 @@ class PollWidget extends StatelessWidget { } final responses = event.getPollResponses(timeline); final pollHasBeenEnded = event.getPollHasBeenEnded(timeline); - final canVote = event.room.canSendEvent(PollEventContent.responseType) && + final canVote = + event.room.canSendEvent(PollEventContent.responseType) && !pollHasBeenEnded; final maxPolls = responses.length; final answersVisible = eventContent.pollStartContent.kind == PollKind.disclosed || - pollHasBeenEnded; + pollHasBeenEnded; return Padding( - padding: const EdgeInsets.symmetric( - vertical: 8, - ), + padding: const EdgeInsets.symmetric(vertical: 8), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 16), @@ -82,13 +79,15 @@ class PollWidget extends StatelessWidget { textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, @@ -97,99 +96,101 @@ class PollWidget extends StatelessWidget { ), ), Divider(color: linkColor.withAlpha(64)), - ...eventContent.pollStartContent.answers.map( - (answer) { - final votedUserIds = responses.entries - .where((entry) => entry.value.contains(answer.id)) - .map((entry) => entry.key) - .toSet(); - return Material( - color: Colors.transparent, - clipBehavior: Clip.hardEdge, - child: CheckboxListTile.adaptive( - value: responses[event.room.client.userID!] - ?.contains(answer.id) ?? - false, - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - checkboxScaleFactor: 1.5, - checkboxShape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(32), + ...eventContent.pollStartContent.answers.map((answer) { + final votedUserIds = responses.entries + .where((entry) => entry.value.contains(answer.id)) + .map((entry) => entry.key) + .toSet(); + return Material( + color: Colors.transparent, + clipBehavior: Clip.hardEdge, + child: CheckboxListTile.adaptive( + value: + responses[event.room.client.userID!]?.contains(answer.id) ?? + false, + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + checkboxScaleFactor: 1.5, + checkboxShape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(32), + ), + onChanged: !canVote + ? null + : (_) => _toggleVote( + context, + answer.id, + eventContent.pollStartContent.maxSelections, + ), + title: Text( + answer.mText, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: textColor, + fontSize: + AppConfig.messageFontSize * + AppSettings.fontSizeFactor.value, ), - onChanged: !canVote - ? null - : (_) => _toggleVote( - context, - answer.id, - eventContent.pollStartContent.maxSelections, - ), - title: Text( - answer.mText, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: textColor, - fontSize: AppConfig.messageFontSize * - AppSettings.fontSizeFactor.value, - ), - ), - subtitle: answersVisible - ? Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - Text( - L10n.of(context) - .countVotes(votedUserIds.length), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: linkColor, - fontSize: + ), + subtitle: answersVisible + ? Column( + crossAxisAlignment: .start, + mainAxisSize: .min, + children: [ + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + Text( + L10n.of( + context, + ).countVotes(votedUserIds.length), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: linkColor, + fontSize: + 12 * AppSettings.fontSizeFactor.value, + ), + ), + const SizedBox(width: 2), + ...votedUserIds.map((userId) { + final user = event.room + .getState(EventTypes.RoomMember, userId) + ?.asUser(event.room); + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 2.0, + ), + child: Avatar( + mxContent: user?.avatarUrl, + name: + user?.calcDisplayname() ?? + userId.localpart, + size: 12 * AppSettings.fontSizeFactor.value, ), - ), - const SizedBox(width: 2), - ...votedUserIds.map((userId) { - final user = event.room - .getState(EventTypes.RoomMember, userId) - ?.asUser(event.room); - return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 2.0, - ), - child: Avatar( - mxContent: user?.avatarUrl, - name: user?.calcDisplayname() ?? - userId.localpart, - size: 12 * - AppSettings.fontSizeFactor.value, - ), - ); - }), - const SizedBox(width: 2), - ], - ), + ); + }), + const SizedBox(width: 2), + ], ), - LinearProgressIndicator( - color: linkColor, - backgroundColor: linkColor.withAlpha(128), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), - value: maxPolls == 0 - ? 0 - : votedUserIds.length / maxPolls, + ), + LinearProgressIndicator( + color: linkColor, + backgroundColor: linkColor.withAlpha(128), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, ), - ], - ) - : null, - ), - ); - }, - ), + value: maxPolls == 0 + ? 0 + : votedUserIds.length / maxPolls, + ), + ], + ) + : null, + ), + ); + }), if (!pollHasBeenEnded && event.senderId == event.room.client.userID) Padding( padding: const EdgeInsets.symmetric(horizontal: 16), diff --git a/lib/pages/chat/events/reply_content.dart b/lib/pages/chat/events/reply_content.dart index 10e6c2351..05934d2fd 100644 --- a/lib/pages/chat/events/reply_content.dart +++ b/lib/pages/chat/events/reply_content.dart @@ -29,21 +29,22 @@ class ReplyContent extends StatelessWidget { final theme = Theme.of(context); final timeline = this.timeline; - final displayEvent = - timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent; + final displayEvent = timeline != null + ? replyEvent.getDisplayEvent(timeline) + : replyEvent; final fontSize = AppConfig.messageFontSize * AppSettings.fontSizeFactor.value; final color = theme.brightness == Brightness.dark ? theme.colorScheme.onTertiaryContainer : ownMessage - ? theme.colorScheme.tertiaryContainer - : theme.colorScheme.tertiary; + ? theme.colorScheme.tertiaryContainer + : theme.colorScheme.tertiary; return Material( color: Colors.transparent, borderRadius: borderRadius, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Container( width: 5, @@ -56,8 +57,8 @@ class ReplyContent extends StatelessWidget { const SizedBox(width: 6), Flexible( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: .start, + mainAxisAlignment: .center, children: [ FutureBuilder( initialData: displayEvent.senderFromMemoryOrFallback, @@ -87,8 +88,8 @@ class ReplyContent extends StatelessWidget { color: theme.brightness == Brightness.dark ? theme.colorScheme.onSurface : ownMessage - ? theme.colorScheme.onTertiary - : theme.colorScheme.onSurface, + ? theme.colorScheme.onTertiary + : theme.colorScheme.onSurface, fontSize: fontSize, ), ), diff --git a/lib/pages/chat/events/room_creation_state_event.dart b/lib/pages/chat/events/room_creation_state_event.dart index 0cac1723e..f1358a3c8 100644 --- a/lib/pages/chat/events/room_creation_state_event.dart +++ b/lib/pages/chat/events/room_creation_state_event.dart @@ -30,7 +30,7 @@ class RoomCreationStateEvent extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(16.0), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Avatar( mxContent: event.room.avatar, diff --git a/lib/pages/chat/events/state_message.dart b/lib/pages/chat/events/state_message.dart index 9ef9d4e7a..196a85a02 100644 --- a/lib/pages/chat/events/state_message.dart +++ b/lib/pages/chat/events/state_message.dart @@ -35,8 +35,9 @@ class StateMessage extends StatelessWidget { padding: const EdgeInsets.all(4), child: Material( color: theme.colorScheme.surface.withAlpha(128), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 3), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 3, + ), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 8.0, diff --git a/lib/pages/chat/events/video_player.dart b/lib/pages/chat/events/video_player.dart index 5635bd23f..d0593cb4a 100644 --- a/lib/pages/chat/events/video_player.dart +++ b/lib/pages/chat/events/video_player.dart @@ -35,8 +35,10 @@ class EventVideoPlayer extends StatelessWidget { Widget build(BuildContext context) { final supportsVideoPlayer = PlatformInfos.supportsVideoPlayer; - final blurHash = (event.infoMap as Map) - .tryGet('xyz.amorgan.blurhash') ?? + final blurHash = + (event.infoMap as Map).tryGet( + 'xyz.amorgan.blurhash', + ) ?? fallbackBlurHash; final fileDescription = event.fileDescription; const maxDimension = 300.0; @@ -49,11 +51,12 @@ class EventVideoPlayer extends StatelessWidget { final height = videoHeight / modifier; final durationInt = infoMap?.tryGet('duration'); - final duration = - durationInt == null ? null : Duration(milliseconds: durationInt); + final duration = durationInt == null + ? null + : Duration(milliseconds: durationInt); return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, spacing: 8, children: [ Material( @@ -128,22 +131,21 @@ class EventVideoPlayer extends StatelessWidget { SizedBox( width: width, child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Linkify( text: fileDescription, textScaleFactor: MediaQuery.textScalerOf(context).scale(1), style: TextStyle( color: textColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, ), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: linkColor, - fontSize: AppSettings.fontSizeFactor.value * + fontSize: + AppSettings.fontSizeFactor.value * AppConfig.messageFontSize, decoration: TextDecoration.underline, decorationColor: linkColor, diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index b1073fe6a..a6e52549a 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -62,10 +62,7 @@ class InputBar extends StatelessWidget { final commandSearch = commandMatch[1]!.toLowerCase(); for (final command in room.client.commands.keys) { if (command.contains(commandSearch)) { - ret.add({ - 'type': 'command', - 'name': command, - }); + ret.add({'type': 'command', 'name': command}); } if (ret.length > maxResults) return ret; @@ -107,8 +104,8 @@ class InputBar extends StatelessWidget { 'type': 'emote', 'name': emote.key, 'pack': packSearch, - 'pack_avatar_url': - emotePacks[packSearch]!.pack.avatarUrl?.toString(), + 'pack_avatar_url': emotePacks[packSearch]!.pack.avatarUrl + ?.toString(), 'pack_display_name': emotePacks[packSearch]!.pack.displayName ?? packSearch, 'mxc': emote.value.url.toString(), @@ -159,8 +156,9 @@ class InputBar extends StatelessWidget { for (final user in room.getParticipants()) { if ((user.displayName != null && (user.displayName!.toLowerCase().contains(userSearch) || - slugify(user.displayName!.toLowerCase()) - .contains(userSearch))) || + slugify( + user.displayName!.toLowerCase(), + ).contains(userSearch))) || user.id.split(':')[0].toLowerCase().contains(userSearch)) { ret.add({ 'type': 'user', @@ -258,11 +256,7 @@ class InputBar extends StatelessWidget { style: const TextStyle(fontSize: 16), ), ), - title: Text( - label, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), + title: Text(label, maxLines: 1, overflow: TextOverflow.ellipsis), ), ); } @@ -280,7 +274,7 @@ class InputBar extends StatelessWidget { isThumbnail: false, ), title: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: .center, children: [ Text(suggestion['name']!), Expanded( @@ -311,7 +305,8 @@ class InputBar extends StatelessWidget { onTap: () => onSelected(suggestion), leading: Avatar( mxContent: url, - name: suggestion.tryGet('displayname') ?? + name: + suggestion.tryGet('displayname') ?? suggestion.tryGet('mxid'), size: size, client: client, @@ -323,8 +318,10 @@ class InputBar extends StatelessWidget { } String insertSuggestion(Map suggestion) { - final replaceText = - controller!.text.substring(0, controller!.selection.baseOffset); + final replaceText = controller!.text.substring( + 0, + controller!.selection.baseOffset, + ); var startText = ''; final afterText = replaceText == controller!.text ? '' @@ -409,10 +406,7 @@ class InputBar extends StatelessWidget { bytes: data, name: content.uri.split('/').last, ); - room.sendFileEvent( - file, - shrinkImageMaxDimension: 1600, - ); + room.sendFileEvent(file, shrinkImageMaxDimension: 1600); }, ), minLines: minLines, diff --git a/lib/pages/chat/pinned_events.dart b/lib/pages/chat/pinned_events.dart index 7c9967a5b..da600a223 100644 --- a/lib/pages/chat/pinned_events.dart +++ b/lib/pages/chat/pinned_events.dart @@ -39,7 +39,8 @@ class PinnedEvents extends StatelessWidget { (event) => AdaptiveModalAction( value: event?.eventId ?? '', icon: const Icon(Icons.push_pin_outlined), - label: event?.calcLocalizedBodyFallback( + label: + event?.calcLocalizedBodyFallback( MatrixLocals(L10n.of(context)), withSenderNamePrefix: true, hideReply: true, @@ -68,7 +69,8 @@ class PinnedEvents extends StatelessWidget { builder: (context, snapshot) { final event = snapshot.data; return ChatAppBarListTile( - title: event?.calcLocalizedBodyFallback( + title: + event?.calcLocalizedBodyFallback( MatrixLocals(L10n.of(context)), withSenderNamePrefix: true, hideReply: true, diff --git a/lib/pages/chat/recording_input_row.dart b/lib/pages/chat/recording_input_row.dart index 2432db36d..2a88a7845 100644 --- a/lib/pages/chat/recording_input_row.dart +++ b/lib/pages/chat/recording_input_row.dart @@ -46,8 +46,8 @@ class RecordingInputRow extends StatelessWidget { builder: (context, constraints) { const width = 4; return Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: .min, + mainAxisAlignment: .end, children: state.amplitudeTimeline.reversed .take((constraints.maxWidth / (width + 2)).floor()) .toList() diff --git a/lib/pages/chat/recording_view_model.dart b/lib/pages/chat/recording_view_model.dart index 72243013e..3898c4893 100644 --- a/lib/pages/chat/recording_view_model.dart +++ b/lib/pages/chat/recording_view_model.dart @@ -20,10 +20,7 @@ import 'events/audio_player.dart'; class RecordingViewModel extends StatefulWidget { final Widget Function(BuildContext, RecordingViewModelState) builder; - const RecordingViewModel({ - required this.builder, - super.key, - }); + const RecordingViewModel({required this.builder, super.key}); @override RecordingViewModelState createState() => RecordingViewModelState(); @@ -70,10 +67,10 @@ class RecordingViewModelState extends State { ? AudioEncoder.wav // Everywhere else we use opus if supported by the platform: : !PlatformInfos - .isIOS && // Blocked by https://github.com/llfbandit/record/issues/560 - await audioRecorder.isEncoderSupported(AudioEncoder.opus) - ? AudioEncoder.opus - : AudioEncoder.aacLc; + .isIOS && // Blocked by https://github.com/llfbandit/record/issues/560 + await audioRecorder.isEncoderSupported(AudioEncoder.opus) + ? AudioEncoder.opus + : AudioEncoder.aacLc; fileName = 'recording${DateTime.now().microsecondsSinceEpoch}.${codec.fileExtension}'; String? path; @@ -126,8 +123,9 @@ class RecordingViewModelState extends State { void _subscribe() { _recorderSubscription?.cancel(); - _recorderSubscription = - Timer.periodic(const Duration(milliseconds: 100), (_) async { + _recorderSubscription = Timer.periodic(const Duration(milliseconds: 100), ( + _, + ) async { final amplitude = await _audioRecorder!.getAmplitude(); var value = 100 + amplitude.current * 2; value = value < 1 ? 1 : value; @@ -178,7 +176,8 @@ class RecordingViewModelState extends State { int duration, List waveform, String? fileName, - ) onSend, + ) + onSend, ) async { _recorderSubscription?.cancel(); final path = await _audioRecorder?.stop(); diff --git a/lib/pages/chat/reply_display.dart b/lib/pages/chat/reply_display.dart index fb352f152..3e9fe0c2d 100644 --- a/lib/pages/chat/reply_display.dart +++ b/lib/pages/chat/reply_display.dart @@ -23,9 +23,7 @@ class ReplyDisplay extends StatelessWidget { ? 56 : 0, clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - color: theme.colorScheme.onInverseSurface, - ), + decoration: BoxDecoration(color: theme.colorScheme.onInverseSurface), child: Row( children: [ IconButton( @@ -63,10 +61,7 @@ class _EditContent extends StatelessWidget { } return Row( children: [ - Icon( - Icons.edit, - color: theme.colorScheme.primary, - ), + Icon(Icons.edit, color: theme.colorScheme.primary), Container(width: 15.0), Text( event.calcLocalizedBodyFallback( @@ -76,9 +71,7 @@ class _EditContent extends StatelessWidget { ), overflow: TextOverflow.ellipsis, maxLines: 1, - style: TextStyle( - color: theme.textTheme.bodyMedium!.color, - ), + style: TextStyle(color: theme.textTheme.bodyMedium!.color), ), ], ); diff --git a/lib/pages/chat/seen_by_row.dart b/lib/pages/chat/seen_by_row.dart index 83813f55d..c55c07366 100644 --- a/lib/pages/chat/seen_by_row.dart +++ b/lib/pages/chat/seen_by_row.dart @@ -20,14 +20,16 @@ class SeenByRow extends StatelessWidget { width: double.infinity, alignment: Alignment.center, child: AnimatedContainer( - constraints: - const BoxConstraints(maxWidth: FluffyThemes.maxTimelineWidth), + constraints: const BoxConstraints( + maxWidth: FluffyThemes.maxTimelineWidth, + ), height: seenByUsers.isEmpty ? 0 : 24, duration: seenByUsers.isEmpty ? Duration.zero : FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, - alignment: controller.timeline!.events.isNotEmpty && + alignment: + controller.timeline!.events.isNotEmpty && controller.timeline!.events.first.senderId == Matrix.of(context).client.userID ? Alignment.topRight @@ -40,12 +42,12 @@ class SeenByRow extends StatelessWidget { ? seenByUsers.sublist(0, maxAvatars) : seenByUsers) .map( - (user) => Avatar( - mxContent: user.avatarUrl, - name: user.calcDisplayname(), - size: 16, - ), - ), + (user) => Avatar( + mxContent: user.avatarUrl, + name: user.calcDisplayname(), + size: 16, + ), + ), if (seenByUsers.length > maxAvatars) SizedBox( width: 16, diff --git a/lib/pages/chat/send_file_dialog.dart b/lib/pages/chat/send_file_dialog.dart index deab14889..57f124b2c 100644 --- a/lib/pages/chat/send_file_dialog.dart +++ b/lib/pages/chat/send_file_dialog.dart @@ -119,8 +119,9 @@ class SendFileDialogState extends State { if (e.error != MatrixError.M_LIMIT_EXCEEDED || retryAfterMs == null) { rethrow; } - final retryAfterDuration = - Duration(milliseconds: retryAfterMs + 1000); + final retryAfterDuration = Duration( + milliseconds: retryAfterMs + 1000, + ); scaffoldMessenger.showSnackBar( SnackBar( @@ -164,8 +165,9 @@ class SendFileDialogState extends State { } Future _calcCombinedFileSize() async { - final lengths = - await Future.wait(widget.files.map((file) => file.length())); + final lengths = await Future.wait( + widget.files.map((file) => file.length()), + ); return lengths.fold(0, (p, length) => p + length).sizeString; } @@ -216,7 +218,7 @@ class SendFileDialogState extends State { width: 256, child: SingleChildScrollView( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const SizedBox(height: 12), if (uniqueFileType == 'image') @@ -243,8 +245,8 @@ class SendFileDialogState extends State { final bytes = snapshot.data; if (bytes == null) { return const Center( - child: CircularProgressIndicator - .adaptive(), + child: + CircularProgressIndicator.adaptive(), ); } if (snapshot.error != null) { @@ -272,8 +274,11 @@ class SendFileDialogState extends State { : null, fit: BoxFit.contain, errorBuilder: (context, e, s) { - Logs() - .w('Unable to preview image', e, s); + Logs().w( + 'Unable to preview image', + e, + s, + ); return const Center( child: SizedBox( width: 256, @@ -303,17 +308,17 @@ class SendFileDialogState extends State { uniqueFileType == null ? Icons.description_outlined : uniqueFileType == 'video' - ? Icons.video_file_outlined - : uniqueFileType == 'audio' - ? Icons.audio_file_outlined - : Icons.description_outlined, + ? Icons.video_file_outlined + : uniqueFileType == 'audio' + ? Icons.audio_file_outlined + : Icons.description_outlined, size: 32, ), const SizedBox(width: 8), Expanded( child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ Text( fileName, @@ -347,10 +352,12 @@ class SendFileDialogState extends State { // Workaround for SwitchListTile.adaptive crashes in CupertinoDialog if ({'image', 'video'}.contains(uniqueFileType)) Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: .center, children: [ - if ({TargetPlatform.iOS, TargetPlatform.macOS} - .contains(theme.platform)) + if ({ + TargetPlatform.iOS, + TargetPlatform.macOS, + }.contains(theme.platform)) CupertinoSwitch( value: compressionSupported && compress, onChanged: compressionSupported @@ -367,11 +374,11 @@ class SendFileDialogState extends State { const SizedBox(width: 16), Expanded( child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Text( L10n.of(context).compress, @@ -430,9 +437,7 @@ extension on ScaffoldMessengerState { const SizedBox( width: 16, height: 16, - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ), const SizedBox(width: 16), Text(title), diff --git a/lib/pages/chat/send_location_dialog.dart b/lib/pages/chat/send_location_dialog.dart index 865b909e6..8efc2cb60 100644 --- a/lib/pages/chat/send_location_dialog.dart +++ b/lib/pages/chat/send_location_dialog.dart @@ -14,10 +14,7 @@ import 'package:fluffychat/widgets/future_loading_dialog.dart'; class SendLocationDialog extends StatefulWidget { final Room room; - const SendLocationDialog({ - required this.room, - super.key, - }); + const SendLocationDialog({required this.room, super.key}); @override SendLocationDialogState createState() => SendLocationDialogState(); @@ -102,12 +99,13 @@ class SendLocationDialogState extends State { } else if (denied) { contentWidget = Text(L10n.of(context).locationPermissionDeniedNotice); } else if (error != null) { - contentWidget = - Text(L10n.of(context).errorObtainingLocation(error.toString())); + contentWidget = Text( + L10n.of(context).errorObtainingLocation(error.toString()), + ); } else { contentWidget = Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: .min, + mainAxisAlignment: .center, children: [ const CupertinoActivityIndicator(), const SizedBox(width: 12), diff --git a/lib/pages/chat/start_poll_bottom_sheet.dart b/lib/pages/chat/start_poll_bottom_sheet.dart index 5962cd2ed..b90dc473b 100644 --- a/lib/pages/chat/start_poll_bottom_sheet.dart +++ b/lib/pages/chat/start_poll_bottom_sheet.dart @@ -50,14 +50,15 @@ class _StartPollBottomSheetState extends State { } catch (e, s) { Logs().w('Unable to create poll', e, s); if (!mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(e.toLocalizedString(context))), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } } void _updateCanCreate([dynamic _]) { - final newCanCreate = _bodyController.text.trim().isNotEmpty && + final newCanCreate = + _bodyController.text.trim().isNotEmpty && !_answers.any((controller) => controller.text.trim().isEmpty); if (_canCreate != newCanCreate) { setState(() { @@ -71,9 +72,7 @@ class _StartPollBottomSheetState extends State { const maxAnswers = 10; return Scaffold( appBar: AppBar( - leading: CloseButton( - onPressed: Navigator.of(context).pop, - ), + leading: CloseButton(onPressed: Navigator.of(context).pop), title: Text(L10n.of(context).startPoll), ), body: ListView( @@ -119,8 +118,8 @@ class _StartPollBottomSheetState extends State { icon: const Icon(Icons.add_outlined), onPressed: _answers.length < maxAnswers ? () => setState(() { - _answers.add(TextEditingController()); - }) + _answers.add(TextEditingController()); + }) : null, label: Text(L10n.of(context).addAnswerOption), ), diff --git a/lib/pages/chat/sticker_picker_dialog.dart b/lib/pages/chat/sticker_picker_dialog.dart index 088ed58ea..e4c21f46e 100644 --- a/lib/pages/chat/sticker_picker_dialog.dart +++ b/lib/pages/chat/sticker_picker_dialog.dart @@ -38,15 +38,17 @@ class StickerPickerDialogState extends State { final filteredImagePackImageEntried = pack.images.entries.toList(); if (searchFilter?.isNotEmpty ?? false) { filteredImagePackImageEntried.removeWhere( - (e) => !(e.key.toLowerCase().contains(searchFilter!.toLowerCase()) || - (e.value.body - ?.toLowerCase() - .contains(searchFilter!.toLowerCase()) ?? - false)), + (e) => + !(e.key.toLowerCase().contains(searchFilter!.toLowerCase()) || + (e.value.body?.toLowerCase().contains( + searchFilter!.toLowerCase(), + ) ?? + false)), ); } - final imageKeys = - filteredImagePackImageEntried.map((e) => e.key).toList(); + final imageKeys = filteredImagePackImageEntried + .map((e) => e.key) + .toList(); if (imageKeys.isEmpty) { return const SizedBox.shrink(); } @@ -82,8 +84,9 @@ class StickerPickerDialogState extends State { key: ValueKey(image.url.toString()), onTap: () { // copy the image - final imageCopy = - ImagePackImageContent.fromJson(image.toJson().copy()); + final imageCopy = ImagePackImageContent.fromJson( + image.toJson().copy(), + ); // set the body, if it doesn't exist, to the key imageCopy.body ??= imageKeys[imageIndex]; widget.onSelected(imageCopy); @@ -137,7 +140,7 @@ class StickerPickerDialogState extends State { SliverFillRemaining( child: Center( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Text(L10n.of(context).noEmotesFound), const SizedBox(height: 12), diff --git a/lib/pages/chat/typing_indicators.dart b/lib/pages/chat/typing_indicators.dart index 8d3fa8d21..236c30e59 100644 --- a/lib/pages/chat/typing_indicators.dart +++ b/lib/pages/chat/typing_indicators.dart @@ -21,8 +21,9 @@ class TypingIndicators extends StatelessWidget { return StreamBuilder( stream: controller.room.client.onSync.stream.where( (syncUpdate) => - syncUpdate.rooms?.join?[controller.room.id]?.ephemeral - ?.any((ephemeral) => ephemeral.type == 'm.typing') ?? + syncUpdate.rooms?.join?[controller.room.id]?.ephemeral?.any( + (ephemeral) => ephemeral.type == 'm.typing', + ) ?? false, ), builder: (context, _) { @@ -33,22 +34,21 @@ class TypingIndicators extends StatelessWidget { width: double.infinity, alignment: Alignment.center, child: AnimatedContainer( - constraints: - const BoxConstraints(maxWidth: FluffyThemes.maxTimelineWidth), + constraints: const BoxConstraints( + maxWidth: FluffyThemes.maxTimelineWidth, + ), height: typingUsers.isEmpty ? 0 : avatarSize + 8, duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, - alignment: controller.timeline!.events.isNotEmpty && + alignment: + controller.timeline!.events.isNotEmpty && controller.timeline!.events.first.senderId == Matrix.of(context).client.userID ? Alignment.topRight : Alignment.topLeft, clipBehavior: Clip.hardEdge, decoration: const BoxDecoration(), - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 4.0, - ), + padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), child: Row( children: [ Container( @@ -115,17 +115,14 @@ class __TypingDotsState extends State<_TypingDots> { @override void initState() { - _timer = Timer.periodic( - animationDuration, - (_) { - if (!mounted) { - return; - } - setState(() { - _tick = (_tick + 1) % 4; - }); - }, - ); + _timer = Timer.periodic(animationDuration, (_) { + if (!mounted) { + return; + } + setState(() { + _tick = (_tick + 1) % 4; + }); + }); super.initState(); } @@ -141,7 +138,7 @@ class __TypingDotsState extends State<_TypingDots> { const size = 8.0; return Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ for (var i = 1; i <= 3; i++) AnimatedContainer( diff --git a/lib/pages/chat_access_settings/chat_access_settings_controller.dart b/lib/pages/chat_access_settings/chat_access_settings_controller.dart index 5a7f8d9aa..4161099fd 100644 --- a/lib/pages/chat_access_settings/chat_access_settings_controller.dart +++ b/lib/pages/chat_access_settings/chat_access_settings_controller.dart @@ -27,15 +27,15 @@ class ChatAccessSettingsController extends State { bool guestAccessLoading = false; Room get room => Matrix.of(context).client.getRoomById(widget.roomId)!; Set 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.client.rooms.where( + (space) => + space.isSpace && + space.spaceChildren.any((child) => child.roomId == room.id), + ), + ...room.spaceParents + .map((parent) => room.client.getRoomById(parent.roomId ?? '')) + .whereType(), + }; String get roomVersion => room @@ -87,21 +87,20 @@ class ChatAccessSettingsController extends State { try { await room.setJoinRules( newJoinRules, - allowConditionRoomIds: {JoinRules.restricted, JoinRules.knockRestricted} - .contains(newJoinRules) + allowConditionRoomIds: + { + JoinRules.restricted, + JoinRules.knockRestricted, + }.contains(newJoinRules) ? knownSpaceParents.map((parent) => parent.id).toList() : null, ); } catch (e, s) { Logs().w('Unable to change join rules', e, s); if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - e.toLocalizedString(context), - ), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } } finally { if (mounted) { @@ -123,13 +122,9 @@ class ChatAccessSettingsController extends State { } catch (e, s) { Logs().w('Unable to change history visibility', e, s); if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - e.toLocalizedString(context), - ), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } } finally { if (mounted) { @@ -151,13 +146,9 @@ class ChatAccessSettingsController extends State { } catch (e, s) { Logs().w('Unable to change guest access', e, s); if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - e.toLocalizedString(context), - ), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } } finally { if (mounted) { @@ -216,8 +207,11 @@ class ChatAccessSettingsController extends State { newRoom = room.client.getRoomById(newRoomId); } - if ({JoinRules.invite, JoinRules.knock, JoinRules.knockRestricted} - .contains(room.joinRules)) { + if ({ + JoinRules.invite, + JoinRules.knock, + JoinRules.knockRestricted, + }.contains(room.joinRules)) { final users = await room.requestParticipants([ Membership.join, Membership.invite, @@ -282,7 +276,8 @@ class ChatAccessSettingsController extends State { cancelLabel: L10n.of(context).no, ); - final altAliases = room + final altAliases = + room .getState(EventTypes.RoomCanonicalAlias) ?.content .tryGetList('alt_aliases') @@ -298,17 +293,13 @@ class ChatAccessSettingsController extends State { await showFutureLoadingDialog( context: context, - future: () => room.client.setRoomStateWithKey( - room.id, - EventTypes.RoomCanonicalAlias, - '', - { - 'alias': canonicalAliasConsent == OkCancelResult.ok - ? alias - : room.canonicalAlias, - if (altAliases.isNotEmpty) 'alt_aliases': altAliases.toList(), - }, - ), + future: () => room.client + .setRoomStateWithKey(room.id, EventTypes.RoomCanonicalAlias, '', { + 'alias': canonicalAliasConsent == OkCancelResult.ok + ? alias + : room.canonicalAlias, + if (altAliases.isNotEmpty) 'alt_aliases': altAliases.toList(), + }), ); } @@ -335,13 +326,9 @@ class ChatAccessSettingsController extends State { } catch (e, s) { Logs().w('Unable to change visibility', e, s); if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - e.toLocalizedString(context), - ), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } } finally { if (mounted) { diff --git a/lib/pages/chat_access_settings/chat_access_settings_page.dart b/lib/pages/chat_access_settings/chat_access_settings_page.dart index 616d13934..a2f040799 100644 --- a/lib/pages/chat_access_settings/chat_access_settings_page.dart +++ b/lib/pages/chat_access_settings/chat_access_settings_page.dart @@ -24,17 +24,19 @@ class ChatAccessSettingsPageView extends StatelessWidget { ), body: MaxWidthBody( child: StreamBuilder( - stream: room.client.onRoomState.stream - .where((update) => update.roomId == controller.room.id), + stream: room.client.onRoomState.stream.where( + (update) => update.roomId == controller.room.id, + ), builder: (context, snapshot) { final canonicalAlias = room.canonicalAlias; - final altAliases = room + final altAliases = + room .getState(EventTypes.RoomCanonicalAlias) ?.content .tryGetList('alt_aliases') ?? []; return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ ListTile( title: Text( @@ -47,12 +49,13 @@ class ChatAccessSettingsPageView extends StatelessWidget { ), RadioGroup( groupValue: room.historyVisibility, - onChanged: controller.historyVisibilityLoading || + onChanged: + controller.historyVisibilityLoading || !room.canChangeHistoryVisibility ? (_) {} : controller.setHistoryVisibility, child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ for (final historyVisibility in HistoryVisibility.values) RadioListTile.adaptive( @@ -80,12 +83,13 @@ class ChatAccessSettingsPageView extends StatelessWidget { groupValue: room.joinRules, onChanged: controller.setJoinRule, child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ for (final joinRule in controller.availableJoinRules) if (joinRule != JoinRules.private) RadioListTile.adaptive( - enabled: !controller.joinRulesLoading && + enabled: + !controller.joinRulesLoading && room.canChangeJoinRules, title: Text( joinRule.localizedString( @@ -99,8 +103,10 @@ class ChatAccessSettingsPageView extends StatelessWidget { ), ), Divider(color: theme.dividerColor), - if ({JoinRules.public, JoinRules.knock} - .contains(room.joinRules)) ...[ + if ({ + JoinRules.public, + JoinRules.knock, + }.contains(room.joinRules)) ...[ ListTile( title: Text( L10n.of(context).areGuestsAllowedToJoin, @@ -114,11 +120,12 @@ class ChatAccessSettingsPageView extends StatelessWidget { groupValue: room.guestAccess, onChanged: controller.setGuestAccess, child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ for (final guestAccess in GuestAccess.values) RadioListTile.adaptive( - enabled: !controller.guestAccessLoading && + enabled: + !controller.guestAccessLoading && room.canChangeGuestAccess, title: Text( guestAccess.getLocalizedString( @@ -148,9 +155,10 @@ class ChatAccessSettingsPageView extends StatelessWidget { if (canonicalAlias.isNotEmpty) _AliasListTile( alias: canonicalAlias, - onDelete: room.canChangeStateEvent( - EventTypes.RoomCanonicalAlias, - ) + onDelete: + room.canChangeStateEvent( + EventTypes.RoomCanonicalAlias, + ) ? () => controller.deleteAlias(canonicalAlias) : null, isCanonicalAlias: true, @@ -158,9 +166,10 @@ class ChatAccessSettingsPageView extends StatelessWidget { for (final alias in altAliases) _AliasListTile( alias: alias, - onDelete: room.canChangeStateEvent( - EventTypes.RoomCanonicalAlias, - ) + onDelete: + room.canChangeStateEvent( + EventTypes.RoomCanonicalAlias, + ) ? () => controller.deleteAlias(alias) : null, ), @@ -172,10 +181,11 @@ class ChatAccessSettingsPageView extends StatelessWidget { return const SizedBox.shrink(); } localAddresses.remove(room.canonicalAlias); - localAddresses - .removeWhere((alias) => altAliases.contains(alias)); + localAddresses.removeWhere( + (alias) => altAliases.contains(alias), + ); return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: localAddresses .map( (alias) => _AliasListTile( @@ -257,10 +267,7 @@ class _AliasListTile extends StatelessWidget { ? const Icon(Icons.star) : const Icon(Icons.link_outlined), title: InkWell( - onTap: () => FluffyShare.share( - 'https://matrix.to/#/$alias', - context, - ), + onTap: () => FluffyShare.share('https://matrix.to/#/$alias', context), child: SelectableText( alias, style: TextStyle( diff --git a/lib/pages/chat_details/chat_details.dart b/lib/pages/chat_details/chat_details.dart index 0952b07f3..8e070e447 100644 --- a/lib/pages/chat_details/chat_details.dart +++ b/lib/pages/chat_details/chat_details.dart @@ -46,11 +46,7 @@ class ChatDetailsController extends State { title: L10n.of(context).changeTheNameOfTheGroup, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - initialText: room.getLocalizedDisplayname( - MatrixLocals( - L10n.of(context), - ), - ), + initialText: room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), ); if (input == null) return; final success = await showFutureLoadingDialog( @@ -83,9 +79,7 @@ class ChatDetailsController extends State { ); if (success.error == null) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(L10n.of(context).chatDescriptionHasBeenChanged), - ), + SnackBar(content: Text(L10n.of(context).chatDescriptionHasBeenChanged)), ); } } @@ -138,10 +132,7 @@ class ChatDetailsController extends State { imageQuality: 50, ); if (result == null) return; - file = MatrixFile( - bytes: await result.readAsBytes(), - name: result.path, - ); + file = MatrixFile(bytes: await result.readAsBytes(), name: result.path); } else { final picked = await selectFiles( context, diff --git a/lib/pages/chat_details/chat_details_view.dart b/lib/pages/chat_details/chat_details_view.dart index 69c44984d..e17e21a80 100644 --- a/lib/pages/chat_details/chat_details_view.dart +++ b/lib/pages/chat_details/chat_details_view.dart @@ -29,9 +29,7 @@ class ChatDetailsView extends StatelessWidget { final room = Matrix.of(context).client.getRoomById(controller.roomId!); if (room == null) { return Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).oopsSomethingWentWrong), - ), + appBar: AppBar(title: Text(L10n.of(context).oopsSomethingWentWrong)), body: Center( child: Text(L10n.of(context).youAreNoLongerParticipatingInThisChat), ), @@ -42,13 +40,15 @@ class ChatDetailsView extends StatelessWidget { final roomAvatar = room.avatar; return StreamBuilder( - stream: room.client.onRoomState.stream - .where((update) => update.roomId == room.id), + stream: room.client.onRoomState.stream.where( + (update) => update.roomId == room.id, + ), builder: (context, snapshot) { var members = room.getParticipants().toList() ..sort((b, a) => a.powerLevel.compareTo(b.powerLevel)); members = members.take(10).toList(); - final actualMembersCount = (room.summary.mInvitedMemberCount ?? 0) + + final actualMembersCount = + (room.summary.mInvitedMemberCount ?? 0) + (room.summary.mJoinedMemberCount ?? 0); final canRequestMoreMembers = members.length < actualMembersCount; final iconColor = theme.textTheme.bodyLarge!.color; @@ -57,7 +57,8 @@ class ChatDetailsView extends StatelessWidget { ); return Scaffold( appBar: AppBar( - leading: controller.widget.embeddedCloseButton ?? + leading: + controller.widget.embeddedCloseButton ?? const Center(child: BackButton()), elevation: theme.appBarTheme.elevation, actions: [ @@ -65,19 +66,15 @@ class ChatDetailsView extends StatelessWidget { IconButton( tooltip: L10n.of(context).share, icon: const Icon(Icons.qr_code_rounded), - onPressed: () => showQrCodeViewer( - context, - room.canonicalAlias, - ), + onPressed: () => + showQrCodeViewer(context, room.canonicalAlias), ) else if (directChatMatrixID != null) IconButton( tooltip: L10n.of(context).share, icon: const Icon(Icons.qr_code_rounded), - onPressed: () => showQrCodeViewer( - context, - directChatMatrixID, - ), + onPressed: () => + showQrCodeViewer(context, directChatMatrixID), ), if (controller.widget.embeddedCloseButton == null) ChatSettingsPopupMenu(room, false), @@ -92,7 +89,7 @@ class ChatDetailsView extends StatelessWidget { itemCount: members.length + 1 + (canRequestMoreMembers ? 1 : 0), itemBuilder: (BuildContext context, int i) => i == 0 ? Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + crossAxisAlignment: .stretch, children: [ Row( children: [ @@ -103,19 +100,19 @@ class ChatDetailsView extends StatelessWidget { Hero( tag: controller.widget.embeddedCloseButton != - null - ? 'embedded_content_banner' - : 'content_banner', + null + ? 'embedded_content_banner' + : 'content_banner', child: Avatar( mxContent: room.avatar, name: displayname, size: Avatar.defaultSize * 2.5, onTap: roomAvatar != null ? () => showDialog( - context: context, - builder: (_) => - MxcImageViewer(roomAvatar), - ) + context: context, + builder: (_) => + MxcImageViewer(roomAvatar), + ) : null, ), ), @@ -139,8 +136,8 @@ class ChatDetailsView extends StatelessWidget { ), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: .center, + crossAxisAlignment: .start, children: [ TextButton.icon( onPressed: () => room.isDirectChat @@ -148,20 +145,20 @@ class ChatDetailsView extends StatelessWidget { : room.canChangeStateEvent( EventTypes.RoomName, ) - ? controller.setDisplaynameAction() - : FluffyShare.share( - displayname, - context, - copyOnly: true, - ), + ? controller.setDisplaynameAction() + : FluffyShare.share( + displayname, + context, + copyOnly: true, + ), icon: Icon( room.isDirectChat ? Icons.chat_bubble_outline : room.canChangeStateEvent( EventTypes.RoomName, ) - ? Icons.edit_outlined - : Icons.copy_outlined, + ? Icons.edit_outlined + : Icons.copy_outlined, size: 16, ), style: TextButton.styleFrom( @@ -194,9 +191,9 @@ class ChatDetailsView extends StatelessWidget { iconColor: theme.colorScheme.secondary, ), label: Text( - L10n.of(context).countParticipants( - actualMembersCount, - ), + L10n.of( + context, + ).countParticipants(actualMembersCount), maxLines: 1, overflow: TextOverflow.ellipsis, // style: const TextStyle(fontSize: 12), @@ -220,13 +217,14 @@ class ChatDetailsView extends StatelessWidget { ), trailing: room.canChangeStateEvent(EventTypes.RoomTopic) - ? IconButton( - onPressed: controller.setTopicAction, - tooltip: - L10n.of(context).setChatDescription, - icon: const Icon(Icons.edit_outlined), - ) - : null, + ? IconButton( + onPressed: controller.setTopicAction, + tooltip: L10n.of( + context, + ).setChatDescription, + icon: const Icon(Icons.edit_outlined), + ) + : null, ), Padding( padding: const EdgeInsets.symmetric( @@ -236,8 +234,9 @@ class ChatDetailsView extends StatelessWidget { text: room.topic.isEmpty ? L10n.of(context).noChatDescriptionYet : room.topic, - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: const TextStyle( color: Colors.blueAccent, @@ -269,14 +268,13 @@ class ChatDetailsView extends StatelessWidget { Icons.admin_panel_settings_outlined, ), ), - title: Text( - L10n.of(context).accessAndVisibility, - ), + title: Text(L10n.of(context).accessAndVisibility), subtitle: Text( L10n.of(context).accessAndVisibilityDescription, ), - onTap: () => context - .push('/rooms/${room.id}/details/access'), + onTap: () => context.push( + '/rooms/${room.id}/details/access', + ), trailing: const Icon(Icons.chevron_right_outlined), ), ListTile( @@ -288,21 +286,20 @@ class ChatDetailsView extends StatelessWidget { backgroundColor: theme.colorScheme.surfaceContainer, foregroundColor: iconColor, - child: const Icon( - Icons.tune_outlined, - ), + child: const Icon(Icons.tune_outlined), ), trailing: const Icon(Icons.chevron_right_outlined), - onTap: () => context - .push('/rooms/${room.id}/details/permissions'), + onTap: () => context.push( + '/rooms/${room.id}/details/permissions', + ), ), ], Divider(color: theme.dividerColor), ListTile( title: Text( - L10n.of(context).countParticipants( - actualMembersCount, - ), + L10n.of( + context, + ).countParticipants(actualMembersCount), style: TextStyle( color: theme.colorScheme.secondary, fontWeight: FontWeight.bold, @@ -326,25 +323,25 @@ class ChatDetailsView extends StatelessWidget { ], ) : i < members.length + 1 - ? ParticipantListItem(members[i - 1]) - : ListTile( - title: Text( - L10n.of(context).loadCountMoreParticipants( - (actualMembersCount - members.length), - ), - ), - leading: CircleAvatar( - backgroundColor: theme.scaffoldBackgroundColor, - child: const Icon( - Icons.group_outlined, - color: Colors.grey, - ), - ), - onTap: () => context.push( - '/rooms/${controller.roomId!}/details/members', - ), - trailing: const Icon(Icons.chevron_right_outlined), + ? ParticipantListItem(members[i - 1]) + : ListTile( + title: Text( + L10n.of(context).loadCountMoreParticipants( + (actualMembersCount - members.length), ), + ), + leading: CircleAvatar( + backgroundColor: theme.scaffoldBackgroundColor, + child: const Icon( + Icons.group_outlined, + color: Colors.grey, + ), + ), + onTap: () => context.push( + '/rooms/${controller.roomId!}/details/members', + ), + trailing: const Icon(Icons.chevron_right_outlined), + ), ), ), ); diff --git a/lib/pages/chat_details/participant_list_item.dart b/lib/pages/chat_details/participant_list_item.dart index cb19ded47..04013ce50 100644 --- a/lib/pages/chat_details/participant_list_item.dart +++ b/lib/pages/chat_details/participant_list_item.dart @@ -27,8 +27,8 @@ class ParticipantListItem extends StatelessWidget { final permissionBatch = user.powerLevel >= 100 ? L10n.of(context).admin : user.powerLevel >= 50 - ? L10n.of(context).moderator - : ''; + ? L10n.of(context).moderator + : ''; return ListTile( onTap: () => showMemberActionsPopupMenu(context: context, user: user), @@ -42,17 +42,12 @@ class ParticipantListItem extends StatelessWidget { ), if (permissionBatch.isNotEmpty) Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, - ), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: user.powerLevel >= 100 ? theme.colorScheme.tertiary : theme.colorScheme.tertiaryContainer, - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), + borderRadius: BorderRadius.circular(AppConfig.borderRadius), ), child: Text( permissionBatch, @@ -66,8 +61,10 @@ class ParticipantListItem extends StatelessWidget { membershipBatch == null ? const SizedBox.shrink() : Container( - padding: - const EdgeInsets.symmetric(vertical: 4, horizontal: 8), + padding: const EdgeInsets.symmetric( + vertical: 4, + horizontal: 8, + ), margin: const EdgeInsets.symmetric(horizontal: 8), decoration: BoxDecoration( color: theme.colorScheme.secondaryContainer, @@ -84,11 +81,7 @@ class ParticipantListItem extends StatelessWidget { ), ], ), - subtitle: Text( - user.id, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), + subtitle: Text(user.id, maxLines: 1, overflow: TextOverflow.ellipsis), leading: Opacity( opacity: user.membership == Membership.join ? 1 : 0.5, child: Avatar( diff --git a/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart b/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart index 754178c25..d185852be 100644 --- a/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart +++ b/lib/pages/chat_encryption_settings/chat_encryption_settings_view.dart @@ -42,7 +42,7 @@ class ChatEncryptionSettingsView extends StatelessWidget { ), body: MaxWidthBody( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ SwitchListTile( secondary: CircleAvatar( @@ -76,16 +76,14 @@ class ChatEncryptionSettingsView extends StatelessWidget { ListTile( title: Text( L10n.of(context).deviceKeys, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), + style: const TextStyle(fontWeight: FontWeight.bold), ), ), StreamBuilder( - stream: room.client.onRoomState.stream - .where((update) => update.roomId == controller.room.id), - builder: (context, snapshot) => - FutureBuilder>( + stream: room.client.onRoomState.stream.where( + (update) => update.roomId == controller.room.id, + ), + builder: (context, snapshot) => FutureBuilder>( future: room.getUserDeviceKeys(), builder: (BuildContext context, snapshot) { if (snapshot.hasError) { @@ -108,20 +106,21 @@ class ChatEncryptionSettingsView extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), itemCount: deviceKeys.length, itemBuilder: (BuildContext context, int i) => Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (i == 0 || deviceKeys[i].userId != deviceKeys[i - 1].userId) ...[ const Divider(), FutureBuilder( - future: room.client - .getUserProfile(deviceKeys[i].userId), + future: room.client.getUserProfile( + deviceKeys[i].userId, + ), builder: (context, snapshot) { final displayname = snapshot.data?.displayname ?? - deviceKeys[i].userId.localpart ?? - deviceKeys[i].userId; + deviceKeys[i].userId.localpart ?? + deviceKeys[i].userId; return ListTile( leading: Avatar( name: displayname, @@ -146,14 +145,14 @@ class ChatEncryptionSettingsView extends StatelessWidget { deviceKeys[i].verified ? L10n.of(context).verified : deviceKeys[i].blocked - ? L10n.of(context).blocked - : L10n.of(context).unverified, + ? L10n.of(context).blocked + : L10n.of(context).unverified, style: TextStyle( color: deviceKeys[i].verified ? Colors.green : deviceKeys[i].blocked - ? Colors.red - : Colors.orange, + ? Colors.red + : Colors.orange, ), ), const Text(' | ID: '), @@ -185,9 +184,7 @@ class ChatEncryptionSettingsView extends StatelessWidget { child: Center( child: Text( L10n.of(context).encryptionNotEnabled, - style: const TextStyle( - fontStyle: FontStyle.italic, - ), + style: const TextStyle(fontStyle: FontStyle.italic), ), ), ), diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index cd1d542a4..3b54e1a8c 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -38,13 +38,7 @@ enum PopupMenuAction { archive, } -enum ActiveFilter { - allChats, - messages, - groups, - unread, - spaces, -} +enum ActiveFilter { allChats, messages, groups, unread, spaces } extension LocalizedActiveFilter on ActiveFilter { String toLocalizedString(BuildContext context) { @@ -102,8 +96,8 @@ class ChatListController extends State } void clearActiveSpace() => setState(() { - _activeSpaceId = null; - }); + _activeSpaceId = null; + }); void onChatTap(Room room) async { if (room.membership == Membership.invite) { @@ -124,9 +118,7 @@ class ChatListController extends State if (room.membership == Membership.ban) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(L10n.of(context).youHaveBeenBannedFromThisChat), - ), + SnackBar(content: Text(L10n.of(context).youHaveBeenBannedFromThisChat)), ); return; } @@ -159,11 +151,9 @@ class ChatListController extends State } } - List get filteredRooms => Matrix.of(context) - .client - .rooms - .where(getRoomFilterByActiveFilter(activeFilter)) - .toList(); + List get filteredRooms => Matrix.of( + context, + ).client.rooms.where(getRoomFilterByActiveFilter(activeFilter)).toList(); bool isSearchMode = false; Future? publicRoomsResponse; @@ -222,8 +212,9 @@ class ChatListController extends State if (searchQuery.isValidMatrixId && searchQuery.sigil == '#' && - roomSearchResult.chunk - .any((room) => room.canonicalAlias == searchQuery) == + roomSearchResult.chunk.any( + (room) => room.canonicalAlias == searchQuery, + ) == false) { final response = await client.getRoomIdByAlias(searchQuery); final roomId = response.roomId; @@ -246,13 +237,9 @@ class ChatListController extends State ); } catch (e, s) { Logs().w('Searching has crashed', e, s); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - e.toLocalizedString(context), - ), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } if (!isSearchMode) return; setState(() { @@ -333,22 +320,17 @@ class ChatListController extends State showScaffoldDialog( context: context, builder: (context) => ShareScaffoldDialog( - items: files.map( - (file) { - if ({ - SharedMediaType.text, - SharedMediaType.url, - }.contains(file.type)) { - return TextShareItem(file.path); - } - return FileShareItem( - XFile( - file.path.replaceFirst('file://', ''), - mimeType: file.mimeType, - ), - ); - }, - ).toList(), + items: files.map((file) { + if ({SharedMediaType.text, SharedMediaType.url}.contains(file.type)) { + return TextShareItem(file.path); + } + return FileShareItem( + XFile( + file.path.replaceFirst('file://', ''), + mimeType: file.mimeType, + ), + ); + }).toList(), ), ); } @@ -370,22 +352,23 @@ class ChatListController extends State .listen(_processIncomingSharedMedia, onError: print); // For sharing images coming from outside the app while the app is closed - ReceiveSharingIntent.instance - .getInitialMedia() - .then(_processIncomingSharedMedia); + ReceiveSharingIntent.instance.getInitialMedia().then( + _processIncomingSharedMedia, + ); // For receiving shared Uris - _intentUriStreamSubscription = - AppLinks().uriLinkStream.listen(_processIncomingUris); + _intentUriStreamSubscription = AppLinks().uriLinkStream.listen( + _processIncomingUris, + ); if (PlatformInfos.isAndroid) { final shortcuts = FlutterShortcuts(); shortcuts.initialize().then( - (_) => shortcuts.listenAction((action) { - if (!mounted) return; - UrlLauncher(context, action).launchUrl(); - }), - ); + (_) => shortcuts.listenAction((action) { + if (!mounted) return; + UrlLauncher(context, action).launchUrl(); + }), + ); } } @@ -402,8 +385,9 @@ class ChatListController extends State _hackyWebRTCFixForWeb(); WidgetsBinding.instance.addPostFrameCallback((_) async { if (mounted) { - searchServer = - Matrix.of(context).store.getString(_serverStoreNamespace); + searchServer = Matrix.of( + context, + ).store.getString(_serverStoreNamespace); Matrix.of(context).backgroundPush?.setupPush(); UpdateNotifier.showUpdateSnackBar(context); } @@ -447,8 +431,9 @@ class ChatListController extends State Offset.zero & overlay.size, ); - final displayname = - room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))); + final displayname = room.getLocalizedDisplayname( + MatrixLocals(L10n.of(context)), + ); final spacesWithPowerLevels = room.client.rooms .where( @@ -466,19 +451,17 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.open, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, spacing: 12.0, children: [ - Avatar( - mxContent: room.avatar, - name: displayname, - ), + Avatar(mxContent: room.avatar, name: displayname), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 128), child: Text( displayname, - style: - TextStyle(color: Theme.of(context).colorScheme.onSurface), + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface, + ), maxLines: 2, overflow: TextOverflow.ellipsis, ), @@ -491,7 +474,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.goToSpace, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Avatar( mxContent: space.avatar, @@ -511,7 +494,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.mute, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Icon( room.pushRuleState == PushRuleState.notify @@ -530,7 +513,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.markUnread, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Icon( room.markedUnread @@ -549,7 +532,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.favorite, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Icon( room.isFavourite ? Icons.push_pin : Icons.push_pin_outlined, @@ -567,7 +550,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.addToSpace, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.group_work_outlined), const SizedBox(width: 12), @@ -579,7 +562,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.leave, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Icon( Icons.delete_outlined, @@ -601,7 +584,7 @@ class ChatListController extends State PopupMenuItem( value: ChatContextAction.block, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Icon( Icons.block_outlined, @@ -684,8 +667,9 @@ class ChatListController extends State .map( (space) => AdaptiveModalAction( value: space, - label: space - .getLocalizedDisplayname(MatrixLocals(L10n.of(context))), + label: space.getLocalizedDisplayname( + MatrixLocals(L10n.of(context)), + ), ), ) .toList(), @@ -746,8 +730,9 @@ class ChatListController extends State await client.accountDataLoading; await client.userDeviceKeysLoading; if (client.prevBatch == null) { - await client.onSyncStatus.stream - .firstWhere((status) => status.status == SyncStatus.finished); + await client.onSyncStatus.stream.firstWhere( + (status) => status.status == SyncStatus.finished, + ); if (!mounted) return; setState(() { @@ -759,8 +744,9 @@ class ChatListController extends State waitForFirstSync = true; }); - if (client.userDeviceKeys[client.userID!]?.deviceKeys.values - .any((device) => !device.verified && !device.blocked) ?? + if (client.userDeviceKeys[client.userID!]?.deviceKeys.values.any( + (device) => !device.verified && !device.blocked, + ) ?? false) { late final ScaffoldFeatureController controller; final theme = Theme.of(context); @@ -772,9 +758,7 @@ class ChatListController extends State closeIconColor: theme.colorScheme.onErrorContainer, content: Text( L10n.of(context).oneOfYourDevicesIsNotVerified, - style: TextStyle( - color: theme.colorScheme.onErrorContainer, - ), + style: TextStyle(color: theme.colorScheme.onErrorContainer), ), action: SnackBarAction( onPressed: () { @@ -810,20 +794,21 @@ class ChatListController extends State setState(() { _activeSpaceId = null; Matrix.of(context).activeBundle = bundle; - if (!Matrix.of(context) - .currentBundle! - .any((client) => client == Matrix.of(context).client)) { - Matrix.of(context) - .setActiveClient(Matrix.of(context).currentBundle!.first); + if (!Matrix.of( + context, + ).currentBundle!.any((client) => client == Matrix.of(context).client)) { + Matrix.of( + context, + ).setActiveClient(Matrix.of(context).currentBundle!.first); } }); } void editBundlesForAccount(String? userId, String? activeBundle) async { final l10n = L10n.of(context); - final client = Matrix.of(context) - .widget - .clients[Matrix.of(context).getClientIndexByMatrixId(userId!)]; + final client = Matrix.of( + context, + ).widget.clients[Matrix.of(context).getClientIndexByMatrixId(userId!)]; final action = await showModalActionPopup( context: context, title: L10n.of(context).editBundlesForAccount, @@ -868,10 +853,9 @@ class ChatListController extends State String? get secureActiveBundle { if (Matrix.of(context).activeBundle == null || - !Matrix.of(context) - .accountBundles - .keys - .contains(Matrix.of(context).activeBundle)) { + !Matrix.of( + context, + ).accountBundles.keys.contains(Matrix.of(context).activeBundle)) { return Matrix.of(context).accountBundles.keys.first; } return Matrix.of(context).activeBundle; @@ -897,11 +881,7 @@ class ChatListController extends State enum EditBundleAction { addToBundle, removeFromBundle } -enum InviteActions { - accept, - decline, - block, -} +enum InviteActions { accept, decline, block } enum ChatContextAction { open, diff --git a/lib/pages/chat_list/chat_list_body.dart b/lib/pages/chat_list/chat_list_body.dart index 20c85b39f..1aa398f3f 100644 --- a/lib/pages/chat_list/chat_list_body.dart +++ b/lib/pages/chat_list/chat_list_body.dart @@ -59,9 +59,7 @@ class ChatListViewBody extends StatelessWidget { const dummyChatCount = 4; final filter = controller.searchController.text.toLowerCase(); return StreamBuilder( - key: ValueKey( - client.userID.toString(), - ), + key: ValueKey(client.userID.toString()), stream: client.onSync.stream .where((s) => s.hasRoomUpdate) .rateLimit(const Duration(seconds: 1)), @@ -74,151 +72,151 @@ class ChatListViewBody extends StatelessWidget { slivers: [ ChatListHeader(controller: controller), SliverList( - delegate: SliverChildListDelegate( - [ - if (controller.isSearchMode) ...[ - SearchTitle( - title: L10n.of(context).publicRooms, - icon: const Icon(Icons.explore_outlined), - ), - PublicRoomsHorizontalList(publicRooms: publicRooms), - SearchTitle( - title: L10n.of(context).publicSpaces, - icon: const Icon(Icons.workspaces_outlined), - ), - PublicRoomsHorizontalList(publicRooms: publicSpaces), - SearchTitle( - title: L10n.of(context).users, - icon: const Icon(Icons.group_outlined), - ), - AnimatedContainer( - clipBehavior: Clip.hardEdge, - decoration: const BoxDecoration(), - height: userSearchResult == null || - userSearchResult.results.isEmpty - ? 0 - : 106, - duration: FluffyThemes.animationDuration, - 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], - ), + delegate: SliverChildListDelegate([ + if (controller.isSearchMode) ...[ + SearchTitle( + title: L10n.of(context).publicRooms, + icon: const Icon(Icons.explore_outlined), + ), + PublicRoomsHorizontalList(publicRooms: publicRooms), + SearchTitle( + title: L10n.of(context).publicSpaces, + icon: const Icon(Icons.workspaces_outlined), + ), + PublicRoomsHorizontalList(publicRooms: publicSpaces), + SearchTitle( + title: L10n.of(context).users, + icon: const Icon(Icons.group_outlined), + ), + AnimatedContainer( + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + height: + userSearchResult == null || + userSearchResult.results.isEmpty + ? 0 + : 106, + duration: FluffyThemes.animationDuration, + 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], ), ), - ), - ], - if (!controller.isSearchMode && - AppSettings.showPresences.value) - GestureDetector( - onLongPress: () => controller.dismissStatusList(), - child: StatusMessageList( - onStatusEdit: controller.setStatus, - ), - ), - if (client.rooms.isNotEmpty && !controller.isSearchMode) - SizedBox( - height: 64, - child: ListView( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 12.0, - ), - shrinkWrap: true, - scrollDirection: Axis.horizontal, - children: [ - if (AppSettings.separateChatTypes.value) - ActiveFilter.messages - else - ActiveFilter.allChats, - ActiveFilter.groups, - ActiveFilter.unread, - if (spaceDelegateCandidates.isNotEmpty && - !AppSettings.displayNavigationRail.value && - !FluffyThemes.isColumnMode(context)) - ActiveFilter.spaces, - ] - .map( - (filter) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 4.0, - ), - child: FilterChip( - selected: filter == controller.activeFilter, - onSelected: (_) => - controller.setActiveFilter(filter), - label: - Text(filter.toLocalizedString(context)), - ), - ), - ) - .toList(), - ), - ), - if (controller.isSearchMode) - SearchTitle( - title: L10n.of(context).chats, - icon: const Icon(Icons.forum_outlined), - ), - if (client.prevBatch != null && - rooms.isEmpty && - !controller.isSearchMode) ...[ - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Stack( - alignment: Alignment.center, - children: [ - const Column( - mainAxisSize: MainAxisSize.min, - children: [ - DummyChatListItem( - opacity: 0.5, - animate: false, - ), - DummyChatListItem( - opacity: 0.3, - animate: false, - ), - ], - ), - Icon( - CupertinoIcons.chat_bubble_text_fill, - size: 128, - color: theme.colorScheme.secondary, - ), - ], - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: Text( - client.rooms.isEmpty - ? L10n.of(context).noChatsFoundHere - : L10n.of(context).noMoreChatsFound, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 18, - color: theme.colorScheme.secondary, - ), ), - ), - ], - ), - ], + ), ], - ), + if (!controller.isSearchMode && + AppSettings.showPresences.value) + GestureDetector( + onLongPress: () => controller.dismissStatusList(), + child: StatusMessageList( + onStatusEdit: controller.setStatus, + ), + ), + if (client.rooms.isNotEmpty && !controller.isSearchMode) + SizedBox( + height: 64, + child: ListView( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 12.0, + ), + shrinkWrap: true, + scrollDirection: Axis.horizontal, + children: + [ + if (AppSettings.separateChatTypes.value) + ActiveFilter.messages + else + ActiveFilter.allChats, + ActiveFilter.groups, + ActiveFilter.unread, + if (spaceDelegateCandidates.isNotEmpty && + !AppSettings + .displayNavigationRail + .value && + !FluffyThemes.isColumnMode(context)) + ActiveFilter.spaces, + ] + .map( + (filter) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + ), + child: FilterChip( + selected: + filter == controller.activeFilter, + onSelected: (_) => + controller.setActiveFilter(filter), + label: Text( + filter.toLocalizedString(context), + ), + ), + ), + ) + .toList(), + ), + ), + if (controller.isSearchMode) + SearchTitle( + title: L10n.of(context).chats, + icon: const Icon(Icons.forum_outlined), + ), + if (client.prevBatch != null && + rooms.isEmpty && + !controller.isSearchMode) ...[ + Column( + mainAxisAlignment: .center, + children: [ + Stack( + alignment: Alignment.center, + children: [ + const Column( + mainAxisSize: .min, + children: [ + DummyChatListItem(opacity: 0.5, animate: false), + DummyChatListItem(opacity: 0.3, animate: false), + ], + ), + Icon( + CupertinoIcons.chat_bubble_text_fill, + size: 128, + color: theme.colorScheme.secondary, + ), + ], + ), + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + client.rooms.isEmpty + ? L10n.of(context).noChatsFoundHere + : L10n.of(context).noMoreChatsFound, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: theme.colorScheme.secondary, + ), + ), + ), + ], + ), + ], + ]), ), if (client.prevBatch == null) SliverList( @@ -257,10 +255,7 @@ class ChatListViewBody extends StatelessWidget { } class PublicRoomsHorizontalList extends StatelessWidget { - const PublicRoomsHorizontalList({ - super.key, - required this.publicRooms, - }); + const PublicRoomsHorizontalList({super.key, required this.publicRooms}); final List? publicRooms; @@ -279,7 +274,8 @@ class PublicRoomsHorizontalList extends StatelessWidget { scrollDirection: Axis.horizontal, itemCount: publicRooms.length, itemBuilder: (context, i) => _SearchItem( - title: publicRooms[i].name ?? + title: + publicRooms[i].name ?? publicRooms[i].canonicalAlias?.localpart ?? L10n.of(context).group, avatar: publicRooms[i].avatarUrl, @@ -310,31 +306,26 @@ class _SearchItem extends StatelessWidget { @override Widget build(BuildContext context) => InkWell( - onTap: onPressed, - child: SizedBox( - width: 84, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const SizedBox(height: 8), - Avatar( - mxContent: avatar, - name: title, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - title, - maxLines: 2, - textAlign: TextAlign.center, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 12, - ), - ), - ), - ], + onTap: onPressed, + child: SizedBox( + width: 84, + child: Column( + mainAxisSize: .min, + children: [ + const SizedBox(height: 8), + Avatar(mxContent: avatar, name: title), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + title, + maxLines: 2, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 12), + ), ), - ), - ); + ], + ), + ), + ); } diff --git a/lib/pages/chat_list/chat_list_header.dart b/lib/pages/chat_list/chat_list_header.dart index ca2bfcbe2..b1b876fd4 100644 --- a/lib/pages/chat_list/chat_list_header.dart +++ b/lib/pages/chat_list/chat_list_header.dart @@ -34,19 +34,19 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { title: StreamBuilder( stream: client.onSyncStatus.stream, builder: (context, snapshot) { - final status = client.onSyncStatus.value ?? + final status = + client.onSyncStatus.value ?? const SyncStatusUpdate(SyncStatus.waitingForResponse); - final hide = client.onSync.value != null && + final hide = + client.onSync.value != null && status.status != SyncStatus.error && client.prevBatch != null; return TextField( controller: controller.searchController, focusNode: controller.searchFocusNode, textInputAction: TextInputAction.search, - onChanged: (text) => controller.onSearchEnter( - text, - globalSearch: globalSearch, - ), + onChanged: (text) => + controller.onSearchEnter(text, globalSearch: globalSearch), decoration: InputDecoration( filled: true, fillColor: theme.colorScheme.secondaryContainer, @@ -66,19 +66,19 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { ), prefixIcon: hide ? controller.isSearchMode - ? IconButton( - tooltip: L10n.of(context).cancel, - icon: const Icon(Icons.close_outlined), - onPressed: controller.cancelSearch, - color: theme.colorScheme.onPrimaryContainer, - ) - : IconButton( - onPressed: controller.startSearch, - icon: Icon( - Icons.search_outlined, + ? IconButton( + tooltip: L10n.of(context).cancel, + icon: const Icon(Icons.close_outlined), + onPressed: controller.cancelSearch, color: theme.colorScheme.onPrimaryContainer, - ), - ) + ) + : IconButton( + onPressed: controller.startSearch, + icon: Icon( + Icons.search_outlined, + color: theme.colorScheme.onPrimaryContainer, + ), + ) : Container( margin: const EdgeInsets.all(12), width: 8, @@ -97,37 +97,34 @@ class ChatListHeader extends StatelessWidget implements PreferredSizeWidget { ), suffixIcon: controller.isSearchMode && globalSearch ? controller.isSearching - ? const Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 12, - ), - child: SizedBox.square( - dimension: 24, - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, + ? const Padding( + padding: EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 12, ), - ), - ) - : TextButton.icon( - onPressed: controller.setServer, - style: TextButton.styleFrom( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(99), + child: SizedBox.square( + dimension: 24, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2, + ), ), - textStyle: const TextStyle(fontSize: 12), - ), - icon: const Icon(Icons.edit_outlined, size: 16), - label: Text( - controller.searchServer ?? - Matrix.of(context).client.homeserver!.host, - maxLines: 2, - ), - ) - : SizedBox( - width: 0, - child: ClientChooserButton(controller), - ), + ) + : TextButton.icon( + onPressed: controller.setServer, + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(99), + ), + textStyle: const TextStyle(fontSize: 12), + ), + icon: const Icon(Icons.edit_outlined, size: 16), + label: Text( + controller.searchServer ?? + Matrix.of(context).client.homeserver!.host, + maxLines: 2, + ), + ) + : SizedBox(width: 0, child: ClientChooserButton(controller)), ), ); }, diff --git a/lib/pages/chat_list/chat_list_item.dart b/lib/pages/chat_list/chat_list_item.dart index 995a7eaa5..c06c22509 100644 --- a/lib/pages/chat_list/chat_list_item.dart +++ b/lib/pages/chat_list/chat_list_item.dart @@ -48,8 +48,9 @@ class ChatListItem extends StatelessWidget { final directChatMatrixId = room.directChatMatrixID; final isDirectChat = directChatMatrixId != null; final hasNotifications = room.notificationCount > 0; - final backgroundColor = - activeChat ? theme.colorScheme.secondaryContainer : null; + final backgroundColor = activeChat + ? theme.colorScheme.secondaryContainer + : null; final displayname = room.getLocalizedDisplayname( MatrixLocals(L10n.of(context)), ); @@ -64,10 +65,7 @@ class ChatListItem extends StatelessWidget { final space = this.space; return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 1, - ), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 1), child: Material( borderRadius: BorderRadius.circular(AppConfig.borderRadius), clipBehavior: Clip.hardEdge, @@ -96,7 +94,8 @@ class ChatListItem extends StatelessWidget { child: Avatar( border: BorderSide( width: 2, - color: backgroundColor ?? + color: + backgroundColor ?? theme.colorScheme.surface, ), borderRadius: BorderRadius.circular( @@ -114,14 +113,15 @@ class ChatListItem extends StatelessWidget { child: Avatar( border: space == null ? room.isSpace - ? BorderSide( - width: 1, - color: theme.dividerColor, - ) - : null + ? BorderSide( + width: 1, + color: theme.dividerColor, + ) + : null : BorderSide( width: 2, - color: backgroundColor ?? + color: + backgroundColor ?? theme.colorScheme.surface, ), borderRadius: room.isSpace @@ -182,10 +182,7 @@ class ChatListItem extends StatelessWidget { if (isMuted) const Padding( padding: EdgeInsets.only(left: 4.0), - child: Icon( - Icons.notifications_off_outlined, - size: 16, - ), + child: Icon(Icons.notifications_off_outlined, size: 16), ), if (room.isFavourite) Padding( @@ -202,8 +199,9 @@ class ChatListItem extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 4.0), child: Text( - room.latestEventReceivedTime - .localizedTimeShort(context), + room.latestEventReceivedTime.localizedTimeShort( + context, + ), style: TextStyle( fontSize: 12, color: theme.colorScheme.outline, @@ -213,8 +211,8 @@ class ChatListItem extends StatelessWidget { ], ), subtitle: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: .start, + mainAxisAlignment: .center, children: [ if (typingText.isEmpty && ownMessage && @@ -240,111 +238,111 @@ class ChatListItem extends StatelessWidget { ), ) : room.lastEvent?.relationshipType == - RelationshipTypes.thread - ? Container( - decoration: BoxDecoration( - border: Border.all( + RelationshipTypes.thread + ? Container( + decoration: BoxDecoration( + border: Border.all( + color: theme.colorScheme.outline, + ), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), + ), + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), + margin: const EdgeInsets.only(right: 4.0), + child: Row( + mainAxisSize: .min, + children: [ + Icon( + Icons.message_outlined, + size: 12, + color: theme.colorScheme.outline, + ), + const SizedBox(width: 4), + Text( + L10n.of(context).thread, + style: TextStyle( + fontSize: 12, color: theme.colorScheme.outline, ), - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), ), - padding: - const EdgeInsets.symmetric(horizontal: 8.0), - margin: const EdgeInsets.only(right: 4.0), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.message_outlined, - size: 12, - color: theme.colorScheme.outline, - ), - const SizedBox(width: 4), - Text( - L10n.of(context).thread, - style: TextStyle( - fontSize: 12, - color: theme.colorScheme.outline, - ), - ), - ], - ), - ) - : const SizedBox.shrink(), + ], + ), + ) + : const SizedBox.shrink(), ), Expanded( child: room.isSpace && room.membership == Membership.join ? Text( - L10n.of(context) - .countChats(room.spaceChildren.length), + L10n.of( + context, + ).countChats(room.spaceChildren.length), style: TextStyle(color: theme.colorScheme.outline), ) : typingText.isNotEmpty - ? Text( - typingText, - style: TextStyle( - color: theme.colorScheme.primary, - ), - maxLines: 1, - softWrap: false, - ) - : FutureBuilder( - key: ValueKey( - '${lastEvent?.eventId}_${lastEvent?.type}_${lastEvent?.redacted}', - ), - future: needLastEventSender - ? lastEvent.calcLocalizedBody( - MatrixLocals(L10n.of(context)), - hideReply: true, - hideEdit: true, - plaintextBody: true, - removeMarkdown: true, - withSenderNamePrefix: (!isDirectChat || - directChatMatrixId != - room.lastEvent?.senderId), - ) + ? Text( + typingText, + style: TextStyle(color: theme.colorScheme.primary), + maxLines: 1, + softWrap: false, + ) + : FutureBuilder( + key: ValueKey( + '${lastEvent?.eventId}_${lastEvent?.type}_${lastEvent?.redacted}', + ), + future: needLastEventSender + ? lastEvent.calcLocalizedBody( + MatrixLocals(L10n.of(context)), + hideReply: true, + hideEdit: true, + plaintextBody: true, + removeMarkdown: true, + withSenderNamePrefix: + (!isDirectChat || + directChatMatrixId != + room.lastEvent?.senderId), + ) + : null, + initialData: lastEvent?.calcLocalizedBodyFallback( + MatrixLocals(L10n.of(context)), + hideReply: true, + hideEdit: true, + plaintextBody: true, + removeMarkdown: true, + withSenderNamePrefix: + (!isDirectChat || + directChatMatrixId != + room.lastEvent?.senderId), + ), + builder: (context, snapshot) => Text( + room.membership == Membership.invite + ? room + .getState( + EventTypes.RoomMember, + room.client.userID!, + ) + ?.content + .tryGet('reason') ?? + (isDirectChat + ? L10n.of(context).newChatRequest + : L10n.of(context).inviteGroupChat) + : snapshot.data ?? + L10n.of(context).noMessagesYet, + softWrap: false, + maxLines: room.notificationCount >= 1 ? 2 : 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: unread || room.hasNewMessages + ? theme.colorScheme.onSurface + : theme.colorScheme.outline, + decoration: room.lastEvent?.redacted == true + ? TextDecoration.lineThrough : null, - initialData: - lastEvent?.calcLocalizedBodyFallback( - MatrixLocals(L10n.of(context)), - hideReply: true, - hideEdit: true, - plaintextBody: true, - removeMarkdown: true, - withSenderNamePrefix: (!isDirectChat || - directChatMatrixId != - room.lastEvent?.senderId), - ), - builder: (context, snapshot) => Text( - room.membership == Membership.invite - ? room - .getState( - EventTypes.RoomMember, - room.client.userID!, - ) - ?.content - .tryGet('reason') ?? - (isDirectChat - ? L10n.of(context).newChatRequest - : L10n.of(context) - .inviteGroupChat) - : snapshot.data ?? - L10n.of(context).noMessagesYet, - softWrap: false, - maxLines: room.notificationCount >= 1 ? 2 : 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - color: unread || room.hasNewMessages - ? theme.colorScheme.onSurface - : theme.colorScheme.outline, - decoration: room.lastEvent?.redacted == true - ? TextDecoration.lineThrough - : null, - ), - ), ), + ), + ), ), const SizedBox(width: 8), UnreadBubble(room: room), @@ -353,27 +351,27 @@ class ChatListItem extends StatelessWidget { onTap: onTap, trailing: onForget == null ? room.membership == Membership.invite - ? IconButton( - tooltip: L10n.of(context).declineInvitation, - icon: const Icon(Icons.delete_forever_outlined), - color: theme.colorScheme.error, - onPressed: () async { - final consent = await showOkCancelAlertDialog( - context: context, - title: L10n.of(context).declineInvitation, - message: L10n.of(context).areYouSure, - okLabel: L10n.of(context).yes, - isDestructive: true, - ); - if (consent != OkCancelResult.ok) return; - if (!context.mounted) return; - await showFutureLoadingDialog( - context: context, - future: room.leave, - ); - }, - ) - : null + ? IconButton( + tooltip: L10n.of(context).declineInvitation, + icon: const Icon(Icons.delete_forever_outlined), + color: theme.colorScheme.error, + onPressed: () async { + final consent = await showOkCancelAlertDialog( + context: context, + title: L10n.of(context).declineInvitation, + message: L10n.of(context).areYouSure, + okLabel: L10n.of(context).yes, + isDestructive: true, + ); + if (consent != OkCancelResult.ok) return; + if (!context.mounted) return; + await showFutureLoadingDialog( + context: context, + future: room.leave, + ); + }, + ) + : null : IconButton( icon: const Icon(Icons.delete_outlined), onPressed: onForget, diff --git a/lib/pages/chat_list/chat_list_view.dart b/lib/pages/chat_list/chat_list_view.dart index 1b04bed8c..36a4f67b8 100644 --- a/lib/pages/chat_list/chat_list_view.dart +++ b/lib/pages/chat_list/chat_list_view.dart @@ -38,10 +38,7 @@ class ChatListView extends StatelessWidget { onGoToChats: controller.clearActiveSpace, onGoToSpaceId: controller.setActiveSpace, ), - Container( - color: Theme.of(context).dividerColor, - width: 1, - ), + Container(color: Theme.of(context).dividerColor, width: 1), ], Expanded( child: GestureDetector( @@ -50,8 +47,8 @@ class ChatListView extends StatelessWidget { behavior: HitTestBehavior.translucent, child: Scaffold( body: ChatListViewBody(controller), - floatingActionButton: !controller.isSearchMode && - controller.activeSpaceId == null + floatingActionButton: + !controller.isSearchMode && controller.activeSpaceId == null ? FloatingActionButton.extended( onPressed: () => context.go('/rooms/newprivatechat'), icon: const Icon(Icons.add_outlined), diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index 9161226f9..50c9f4a72 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -25,8 +25,8 @@ class ClientChooserButton extends StatelessWidget { (a, b) => a!.isValidMatrixId == b!.isValidMatrixId ? 0 : a.isValidMatrixId && !b.isValidMatrixId - ? -1 - : 1, + ? -1 + : 1, ); return >[ PopupMenuItem( @@ -97,8 +97,8 @@ class ClientChooserButton extends StatelessWidget { PopupMenuItem( value: null, child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + crossAxisAlignment: .start, + mainAxisSize: .min, children: [ Text( bundle!, @@ -123,7 +123,8 @@ class ClientChooserButton extends StatelessWidget { children: [ Avatar( mxContent: snapshot.data?.avatarUrl, - name: snapshot.data?.displayName ?? + name: + snapshot.data?.displayName ?? client.userID!.localpart, size: 32, ), @@ -193,10 +194,7 @@ class ClientChooserButton extends StatelessWidget { ); } - void _clientSelected( - Object object, - BuildContext context, - ) async { + void _clientSelected(Object object, BuildContext context) async { if (object is Client) { controller.setActiveClient(object); } else if (object is String) { diff --git a/lib/pages/chat_list/navi_rail_item.dart b/lib/pages/chat_list/navi_rail_item.dart index f29a16b5d..b0c50a923 100644 --- a/lib/pages/chat_list/navi_rail_item.dart +++ b/lib/pages/chat_list/navi_rail_item.dart @@ -46,8 +46,8 @@ class NaviRailItem extends StatelessWidget { child: AnimatedContainer( width: isSelected ? FluffyThemes.isColumnMode(context) - ? 8 - : 4 + ? 8 + : 4 : 0, duration: FluffyThemes.animationDuration, curve: FluffyThemes.animationCurve, diff --git a/lib/pages/chat_list/search_title.dart b/lib/pages/chat_list/search_title.dart index 496a5feec..95bb5364d 100644 --- a/lib/pages/chat_list/search_title.dart +++ b/lib/pages/chat_list/search_title.dart @@ -22,14 +22,8 @@ class SearchTitle extends StatelessWidget { return Material( shape: Border( - top: BorderSide( - color: theme.dividerColor, - width: 1, - ), - bottom: BorderSide( - color: theme.dividerColor, - width: 1, - ), + top: BorderSide(color: theme.dividerColor, width: 1), + bottom: BorderSide(color: theme.dividerColor, width: 1), ), color: color ?? theme.colorScheme.surface, child: InkWell( @@ -38,10 +32,7 @@ class SearchTitle extends StatelessWidget { child: Align( alignment: Alignment.centerLeft, child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: IconTheme( data: theme.iconTheme.copyWith(size: 16), child: Row( diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index a16220c4e..16058eb74 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -28,12 +28,7 @@ enum AddRoomType { chat, subspace } enum SpaceChildAction { edit, moveToSpace, removeFromSpace } -enum SpaceActions { - settings, - invite, - members, - leave, -} +enum SpaceActions { settings, invite, members, leave } class SpaceView extends StatefulWidget { final String spaceId; @@ -124,8 +119,9 @@ class _SpaceViewState extends State { } catch (e, s) { Logs().w('Unable to load hierarchy', e, s); if (!mounted) return; - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); setState(() { _isLoading = false; }); @@ -141,9 +137,7 @@ class _SpaceViewState extends State { builder: (_) => PublicRoomDialog( chunk: item, via: space?.spaceChildren - .firstWhereOrNull( - (child) => child.roomId == item.roomId, - ) + .firstWhereOrNull((child) => child.roomId == item.roomId) ?.via, ), ); @@ -224,8 +218,9 @@ class _SpaceViewState extends State { if (roomType == AddRoomType.subspace) { roomId = await client.createSpace( name: names, - visibility: - isPublicSpace ? sdk.Visibility.public : sdk.Visibility.private, + visibility: isPublicSpace + ? sdk.Visibility.public + : sdk.Visibility.private, ); } else { roomId = await client.createGroupChat( @@ -234,8 +229,9 @@ class _SpaceViewState extends State { preset: isPublicSpace ? CreateRoomPreset.publicChat : CreateRoomPreset.privateChat, - visibility: - isPublicSpace ? sdk.Visibility.public : sdk.Visibility.private, + visibility: isPublicSpace + ? sdk.Visibility.public + : sdk.Visibility.private, initialState: isPublicSpace ? null : [ @@ -289,7 +285,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceChildAction.moveToSpace, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.move_down_outlined), const SizedBox(width: 12), @@ -300,7 +296,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceChildAction.edit, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.edit_outlined), const SizedBox(width: 12), @@ -311,7 +307,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceChildAction.removeFromSpace, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.group_remove_outlined), const SizedBox(width: 12), @@ -344,8 +340,9 @@ class _SpaceViewState extends State { .map( (space) => AdaptiveModalAction( value: space, - label: space - .getLocalizedDisplayname(MatrixLocals(L10n.of(context))), + label: space.getLocalizedDisplayname( + MatrixLocals(L10n.of(context)), + ), ), ) .toList(), @@ -392,19 +389,12 @@ class _SpaceViewState extends State { final displayname = room?.getLocalizedDisplayname() ?? L10n.of(context).nothingFound; const avatarSize = Avatar.defaultSize / 1.5; - final isAdmin = room?.canChangeStateEvent( - EventTypes.SpaceChild, - ) == - true; + final isAdmin = room?.canChangeStateEvent(EventTypes.SpaceChild) == true; return Scaffold( appBar: AppBar( leading: FluffyThemes.isColumnMode(context) ? null - : Center( - child: CloseButton( - onPressed: widget.onBack, - ), - ), + : Center(child: CloseButton(onPressed: widget.onBack)), automaticallyImplyLeading: false, titleSpacing: FluffyThemes.isColumnMode(context) ? null : 0, title: ListTile( @@ -432,7 +422,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: AddRoomType.chat, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.group_add_outlined), const SizedBox(width: 12), @@ -443,7 +433,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: AddRoomType.subspace, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.workspaces_outlined), const SizedBox(width: 12), @@ -460,7 +450,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceActions.settings, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.settings_outlined), const SizedBox(width: 12), @@ -471,7 +461,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceActions.invite, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.person_add_outlined), const SizedBox(width: 12), @@ -482,7 +472,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceActions.members, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.group_outlined), const SizedBox(width: 12), @@ -497,7 +487,7 @@ class _SpaceViewState extends State { PopupMenuItem( value: SpaceActions.leave, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.delete_outlined), const SizedBox(width: 12), @@ -510,12 +500,7 @@ class _SpaceViewState extends State { ], ), body: room == null - ? const Center( - child: Icon( - Icons.search_outlined, - size: 80, - ), - ) + ? const Center(child: Icon(Icons.search_outlined, size: 80)) : StreamBuilder( stream: room.client.onSync.stream .where((s) => s.hasRoomUpdate) @@ -573,7 +558,8 @@ class _SpaceViewState extends State { ); } final item = _discoveredChildren[i]; - final displayname = item.name ?? + final displayname = + item.name ?? item.canonicalAlias ?? L10n.of(context).emptyChat; if (!displayname.toLowerCase().contains(filter)) { @@ -589,27 +575,31 @@ class _SpaceViewState extends State { vertical: 1, ), child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), clipBehavior: Clip.hardEdge, - color: joinedRoom != null && + 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), + 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, - ) + context, + item.roomId, + ) : null, leading: hovered && isAdmin ? SizedBox.square( @@ -618,16 +608,18 @@ class _SpaceViewState extends State { splashRadius: avatarSize, iconSize: 14, style: IconButton.styleFrom( - foregroundColor: theme.colorScheme + foregroundColor: theme + .colorScheme .onTertiaryContainer, backgroundColor: theme - .colorScheme.tertiaryContainer, + .colorScheme + .tertiaryContainer, ), onPressed: () => _showSpaceChildEditMenu( - context, - item.roomId, - ), + context, + item.roomId, + ), icon: const Icon(Icons.edit_outlined), ), ) @@ -637,11 +629,13 @@ class _SpaceViewState extends State { name: '#', backgroundColor: theme.colorScheme.surfaceContainer, - textColor: item.name?.darkColor ?? + textColor: + item.name?.darkColor ?? theme.colorScheme.onSurface, border: item.roomType == 'm.space' ? BorderSide( - color: theme.colorScheme + color: theme + .colorScheme .surfaceContainerHighest, ) : null, diff --git a/lib/pages/chat_list/status_msg_list.dart b/lib/pages/chat_list/status_msg_list.dart index f49da939d..de2690eb8 100644 --- a/lib/pages/chat_list/status_msg_list.dart +++ b/lib/pages/chat_list/status_msg_list.dart @@ -13,10 +13,7 @@ import '../../widgets/adaptive_dialogs/user_dialog.dart'; class StatusMessageList extends StatelessWidget { final void Function() onStatusEdit; - const StatusMessageList({ - required this.onStatusEdit, - super.key, - }); + const StatusMessageList({required this.onStatusEdit, super.key}); static const double height = 116; @@ -24,10 +21,7 @@ class StatusMessageList extends StatelessWidget { final client = Matrix.of(context).client; if (profile.userId == client.userID) return onStatusEdit(); - UserDialog.show( - context: context, - profile: profile, - ); + UserDialog.show(context: context, profile: profile); return; } @@ -56,8 +50,9 @@ class StatusMessageList extends StatelessWidget { ), ), builder: (context, snapshot) { - final presences = - snapshot.data?.where(isInterestingPresence).toList(); + final presences = snapshot.data + ?.where(isInterestingPresence) + .toList(); // If no other presences than the own entry is interesting, we // hide the presence header. @@ -121,7 +116,8 @@ class PresenceAvatar extends StatelessWidget { final theme = Theme.of(context); final profile = snapshot.data; - final displayName = profile?.displayName ?? + final displayName = + profile?.displayName ?? presence.userid.localpart ?? presence.userid; final statusMsg = presence.statusMsg; @@ -152,8 +148,9 @@ class PresenceAvatar extends StatelessWidget { padding: const EdgeInsets.all(3), decoration: BoxDecoration( gradient: presence.gradient, - borderRadius: - BorderRadius.circular(avatarSize), + borderRadius: BorderRadius.circular( + avatarSize, + ), ), alignment: Alignment.center, child: Container( @@ -161,8 +158,9 @@ class PresenceAvatar extends StatelessWidget { alignment: Alignment.center, decoration: BoxDecoration( color: theme.colorScheme.surface, - borderRadius: - BorderRadius.circular(avatarSize), + borderRadius: BorderRadius.circular( + avatarSize, + ), ), padding: const EdgeInsets.all(3.0), child: Avatar( @@ -202,9 +200,8 @@ class PresenceAvatar extends StatelessWidget { right: 8, child: Column( spacing: 2, - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, + crossAxisAlignment: .start, + mainAxisSize: .min, children: [ Material( elevation: statusMsgBubbleElevation, @@ -230,8 +227,9 @@ class PresenceAvatar extends StatelessWidget { ), ), Padding( - padding: - const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.only( + left: 8.0, + ), child: Material( color: statusMsgBubbleColor, elevation: statusMsgBubbleElevation, @@ -246,8 +244,9 @@ class PresenceAvatar extends StatelessWidget { ), ), Padding( - padding: - const EdgeInsets.only(left: 13.0), + padding: const EdgeInsets.only( + left: 13.0, + ), child: Material( color: statusMsgBubbleColor, elevation: statusMsgBubbleElevation, @@ -280,9 +279,7 @@ class PresenceAvatar extends StatelessWidget { textAlign: TextAlign.center, maxLines: 1, overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 11, - ), + style: const TextStyle(fontSize: 11), ), ), ], @@ -296,10 +293,12 @@ class PresenceAvatar extends StatelessWidget { extension on Client { Set get interestingPresences { - final allHeroes = rooms.map((room) => room.summary.mHeroes).fold( - {}, - (previousValue, element) => previousValue..addAll(element ?? {}), - ); + final allHeroes = rooms + .map((room) => room.summary.mHeroes) + .fold( + {}, + (previousValue, element) => previousValue..addAll(element ?? {}), + ); allHeroes.add(userID!); return allHeroes; } @@ -317,31 +316,23 @@ extension on CachedPresence { LinearGradient get gradient => presence.isOnline == true ? LinearGradient( - colors: [ - Colors.green, - Colors.green.shade200, - Colors.green.shade900, - ], + colors: [Colors.green, Colors.green.shade200, Colors.green.shade900], begin: Alignment.topLeft, end: Alignment.bottomRight, ) : presence.isUnavailable - ? LinearGradient( - colors: [ - Colors.yellow, - Colors.yellow.shade200, - Colors.yellow.shade900, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ) - : LinearGradient( - colors: [ - Colors.grey, - Colors.grey.shade200, - Colors.grey.shade900, - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ); + ? LinearGradient( + colors: [ + Colors.yellow, + Colors.yellow.shade200, + Colors.yellow.shade900, + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ) + : LinearGradient( + colors: [Colors.grey, Colors.grey.shade200, Colors.grey.shade900], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ); } diff --git a/lib/pages/chat_list/unread_bubble.dart b/lib/pages/chat_list/unread_bubble.dart index 964094f97..29266ff0f 100644 --- a/lib/pages/chat_list/unread_bubble.dart +++ b/lib/pages/chat_list/unread_bubble.dart @@ -15,8 +15,8 @@ class UnreadBubble extends StatelessWidget { final hasNotifications = room.notificationCount > 0; final unreadBubbleSize = unread || room.hasNewMessages ? room.notificationCount > 0 - ? 20.0 - : 14.0 + ? 20.0 + : 14.0 : 0.0; return AnimatedContainer( duration: FluffyThemes.animationDuration, @@ -27,13 +27,13 @@ class UnreadBubble extends StatelessWidget { width: !hasNotifications && !unread && !room.hasNewMessages ? 0 : (unreadBubbleSize - 9) * room.notificationCount.toString().length + - 9, + 9, decoration: BoxDecoration( color: room.highlightCount > 0 ? theme.colorScheme.error : hasNotifications || room.markedUnread - ? theme.colorScheme.primary - : theme.colorScheme.primaryContainer, + ? theme.colorScheme.primary + : theme.colorScheme.primaryContainer, borderRadius: BorderRadius.circular(7), ), child: hasNotifications @@ -43,8 +43,8 @@ class UnreadBubble extends StatelessWidget { color: room.highlightCount > 0 ? theme.colorScheme.onError : hasNotifications - ? theme.colorScheme.onPrimary - : theme.colorScheme.onPrimaryContainer, + ? theme.colorScheme.onPrimary + : theme.colorScheme.onPrimaryContainer, fontSize: 13, fontWeight: FontWeight.w500, ), diff --git a/lib/pages/chat_members/chat_members.dart b/lib/pages/chat_members/chat_members.dart index 36b59f3f9..21cbc5258 100644 --- a/lib/pages/chat_members/chat_members.dart +++ b/lib/pages/chat_members/chat_members.dart @@ -32,8 +32,7 @@ class ChatMembersController extends State { void setFilter([dynamic _]) async { final filter = filterController.text.toLowerCase().trim(); - final members = this - .members + final members = this.members ?.where((member) => member.membership == membershipFilter) .toList(); @@ -45,14 +44,15 @@ class ChatMembersController extends State { return; } setState(() { - filteredMembers = members - ?.where( - (user) => - user.displayName?.toLowerCase().contains(filter) ?? - user.id.toLowerCase().contains(filter), - ) - .toList() - ?..sort((b, a) => a.powerLevel.compareTo(b.powerLevel)); + filteredMembers = + members + ?.where( + (user) => + user.displayName?.toLowerCase().contains(filter) ?? + user.id.toLowerCase().contains(filter), + ) + .toList() + ?..sort((b, a) => a.powerLevel.compareTo(b.powerLevel)); }); } @@ -62,8 +62,7 @@ class ChatMembersController extends State { setState(() { error = null; }); - final participants = await Matrix.of(context) - .client + final participants = await Matrix.of(context).client .getRoomById(widget.roomId) ?.requestParticipants( [...Membership.values]..remove(Membership.leave), @@ -76,8 +75,11 @@ class ChatMembersController extends State { }); setFilter(); } catch (e, s) { - Logs() - .d('Unable to request participants. Try again in 3 seconds...', e, s); + Logs().d( + 'Unable to request participants. Try again in 3 seconds...', + e, + s, + ); setState(() { error = e; }); @@ -91,14 +93,12 @@ class ChatMembersController extends State { super.initState(); refreshMembers(); - _updateSub = Matrix.of(context) - .client - .onSync - .stream + _updateSub = Matrix.of(context).client.onSync.stream .where( (syncUpdate) => - syncUpdate.rooms?.join?[widget.roomId]?.timeline?.events - ?.any((state) => state.type == EventTypes.RoomMember) ?? + syncUpdate.rooms?.join?[widget.roomId]?.timeline?.events?.any( + (state) => state.type == EventTypes.RoomMember, + ) ?? false, ) .listen(refreshMembers); diff --git a/lib/pages/chat_members/chat_members_view.dart b/lib/pages/chat_members/chat_members_view.dart index e4c812e8a..89707a100 100644 --- a/lib/pages/chat_members/chat_members_view.dart +++ b/lib/pages/chat_members/chat_members_view.dart @@ -17,13 +17,12 @@ class ChatMembersView extends StatelessWidget { @override Widget build(BuildContext context) { - final room = - Matrix.of(context).client.getRoomById(controller.widget.roomId); + final room = Matrix.of( + context, + ).client.getRoomById(controller.widget.roomId); if (room == null) { return Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).oopsSomethingWentWrong), - ), + appBar: AppBar(title: Text(L10n.of(context).oopsSomethingWentWrong)), body: Center( child: Text(L10n.of(context).youAreNoLongerParticipatingInThisChat), ), @@ -32,7 +31,8 @@ class ChatMembersView extends StatelessWidget { final members = controller.filteredMembers; - final roomCount = (room.summary.mJoinedMemberCount ?? 0) + + final roomCount = + (room.summary.mJoinedMemberCount ?? 0) + (room.summary.mInvitedMemberCount ?? 0); final error = controller.error; @@ -41,16 +41,12 @@ class ChatMembersView extends StatelessWidget { return Scaffold( appBar: AppBar( leading: const Center(child: BackButton()), - title: Text( - L10n.of(context).countParticipants(roomCount), - ), + title: Text(L10n.of(context).countParticipants(roomCount)), actions: [ if (room.canInvite) IconButton( onPressed: () => context.go('/rooms/${room.id}/invite'), - icon: const Icon( - Icons.person_add_outlined, - ), + icon: const Icon(Icons.person_add_outlined), ), ], ), @@ -62,7 +58,7 @@ class ChatMembersView extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(16.0), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.error_outline), Text(error.toLocalizedString(context)), @@ -77,120 +73,117 @@ class ChatMembersView extends StatelessWidget { ), ) : members == null - ? const Center( - child: Padding( - padding: EdgeInsets.all(16.0), - child: CircularProgressIndicator.adaptive(), - ), - ) - : ListView.builder( - shrinkWrap: true, - itemCount: members.length + 1, - itemBuilder: (context, i) { - if (i == 0) { - final availableFilters = Membership.values - .where( - (membership) => - controller.members?.any( - (member) => member.membership == membership, - ) ?? - false, - ) - .toList(); - availableFilters - .sort((a, b) => a == Membership.join ? -1 : 1); - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - Padding( - padding: const EdgeInsets.all(16.0), - child: TextField( - controller: controller.filterController, - onChanged: controller.setFilter, - decoration: InputDecoration( - filled: true, - fillColor: - theme.colorScheme.secondaryContainer, - border: OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.circular(99), - ), - hintStyle: TextStyle( - color: theme.colorScheme.onPrimaryContainer, - fontWeight: FontWeight.normal, - ), - prefixIcon: const Icon(Icons.search_outlined), - hintText: L10n.of(context).search, + ? const Center( + child: Padding( + padding: EdgeInsets.all(16.0), + child: CircularProgressIndicator.adaptive(), + ), + ) + : ListView.builder( + shrinkWrap: true, + itemCount: members.length + 1, + itemBuilder: (context, i) { + if (i == 0) { + final availableFilters = Membership.values + .where( + (membership) => + controller.members?.any( + (member) => member.membership == membership, + ) ?? + false, + ) + .toList(); + availableFilters.sort( + (a, b) => a == Membership.join ? -1 : 1, + ); + return Column( + mainAxisSize: .min, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: TextField( + controller: controller.filterController, + onChanged: controller.setFilter, + decoration: InputDecoration( + filled: true, + fillColor: theme.colorScheme.secondaryContainer, + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(99), + ), + hintStyle: TextStyle( + color: theme.colorScheme.onPrimaryContainer, + fontWeight: FontWeight.normal, + ), + prefixIcon: const Icon(Icons.search_outlined), + hintText: L10n.of(context).search, + ), + ), + ), + if (availableFilters.length > 1) + SizedBox( + height: 64, + child: ListView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 12.0, + ), + scrollDirection: Axis.horizontal, + itemCount: availableFilters.length, + itemBuilder: (context, i) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 4.0, + ), + child: FilterChip( + label: Text(switch (availableFilters[i]) { + Membership.ban => L10n.of(context).banned, + Membership.invite => + L10n.of(context).countInvited( + room.summary.mInvitedMemberCount ?? + controller.members + ?.where( + (member) => + member.membership == + Membership.invite, + ) + .length ?? + 0, + ), + Membership.join => + L10n.of(context).countParticipants( + room.summary.mJoinedMemberCount ?? + controller.members + ?.where( + (member) => + member.membership == + Membership.join, + ) + .length ?? + 0, + ), + Membership.knock => L10n.of( + context, + ).knocking, + Membership.leave => L10n.of( + context, + ).leftTheChat, + }), + selected: + controller.membershipFilter == + availableFilters[i], + onSelected: (_) => controller + .setMembershipFilter(availableFilters[i]), ), ), ), - if (availableFilters.length > 1) - SizedBox( - height: 64, - child: ListView.builder( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 12.0, - ), - scrollDirection: Axis.horizontal, - itemCount: availableFilters.length, - itemBuilder: (context, i) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 4.0, - ), - child: FilterChip( - label: Text( - switch (availableFilters[i]) { - Membership.ban => - L10n.of(context).banned, - Membership.invite => - L10n.of(context).countInvited( - room.summary - .mInvitedMemberCount ?? - controller.members - ?.where( - (member) => - member.membership == - Membership.invite, - ) - .length ?? - 0, - ), - Membership.join => - L10n.of(context).countParticipants( - room.summary.mJoinedMemberCount ?? - controller.members - ?.where( - (member) => - member.membership == - Membership.join, - ) - .length ?? - 0, - ), - Membership.knock => - L10n.of(context).knocking, - Membership.leave => - L10n.of(context).leftTheChat, - }, - ), - selected: controller.membershipFilter == - availableFilters[i], - onSelected: (_) => - controller.setMembershipFilter( - availableFilters[i], - ), - ), - ), - ), - ), - ], - ); - } - i--; - return ParticipantListItem(members[i]); - }, - ), + ), + ], + ); + } + i--; + return ParticipantListItem(members[i]); + }, + ), ), ); } diff --git a/lib/pages/chat_permissions_settings/chat_permissions_settings.dart b/lib/pages/chat_permissions_settings/chat_permissions_settings.dart index 28f0a43b3..f9d5afb82 100644 --- a/lib/pages/chat_permissions_settings/chat_permissions_settings.dart +++ b/lib/pages/chat_permissions_settings/chat_permissions_settings.dart @@ -30,9 +30,9 @@ class ChatPermissionsSettingsController extends State { }) async { final room = Matrix.of(context).client.getRoomById(roomId!)!; if (!room.canSendEvent(EventTypes.RoomPowerLevels)) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context).noPermission)), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(L10n.of(context).noPermission))); return; } newLevel ??= await showPermissionChooser( @@ -64,12 +64,13 @@ class ChatPermissionsSettingsController extends State { } Stream get onChanged => Matrix.of(context).client.onSync.stream.where( - (e) => - (e.rooms?.join?.containsKey(roomId) ?? false) && - (e.rooms!.join![roomId!]?.timeline?.events - ?.any((s) => s.type == EventTypes.RoomPowerLevels) ?? - false), - ); + (e) => + (e.rooms?.join?.containsKey(roomId) ?? false) && + (e.rooms!.join![roomId!]?.timeline?.events?.any( + (s) => s.type == EventTypes.RoomPowerLevels, + ) ?? + false), + ); @override Widget build(BuildContext context) => ChatPermissionsSettingsView(this); diff --git a/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart b/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart index a1f7486e1..e904403a1 100644 --- a/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart +++ b/lib/pages/chat_permissions_settings/chat_permissions_settings_view.dart @@ -45,9 +45,7 @@ class ChatPermissionsSettingsView extends StatelessWidget { children: [ ListTile( leading: const Icon(Icons.info_outlined), - subtitle: Text( - L10n.of(context).chatPermissionsDescription, - ), + subtitle: Text(L10n.of(context).chatPermissionsDescription), ), Divider(color: theme.dividerColor), ListTile( @@ -60,7 +58,7 @@ class ChatPermissionsSettingsView extends StatelessWidget { ), ), Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ for (final entry in powerLevels.entries) PermissionsListTile( @@ -87,12 +85,14 @@ class ChatPermissionsSettingsView extends StatelessWidget { Builder( builder: (context) { const key = 'rooms'; - final value = powerLevelsContent - .containsKey('notifications') + final value = + powerLevelsContent.containsKey('notifications') ? powerLevelsContent - .tryGetMap('notifications') - ?.tryGet('rooms') ?? - 0 + .tryGetMap( + 'notifications', + ) + ?.tryGet('rooms') ?? + 0 : 0; return PermissionsListTile( permissionKey: key, diff --git a/lib/pages/chat_permissions_settings/permission_list_tile.dart b/lib/pages/chat_permissions_settings/permission_list_tile.dart index b51cb32e9..7344ba5b7 100644 --- a/lib/pages/chat_permissions_settings/permission_list_tile.dart +++ b/lib/pages/chat_permissions_settings/permission_list_tile.dart @@ -76,8 +76,8 @@ class PermissionsListTile extends StatelessWidget { final color = permission >= 100 ? Colors.orangeAccent : permission >= 50 - ? Colors.blueAccent - : Colors.greenAccent; + ? Colors.blueAccent + : Colors.greenAccent; return ListTile( title: Text( getLocalizedPowerLevelString(context), @@ -110,14 +110,12 @@ class PermissionsListTile extends StatelessWidget { DropdownMenuItem( value: permission >= 100 ? permission : 100, child: Text( - L10n.of(context) - .adminLevel(permission >= 100 ? permission : 100), + L10n.of( + context, + ).adminLevel(permission >= 100 ? permission : 100), ), ), - DropdownMenuItem( - value: null, - child: Text(L10n.of(context).custom), - ), + DropdownMenuItem(value: null, child: Text(L10n.of(context).custom)), ], ), ), diff --git a/lib/pages/chat_search/chat_search_files_tab.dart b/lib/pages/chat_search/chat_search_files_tab.dart index 81fdf5196..229cb6a6e 100644 --- a/lib/pages/chat_search/chat_search_files_tab.dart +++ b/lib/pages/chat_search/chat_search_files_tab.dart @@ -11,10 +11,8 @@ import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; class ChatSearchFilesTab extends StatelessWidget { final Room room; final Stream<(List, String?)>? searchStream; - final void Function({ - String? prevBatch, - List? previousSearchResult, - }) startSearch; + final void Function({String? prevBatch, List? previousSearchResult}) + startSearch; const ChatSearchFilesTab({ required this.room, @@ -32,15 +30,13 @@ class ChatSearchFilesTab extends StatelessWidget { final events = snapshot.data?.$1; if (searchStream == null || events == null) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ const CircularProgressIndicator.adaptive(strokeWidth: 2), const SizedBox(height: 8), Text( L10n.of(context).searchIn( - room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ), + room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), ), ), ], @@ -49,7 +45,7 @@ class ChatSearchFilesTab extends StatelessWidget { if (events.isEmpty) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ const Icon(Icons.file_present_outlined, size: 64), const SizedBox(height: 8), @@ -68,9 +64,7 @@ class ChatSearchFilesTab extends StatelessWidget { return const Padding( padding: EdgeInsets.all(16.0), child: Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ), ); } @@ -90,35 +84,35 @@ class ChatSearchFilesTab extends StatelessWidget { prevBatch: nextBatch, previousSearchResult: events, ), - icon: const Icon( - Icons.arrow_downward_outlined, - ), + icon: const Icon(Icons.arrow_downward_outlined), label: Text(L10n.of(context).searchMore), ), ), ); } final event = events[i]; - final filename = event.content.tryGet('filename') ?? + final filename = + event.content.tryGet('filename') ?? event.content.tryGet('body') ?? L10n.of(context).unknownEvent('File'); final filetype = (filename.contains('.') ? filename.split('.').last.toUpperCase() : event.content - .tryGetMap('info') - ?.tryGet('mimetype') - ?.toUpperCase() ?? - 'UNKNOWN'); + .tryGetMap('info') + ?.tryGet('mimetype') + ?.toUpperCase() ?? + 'UNKNOWN'); final sizeString = event.sizeString; final prevEvent = i > 0 ? events[i - 1] : null; final sameEnvironment = prevEvent == null ? false - : prevEvent.originServerTs - .sameEnvironment(event.originServerTs); + : prevEvent.originServerTs.sameEnvironment( + event.originServerTs, + ); return Padding( padding: const EdgeInsets.all(8.0), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (!sameEnvironment) ...[ Row( @@ -148,8 +142,9 @@ class ChatSearchFilesTab extends StatelessWidget { const SizedBox(height: 4), ], Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), color: theme.colorScheme.onInverseSurface, clipBehavior: Clip.hardEdge, child: ListTile( diff --git a/lib/pages/chat_search/chat_search_images_tab.dart b/lib/pages/chat_search/chat_search_images_tab.dart index 566e44cc1..ecd66a312 100644 --- a/lib/pages/chat_search/chat_search_images_tab.dart +++ b/lib/pages/chat_search/chat_search_images_tab.dart @@ -13,10 +13,8 @@ import 'package:fluffychat/widgets/mxc_image.dart'; class ChatSearchImagesTab extends StatelessWidget { final Room room; final Stream<(List, String?)>? searchStream; - final void Function({ - String? prevBatch, - List? previousSearchResult, - }) startSearch; + final void Function({String? prevBatch, List? previousSearchResult}) + startSearch; const ChatSearchImagesTab({ required this.room, @@ -35,15 +33,13 @@ class ChatSearchImagesTab extends StatelessWidget { final events = snapshot.data?.$1; if (searchStream == null || events == null) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ const CircularProgressIndicator.adaptive(strokeWidth: 2), const SizedBox(height: 8), Text( L10n.of(context).searchIn( - room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ), + room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), ), ), ], @@ -51,7 +47,7 @@ class ChatSearchImagesTab extends StatelessWidget { } if (events.isEmpty) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ const Icon(Icons.photo_outlined, size: 64), const SizedBox(height: 8), @@ -80,9 +76,7 @@ class ChatSearchImagesTab extends StatelessWidget { return const Padding( padding: EdgeInsets.all(16.0), child: Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ), ); } @@ -102,9 +96,7 @@ class ChatSearchImagesTab extends StatelessWidget { prevBatch: nextBatch, previousSearchResult: events, ), - icon: const Icon( - Icons.arrow_downward_outlined, - ), + icon: const Icon(Icons.arrow_downward_outlined), label: Text(L10n.of(context).searchMore), ), ), @@ -113,16 +105,13 @@ class ChatSearchImagesTab extends StatelessWidget { final monthEvents = eventsByMonthList[i].value; return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const SizedBox(height: 4), Row( children: [ Expanded( - child: Container( - height: 1, - color: theme.dividerColor, - ), + child: Container(height: 1, color: theme.dividerColor), ), Padding( padding: const EdgeInsets.all(8.0), @@ -135,10 +124,7 @@ class ChatSearchImagesTab extends StatelessWidget { ), ), Expanded( - child: Container( - height: 1, - color: theme.dividerColor, - ), + child: Container(height: 1, color: theme.dividerColor), ), ], ), @@ -150,39 +136,35 @@ class ChatSearchImagesTab extends StatelessWidget { clipBehavior: Clip.hardEdge, padding: const EdgeInsets.all(padding), crossAxisCount: 3, - children: monthEvents.map( - (event) { - if (event.messageType == MessageTypes.Video) { - return Material( - clipBehavior: Clip.hardEdge, - borderRadius: borderRadius, - child: EventVideoPlayer(event), - ); - } - return InkWell( - onTap: () => showDialog( - context: context, - builder: (_) => ImageViewer( - event, - outerContext: context, - ), - ), + children: monthEvents.map((event) { + if (event.messageType == MessageTypes.Video) { + return Material( + clipBehavior: Clip.hardEdge, borderRadius: borderRadius, - child: Material( - clipBehavior: Clip.hardEdge, - borderRadius: borderRadius, - child: MxcImage( - event: event, - width: 128, - height: 128, - fit: BoxFit.cover, - animated: true, - isThumbnail: true, - ), - ), + child: EventVideoPlayer(event), ); - }, - ).toList(), + } + return InkWell( + onTap: () => showDialog( + context: context, + builder: (_) => + ImageViewer(event, outerContext: context), + ), + borderRadius: borderRadius, + child: Material( + clipBehavior: Clip.hardEdge, + borderRadius: borderRadius, + child: MxcImage( + event: event, + width: 128, + height: 128, + fit: BoxFit.cover, + animated: true, + isThumbnail: true, + ), + ), + ); + }).toList(), ), ], ); diff --git a/lib/pages/chat_search/chat_search_message_tab.dart b/lib/pages/chat_search/chat_search_message_tab.dart index a56e4a5f6..8b1ca3166 100644 --- a/lib/pages/chat_search/chat_search_message_tab.dart +++ b/lib/pages/chat_search/chat_search_message_tab.dart @@ -14,10 +14,8 @@ class ChatSearchMessageTab extends StatelessWidget { final String searchQuery; final Room room; final Stream<(List, String?)>? searchStream; - final void Function({ - String? prevBatch, - List? previousSearchResult, - }) startSearch; + final void Function({String? prevBatch, List? previousSearchResult}) + startSearch; const ChatSearchMessageTab({ required this.searchQuery, @@ -36,15 +34,13 @@ class ChatSearchMessageTab extends StatelessWidget { final theme = Theme.of(context); if (searchStream == null) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ const Icon(Icons.search_outlined, size: 64), const SizedBox(height: 8), Text( L10n.of(context).searchIn( - room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ), + room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), ), ), ], @@ -55,19 +51,15 @@ class ChatSearchMessageTab extends StatelessWidget { return SelectionArea( child: ListView.separated( itemCount: events.length + 1, - separatorBuilder: (context, _) => Divider( - color: theme.dividerColor, - height: 1, - ), + separatorBuilder: (context, _) => + Divider(color: theme.dividerColor, height: 1), itemBuilder: (context, i) { if (i == events.length) { if (snapshot.connectionState != ConnectionState.done) { return const Padding( padding: EdgeInsets.all(16.0), child: Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ), ); } @@ -87,9 +79,7 @@ class ChatSearchMessageTab extends StatelessWidget { prevBatch: nextBatch, previousSearchResult: events, ), - icon: const Icon( - Icons.arrow_downward_outlined, - ), + icon: const Icon(Icons.arrow_downward_outlined), label: Text(L10n.of(context).searchMore), ), ), @@ -134,15 +124,9 @@ class _MessageSearchResultListTile extends StatelessWidget { return ListTile( title: Row( children: [ - Avatar( - mxContent: sender.avatarUrl, - name: displayname, - size: 16, - ), + Avatar(mxContent: sender.avatarUrl, name: displayname, size: 16), const SizedBox(width: 8), - Text( - displayname, - ), + Text(displayname), Expanded( child: Text( ' | ${event.originServerTs.localizedTimeShort(context)}', @@ -164,23 +148,16 @@ class _MessageSearchResultListTile extends StatelessWidget { .calcLocalizedBodyFallback( plaintextBody: true, removeMarkdown: true, - MatrixLocals( - L10n.of(context), - ), + MatrixLocals(L10n.of(context)), ) .trim(), maxLines: 7, overflow: TextOverflow.ellipsis, ), trailing: IconButton( - icon: const Icon( - Icons.chevron_right_outlined, - ), + icon: const Icon(Icons.chevron_right_outlined), onPressed: () => context.go( - '/${Uri( - pathSegments: ['rooms', room.id], - queryParameters: {'event': event.eventId}, - )}', + '/${Uri(pathSegments: ['rooms', room.id], queryParameters: {'event': event.eventId})}', ), ), ); diff --git a/lib/pages/chat_search/chat_search_view.dart b/lib/pages/chat_search/chat_search_view.dart index 8776582b4..fc55dc4cb 100644 --- a/lib/pages/chat_search/chat_search_view.dart +++ b/lib/pages/chat_search/chat_search_view.dart @@ -48,9 +48,7 @@ class ChatSearchView extends StatelessWidget { if (FluffyThemes.isThreeColumnMode(context)) const SizedBox(height: 16), Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(horizontal: 16), child: TextField( controller: controller.searchController, onSubmitted: (_) => controller.restartSearch(), diff --git a/lib/pages/device_settings/device_settings.dart b/lib/pages/device_settings/device_settings.dart index 2114e999c..12c1d1fce 100644 --- a/lib/pages/device_settings/device_settings.dart +++ b/lib/pages/device_settings/device_settings.dart @@ -59,10 +59,7 @@ class DevicesSettingsController extends State { .tryGetMap('org.matrix.msc2965.authentication') ?.tryGet('account'); if (accountManageUrl != null) { - launchUrlString( - accountManageUrl, - mode: LaunchMode.inAppBrowserView, - ); + launchUrlString(accountManageUrl, mode: LaunchMode.inAppBrowserView); return; } if (await showOkCancelAlertDialog( @@ -86,10 +83,7 @@ class DevicesSettingsController extends State { context: context, delay: false, future: () => matrix.client.uiaRequestBackground( - (auth) => matrix.client.deleteDevices( - deviceIds, - auth: auth, - ), + (auth) => matrix.client.deleteDevices(deviceIds, auth: auth), ), ); reload(); @@ -106,9 +100,9 @@ class DevicesSettingsController extends State { if (displayName == null) return; final success = await showFutureLoadingDialog( context: context, - future: () => Matrix.of(context) - .client - .updateDevice(device.deviceId, displayName: displayName), + future: () => Matrix.of( + context, + ).client.updateDevice(device.deviceId, displayName: displayName), ); if (success.error == null) { reload(); @@ -130,8 +124,10 @@ class DevicesSettingsController extends State { .deviceKeys[device.deviceId]! .startVerification(); req.onUpdate = () { - if ({KeyVerificationState.error, KeyVerificationState.done} - .contains(req.state)) { + if ({ + KeyVerificationState.error, + KeyVerificationState.done, + }.contains(req.state)) { setState(() {}); } }; @@ -162,9 +158,7 @@ class DevicesSettingsController extends State { bool _isOwnDevice(Device userDevice) => userDevice.deviceId == Matrix.of(context).client.deviceID; - Device? get thisDevice => devices!.firstWhereOrNull( - _isOwnDevice, - ); + Device? get thisDevice => devices!.firstWhereOrNull(_isOwnDevice); List get notThisDevice => List.from(devices!) ..removeWhere(_isOwnDevice) diff --git a/lib/pages/device_settings/device_settings_view.dart b/lib/pages/device_settings/device_settings_view.dart index 74e190397..232ae06c9 100644 --- a/lib/pages/device_settings/device_settings_view.dart +++ b/lib/pages/device_settings/device_settings_view.dart @@ -27,7 +27,7 @@ class DevicesSettingsView extends StatelessWidget { if (snapshot.hasError) { return Center( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.error_outlined), Text(snapshot.error.toString()), @@ -47,7 +47,7 @@ class DevicesSettingsView extends StatelessWidget { itemBuilder: (BuildContext context, int i) { if (i == 0) { return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (controller.chatBackupEnabled == false) Padding( @@ -57,8 +57,9 @@ class DevicesSettingsView extends StatelessWidget { child: Icon(Icons.info_outlined), ), subtitle: Text( - L10n.of(context) - .noticeChatBackupDeviceVerification, + L10n.of( + context, + ).noticeChatBackupDeviceVerification, ), ), ), diff --git a/lib/pages/device_settings/user_device_list_item.dart b/lib/pages/device_settings/user_device_list_item.dart index 02c915916..095a4335c 100644 --- a/lib/pages/device_settings/user_device_list_item.dart +++ b/lib/pages/device_settings/user_device_list_item.dart @@ -9,13 +9,7 @@ import '../../utils/date_time_extension.dart'; import '../../utils/matrix_sdk_extensions/device_extension.dart'; import '../../widgets/matrix.dart'; -enum UserDeviceListItemAction { - rename, - remove, - verify, - block, - unblock, -} +enum UserDeviceListItemAction { rename, remove, verify, block, unblock } class UserDeviceListItem extends StatelessWidget { final Device userDevice; @@ -38,7 +32,8 @@ class UserDeviceListItem extends StatelessWidget { @override Widget build(BuildContext context) { final client = Matrix.of(context).client; - final keys = client.userDeviceKeys[Matrix.of(context).client.userID] + final keys = client + .userDeviceKeys[Matrix.of(context).client.userID] ?.deviceKeys[userDevice.deviceId]; final isOwnDevice = userDevice.deviceId == client.deviceID; @@ -113,10 +108,10 @@ class UserDeviceListItem extends StatelessWidget { backgroundColor: keys == null ? Colors.grey[700] : keys.blocked - ? Colors.red - : keys.verified - ? Colors.green - : Colors.orange, + ? Colors.red + : keys.verified + ? Colors.green + : Colors.orange, child: Icon(userDevice.icon), ), title: Text( @@ -126,8 +121,9 @@ class UserDeviceListItem extends StatelessWidget { ), subtitle: Text( L10n.of(context).lastActiveAgo( - DateTime.fromMillisecondsSinceEpoch(userDevice.lastSeenTs ?? 0) - .localizedTimeShort(context), + DateTime.fromMillisecondsSinceEpoch( + userDevice.lastSeenTs ?? 0, + ).localizedTimeShort(context), ), style: const TextStyle(fontWeight: FontWeight.w300), ), @@ -137,14 +133,14 @@ class UserDeviceListItem extends StatelessWidget { keys.blocked ? L10n.of(context).blocked : keys.verified - ? L10n.of(context).verified - : L10n.of(context).unverified, + ? L10n.of(context).verified + : L10n.of(context).unverified, style: TextStyle( color: keys.blocked ? Colors.red : keys.verified - ? Colors.green - : Colors.orange, + ? Colors.green + : Colors.orange, ), ), ), diff --git a/lib/pages/dialer/dialer.dart b/lib/pages/dialer/dialer.dart index 8f314808b..d3cca97c1 100644 --- a/lib/pages/dialer/dialer.dart +++ b/lib/pages/dialer/dialer.dart @@ -70,9 +70,7 @@ class _StreamView extends StatelessWidget { @override Widget build(BuildContext context) { return Container( - decoration: const BoxDecoration( - color: Colors.black54, - ), + decoration: const BoxDecoration(color: Colors.black54), child: Stack( alignment: Alignment.center, children: [ @@ -133,9 +131,8 @@ class Calling extends StatefulWidget { class MyCallingPage extends State { Room? get room => call.room; - String get displayName => call.room.getLocalizedDisplayname( - MatrixLocals(L10n.of(widget.context)), - ); + String get displayName => + call.room.getLocalizedDisplayname(MatrixLocals(L10n.of(widget.context))); String get callId => widget.callId; @@ -219,10 +216,7 @@ class MyCallingPage extends State { } void cleanUp() { - Timer( - const Duration(seconds: 2), - () => widget.onClear?.call(), - ); + Timer(const Duration(seconds: 2), () => widget.onClear?.call()); if (call.type == CallType.kVideo) { try { unawaited(WakelockPlus.disable()); @@ -295,8 +289,9 @@ class MyCallingPage extends State { androidNotificationOptions: AndroidNotificationOptions( channelId: 'notification_channel_id', channelName: 'Foreground Notification', - channelDescription: - L10n.of(widget.context).foregroundServiceRunning, + channelDescription: L10n.of( + widget.context, + ).foregroundServiceRunning, ), iosNotificationOptions: const IOSNotificationOptions(), foregroundTaskOptions: ForegroundTaskOptions( @@ -434,9 +429,7 @@ class MyCallingPage extends State { hangupButton, ]; case CallState.kEnded: - return [ - hangupButton, - ]; + return [hangupButton]; case CallState.kFledgling: case CallState.kWaitLocalMedia: case CallState.kCreateOffer: @@ -458,28 +451,20 @@ class MyCallingPage extends State { if (call.localHold || call.remoteOnHold) { var title = ''; if (call.localHold) { - title = '${call.room.getLocalizedDisplayname( - MatrixLocals(L10n.of(widget.context)), - )} held the call.'; + title = + '${call.room.getLocalizedDisplayname(MatrixLocals(L10n.of(widget.context)))} held the call.'; } else if (call.remoteOnHold) { title = 'You held the call.'; } stackWidgets.add( Center( child: Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ - const Icon( - Icons.pause, - size: 48.0, - color: Colors.white, - ), + const Icon(Icons.pause, size: 48.0, color: Colors.white), Text( title, - style: const TextStyle( - color: Colors.white, - fontSize: 24.0, - ), + style: const TextStyle(color: Colors.white, fontSize: 24.0), ), ], ), @@ -488,7 +473,8 @@ class MyCallingPage extends State { return stackWidgets; } - var primaryStream = call.remoteScreenSharingStream ?? + var primaryStream = + call.remoteScreenSharingStream ?? call.localScreenSharingStream ?? call.remoteUserMediaStream ?? call.localUserMediaStream; @@ -527,8 +513,10 @@ class MyCallingPage extends State { SizedBox( width: _localVideoWidth, height: _localVideoHeight, - child: - _StreamView(remoteUserMediaStream!, matrixClient: widget.client), + child: _StreamView( + remoteUserMediaStream!, + matrixClient: widget.client, + ), ), ); secondaryStreamViews.add(const SizedBox(height: 10)); @@ -569,9 +557,7 @@ class MyCallingPage extends State { child: Container( width: _localVideoWidth, margin: _localVideoMargin, - child: Column( - children: secondaryStreamViews, - ), + child: Column(children: secondaryStreamViews), ), ), ); @@ -592,16 +578,14 @@ class MyCallingPage extends State { width: 320.0, height: 150.0, child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + mainAxisAlignment: .spaceAround, children: _buildActionButtons(isFloating), ), ), body: OrientationBuilder( builder: (BuildContext context, Orientation orientation) { return Container( - decoration: const BoxDecoration( - color: Colors.black87, - ), + decoration: const BoxDecoration(color: Colors.black87), child: Stack( children: [ ..._buildContent(orientation, isFloating), diff --git a/lib/pages/dialer/pip/pip_view.dart b/lib/pages/dialer/pip/pip_view.dart index d8ad23f4c..1cf1e5ecc 100644 --- a/lib/pages/dialer/pip/pip_view.dart +++ b/lib/pages/dialer/pip/pip_view.dart @@ -9,10 +9,7 @@ class PIPView extends StatefulWidget { final double? floatingHeight; final bool avoidKeyboard; - final Widget Function( - BuildContext context, - bool isFloating, - ) builder; + final Widget Function(BuildContext context, bool isFloating) builder; const PIPView({ super.key, @@ -95,10 +92,7 @@ class PIPViewState extends State with TickerProviderStateMixin { void _onPanUpdate(DragUpdateDetails details) { if (!_isDragging) return; setState(() { - _dragOffset = _dragOffset.translate( - details.delta.dx, - details.delta.dy, - ); + _dragOffset = _dragOffset.translate(details.delta.dx, details.delta.dy); }); } @@ -182,9 +176,7 @@ class PIPViewState extends State with TickerProviderStateMixin { _dragAnimationController, ]), builder: (context, child) { - final animationCurve = CurveTween( - curve: Curves.easeInOutQuad, - ); + final animationCurve = CurveTween(curve: Curves.easeInOutQuad); final dragAnimationValue = animationCurve.transform( _dragAnimationController.value, ); @@ -265,21 +257,13 @@ class PIPViewState extends State with TickerProviderStateMixin { } } -enum PIPViewCorner { - topLeft, - topRight, - bottomLeft, - bottomRight, -} +enum PIPViewCorner { topLeft, topRight, bottomLeft, bottomRight } class _CornerDistance { final PIPViewCorner corner; final double distance; - _CornerDistance({ - required this.corner, - required this.distance, - }); + _CornerDistance({required this.corner, required this.distance}); } PIPViewCorner _calculateNearestCorner({ @@ -288,15 +272,9 @@ PIPViewCorner _calculateNearestCorner({ }) { _CornerDistance calculateDistance(PIPViewCorner corner) { final distance = offsets[corner]! - .translate( - -offset.dx, - -offset.dy, - ) + .translate(-offset.dx, -offset.dy) .distanceSquared; - return _CornerDistance( - corner: corner, - distance: distance, - ); + return _CornerDistance(corner: corner, distance: distance); } final distances = PIPViewCorner.values.map(calculateDistance).toList(); diff --git a/lib/pages/homeserver_picker/homeserver_picker.dart b/lib/pages/homeserver_picker/homeserver_picker.dart index e57243851..7f3f6cfa6 100644 --- a/lib/pages/homeserver_picker/homeserver_picker.dart +++ b/lib/pages/homeserver_picker/homeserver_picker.dart @@ -42,8 +42,10 @@ class HomeserverPickerController extends State { /// well-known information and forwards to the login page depending on the /// login type. Future checkHomeserverAction({bool legacyPasswordLogin = false}) async { - final homeserverInput = - homeserverController.text.trim().toLowerCase().replaceAll(' ', '-'); + final homeserverInput = homeserverController.text + .trim() + .toLowerCase() + .replaceAll(' ', '-'); if (homeserverInput.isEmpty) { final client = await Matrix.of(context).getLoginClient(); @@ -113,14 +115,12 @@ class HomeserverPickerController extends State { void ssoLoginAction() async { final redirectUrl = kIsWeb - ? Uri.parse(html.window.location.href) - .resolveUri( - Uri(pathSegments: ['auth.html']), - ) - .toString() + ? Uri.parse( + html.window.location.href, + ).resolveUri(Uri(pathSegments: ['auth.html'])).toString() : isDefaultPlatform - ? '${AppConfig.appOpenUrlScheme.toLowerCase()}://login' - : 'http://localhost:3001//login'; + ? '${AppConfig.appOpenUrlScheme.toLowerCase()}://login' + : 'http://localhost:3001//login'; final client = await Matrix.of(context).getLoginClient(); final url = client.homeserver!.replace( path: '/_matrix/client/v3/login/sso/redirect', diff --git a/lib/pages/homeserver_picker/homeserver_picker_view.dart b/lib/pages/homeserver_picker/homeserver_picker_view.dart index c49ac1606..0a77592b3 100644 --- a/lib/pages/homeserver_picker/homeserver_picker_view.dart +++ b/lib/pages/homeserver_picker/homeserver_picker_view.dart @@ -15,18 +15,16 @@ import 'homeserver_picker.dart'; class HomeserverPickerView extends StatelessWidget { final HomeserverPickerController controller; - const HomeserverPickerView( - this.controller, { - super.key, - }); + const HomeserverPickerView(this.controller, {super.key}); @override Widget build(BuildContext context) { final theme = Theme.of(context); return LoginScaffold( - enforceMobileMode: - Matrix.of(context).widget.clients.any((client) => client.isLogged()), + enforceMobileMode: Matrix.of( + context, + ).widget.clients.any((client) => client.isLogged()), appBar: AppBar( centerTitle: true, title: Text( @@ -42,7 +40,7 @@ class HomeserverPickerView extends StatelessWidget { PopupMenuItem( value: MoreLoginActions.importBackup, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.import_export_outlined), const SizedBox(width: 12), @@ -53,7 +51,7 @@ class HomeserverPickerView extends StatelessWidget { PopupMenuItem( value: MoreLoginActions.privacy, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.privacy_tip_outlined), const SizedBox(width: 12), @@ -64,7 +62,7 @@ class HomeserverPickerView extends StatelessWidget { PopupMenuItem( value: MoreLoginActions.about, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const Icon(Icons.info_outlined), const SizedBox(width: 12), @@ -100,8 +98,9 @@ class HomeserverPickerView extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 32.0), child: SelectableLinkify( text: L10n.of(context).appIntroduction, - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), textAlign: TextAlign.center, linkStyle: TextStyle( color: theme.colorScheme.secondary, @@ -114,8 +113,8 @@ class HomeserverPickerView extends StatelessWidget { Padding( padding: const EdgeInsets.all(32.0), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: .min, + crossAxisAlignment: .stretch, children: [ TextField( onSubmitted: (_) => @@ -147,11 +146,13 @@ class HomeserverPickerView extends StatelessWidget { L10n.of(context).whatIsAHomeserver, ), content: Linkify( - text: L10n.of(context) - .homeserverDescription, + text: L10n.of( + context, + ).homeserverDescription, textScaleFactor: - MediaQuery.textScalerOf(context) - .scale(1), + MediaQuery.textScalerOf( + context, + ).scale(1), options: const LinkifyOptions( humanize: false, ), @@ -169,8 +170,9 @@ class HomeserverPickerView extends StatelessWidget { Uri.https('servers.joinmatrix.org'), ), child: Text( - L10n.of(context) - .discoverHomeservers, + L10n.of( + context, + ).discoverHomeservers, ), ), AdaptiveDialogAction( @@ -206,8 +208,8 @@ class HomeserverPickerView extends StatelessWidget { onPressed: controller.isLoading ? null : () => controller.checkHomeserverAction( - legacyPasswordLogin: true, - ), + legacyPasswordLogin: true, + ), child: Text(L10n.of(context).loginWithMatrixId), ), ], diff --git a/lib/pages/image_viewer/image_viewer.dart b/lib/pages/image_viewer/image_viewer.dart index 3ae3410a1..1dba46b28 100644 --- a/lib/pages/image_viewer/image_viewer.dart +++ b/lib/pages/image_viewer/image_viewer.dart @@ -32,7 +32,8 @@ class ImageViewerController extends State { @override void initState() { super.initState(); - allEvents = widget.timeline?.events + allEvents = + widget.timeline?.events .where( (event) => { MessageTypes.Image, @@ -44,8 +45,9 @@ class ImageViewerController extends State { .reversed .toList() ?? [widget.event]; - var index = - allEvents.indexWhere((event) => event.eventId == widget.event.eventId); + var index = allEvents.indexWhere( + (event) => event.eventId == widget.event.eventId, + ); if (index < 0) index = 0; pageController = PageController(initialPage: index); } @@ -93,11 +95,10 @@ class ImageViewerController extends State { /// Forward this image to another room. void forwardAction() => showScaffoldDialog( - context: context, - builder: (context) => ShareScaffoldDialog( - items: [ContentShareItem(currentEvent.content)], - ), - ); + context: context, + builder: (context) => + ShareScaffoldDialog(items: [ContentShareItem(currentEvent.content)]), + ); /// Save this file with a system call. void saveFileAction(BuildContext context) => currentEvent.saveFile(context); diff --git a/lib/pages/image_viewer/image_viewer_view.dart b/lib/pages/image_viewer/image_viewer_view.dart index f6cfa96f2..7eb529494 100644 --- a/lib/pages/image_viewer/image_viewer_view.dart +++ b/lib/pages/image_viewer/image_viewer_view.dart @@ -124,7 +124,7 @@ class ImageViewerView extends StatelessWidget { Align( alignment: Alignment.centerRight, child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (controller.canGoBack) Padding( diff --git a/lib/pages/image_viewer/video_player.dart b/lib/pages/image_viewer/video_player.dart index 3f3ac9e19..052bd6cff 100644 --- a/lib/pages/image_viewer/video_player.dart +++ b/lib/pages/image_viewer/video_player.dart @@ -19,10 +19,7 @@ import '../../widgets/mxc_image.dart'; class EventVideoPlayer extends StatefulWidget { final Event event; - const EventVideoPlayer( - this.event, { - super.key, - }); + const EventVideoPlayer(this.event, {super.key}); @override EventVideoPlayerState createState() => EventVideoPlayerState(); @@ -54,8 +51,9 @@ class EventVideoPlayerState extends State { : (progress) { final progressPercentage = progress / fileSize; setState(() { - _downloadProgress = - progressPercentage < 1 ? progressPercentage : null; + _downloadProgress = progressPercentage < 1 + ? progressPercentage + : null; }); }, ); @@ -100,11 +98,9 @@ class EventVideoPlayerState extends State { ); }); } on IOException catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(e.toLocalizedString(context)), - ), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } catch (e, s) { ErrorReporter(context, 'Unable to play video').onErrorCallback(e, s); } @@ -136,8 +132,10 @@ class EventVideoPlayerState extends State { @override Widget build(BuildContext context) { final hasThumbnail = widget.event.hasThumbnail; - final blurHash = (widget.event.infoMap as Map) - .tryGet('xyz.amorgan.blurhash') ?? + final blurHash = + (widget.event.infoMap as Map).tryGet( + 'xyz.amorgan.blurhash', + ) ?? fallbackBlurHash; final infoMap = widget.event.content.tryGetMap('info'); final videoWidth = infoMap?.tryGet('w') ?? 400; diff --git a/lib/pages/invitation_selection/invitation_selection.dart b/lib/pages/invitation_selection/invitation_selection.dart index 0c0d27fe5..1701a1a0f 100644 --- a/lib/pages/invitation_selection/invitation_selection.dart +++ b/lib/pages/invitation_selection/invitation_selection.dart @@ -12,10 +12,7 @@ import '../../utils/localized_exception_extension.dart'; class InvitationSelection extends StatefulWidget { final String roomId; - const InvitationSelection({ - super.key, - required this.roomId, - }); + const InvitationSelection({super.key, required this.roomId}); @override InvitationSelectionController createState() => @@ -47,8 +44,8 @@ class InvitationSelectionController extends State { .toList(); contacts.sort( (a, b) => a.calcDisplayname().toLowerCase().compareTo( - b.calcDisplayname().toLowerCase(), - ), + b.calcDisplayname().toLowerCase(), + ), ); return contacts; } @@ -91,9 +88,9 @@ class InvitationSelectionController extends State { try { response = await matrix.client.searchUserDirectory(text, limit: 10); } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text((e).toLocalizedString(context))), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text((e).toLocalizedString(context)))); return; } finally { setState(() => loading = false); diff --git a/lib/pages/invitation_selection/invitation_selection_view.dart b/lib/pages/invitation_selection/invitation_selection_view.dart index f4a84d5c8..4db33841f 100644 --- a/lib/pages/invitation_selection/invitation_selection_view.dart +++ b/lib/pages/invitation_selection/invitation_selection_view.dart @@ -16,13 +16,12 @@ class InvitationSelectionView extends StatelessWidget { @override Widget build(BuildContext context) { - final room = - Matrix.of(context).client.getRoomById(controller.widget.roomId); + final room = Matrix.of( + context, + ).client.getRoomById(controller.widget.roomId); if (room == null) { return Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).oopsSomethingWentWrong), - ), + appBar: AppBar(title: Text(L10n.of(context).oopsSomethingWentWrong)), body: Center( child: Text(L10n.of(context).youAreNoLongerParticipatingInThisChat), ), @@ -76,11 +75,14 @@ class InvitationSelectionView extends StatelessWidget { ), ), StreamBuilder( - stream: room.client.onRoomState.stream - .where((update) => update.roomId == room.id), + stream: room.client.onRoomState.stream.where( + (update) => update.roomId == room.id, + ), builder: (context, snapshot) { - final participants = - room.getParticipants().map((user) => user.id).toSet(); + final participants = room + .getParticipants() + .map((user) => user.id) + .toSet(); return controller.foundProfiles.isNotEmpty ? ListView.builder( physics: const NeverScrollableScrollPhysics(), @@ -88,17 +90,21 @@ class InvitationSelectionView extends StatelessWidget { itemCount: controller.foundProfiles.length, itemBuilder: (BuildContext context, int i) => _InviteContactListTile( - profile: controller.foundProfiles[i], - isMember: participants - .contains(controller.foundProfiles[i].userId), - onTap: () => controller.inviteAction( - context, - controller.foundProfiles[i].userId, - controller.foundProfiles[i].displayName ?? - controller.foundProfiles[i].userId.localpart ?? - L10n.of(context).user, - ), - ), + profile: controller.foundProfiles[i], + isMember: participants.contains( + controller.foundProfiles[i].userId, + ), + onTap: () => controller.inviteAction( + context, + controller.foundProfiles[i].userId, + controller.foundProfiles[i].displayName ?? + controller + .foundProfiles[i] + .userId + .localpart ?? + L10n.of(context).user, + ), + ), ) : FutureBuilder>( future: controller.getContacts(context), @@ -117,23 +123,26 @@ class InvitationSelectionView extends StatelessWidget { itemCount: contacts.length, itemBuilder: (BuildContext context, int i) => _InviteContactListTile( - user: contacts[i], - profile: Profile( - avatarUrl: contacts[i].avatarUrl, - displayName: contacts[i].displayName ?? - contacts[i].id.localpart ?? - L10n.of(context).user, - userId: contacts[i].id, - ), - isMember: participants.contains(contacts[i].id), - onTap: () => controller.inviteAction( - context, - contacts[i].id, - contacts[i].displayName ?? - contacts[i].id.localpart ?? - L10n.of(context).user, - ), - ), + user: contacts[i], + profile: Profile( + avatarUrl: contacts[i].avatarUrl, + displayName: + contacts[i].displayName ?? + contacts[i].id.localpart ?? + L10n.of(context).user, + userId: contacts[i].id, + ), + isMember: participants.contains( + contacts[i].id, + ), + onTap: () => controller.inviteAction( + context, + contacts[i].id, + contacts[i].displayName ?? + contacts[i].id.localpart ?? + L10n.of(context).user, + ), + ), ); }, ); @@ -169,10 +178,7 @@ class _InviteContactListTile extends StatelessWidget { mxContent: profile.avatarUrl, name: profile.displayName, presenceUserId: profile.userId, - onTap: () => UserDialog.show( - context: context, - profile: profile, - ), + onTap: () => UserDialog.show(context: context, profile: profile), ), title: Text( profile.displayName ?? profile.userId.localpart ?? l10n.user, @@ -183,9 +189,7 @@ class _InviteContactListTile extends StatelessWidget { profile.userId, maxLines: 1, overflow: TextOverflow.ellipsis, - style: TextStyle( - color: theme.colorScheme.secondary, - ), + style: TextStyle(color: theme.colorScheme.secondary), ), trailing: TextButton.icon( onPressed: isMember ? null : onTap, diff --git a/lib/pages/key_verification/key_verification_dialog.dart b/lib/pages/key_verification/key_verification_dialog.dart index 3562163c2..10121f9b9 100644 --- a/lib/pages/key_verification/key_verification_dialog.dart +++ b/lib/pages/key_verification/key_verification_dialog.dart @@ -15,17 +15,14 @@ import 'package:fluffychat/widgets/future_loading_dialog.dart'; class KeyVerificationDialog extends StatefulWidget { Future show(BuildContext context) => showAdaptiveDialog( - context: context, - builder: (context) => this, - barrierDismissible: false, - ); + context: context, + builder: (context) => this, + barrierDismissible: false, + ); final KeyVerification request; - const KeyVerificationDialog({ - super.key, - required this.request, - }); + const KeyVerificationDialog({super.key, required this.request}); @override KeyVerificationPageState createState() => KeyVerificationPageState(); @@ -57,8 +54,10 @@ class KeyVerificationPageState extends State { void dispose() { widget.request.onUpdate = originalOnUpdate; // don't want to get updates anymore - if (![KeyVerificationState.error, KeyVerificationState.done] - .contains(widget.request.state)) { + if (![ + KeyVerificationState.error, + KeyVerificationState.done, + ].contains(widget.request.state)) { widget.request.cancel('m.user'); } super.dispose(); @@ -98,8 +97,9 @@ class KeyVerificationPageState extends State { final theme = Theme.of(context); User? user; - final directChatId = - widget.request.client.getDirectChatFromUserId(widget.request.userId); + final directChatId = widget.request.client.getDirectChatFromUserId( + widget.request.userId, + ); if (directChatId != null) { user = widget.request.client .getRoomById(directChatId)! @@ -122,7 +122,7 @@ class KeyVerificationPageState extends State { body = Container( margin: const EdgeInsets.only(left: 8.0, right: 8.0), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Text( L10n.of(context).askSSSSSign, @@ -152,17 +152,13 @@ class KeyVerificationPageState extends State { ); buttons.add( AdaptiveDialogAction( - child: Text( - L10n.of(context).submit, - ), + child: Text(L10n.of(context).submit), onPressed: () => checkInput(textEditingController.text), ), ); buttons.add( AdaptiveDialogAction( - child: Text( - L10n.of(context).skip, - ), + child: Text(L10n.of(context).skip), onPressed: () => widget.request.openSSSS(skip: true), ), ); @@ -170,7 +166,7 @@ class KeyVerificationPageState extends State { case KeyVerificationState.askAccept: title = Text(L10n.of(context).newVerificationRequest); body = Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const SizedBox(height: 16), Avatar( @@ -179,16 +175,14 @@ class KeyVerificationPageState extends State { size: Avatar.defaultSize * 2, ), const SizedBox(height: 16), - Text( - L10n.of(context).askVerificationRequest(displayName), - ), + Text(L10n.of(context).askVerificationRequest(displayName)), ], ); buttons.add( AdaptiveDialogAction( onPressed: () => widget.request.rejectVerification().then( - (_) => Navigator.of(context, rootNavigator: false).pop(false), - ), + (_) => Navigator.of(context, rootNavigator: false).pop(false), + ), child: Text( L10n.of(context).reject, style: TextStyle(color: theme.colorScheme.error), @@ -211,10 +205,7 @@ class KeyVerificationPageState extends State { Stack( alignment: Alignment.center, children: [ - Avatar( - mxContent: user?.avatarUrl, - name: displayName, - ), + Avatar(mxContent: user?.avatarUrl, name: displayName), const SizedBox( width: Avatar.defaultSize + 2, height: Avatar.defaultSize + 2, @@ -258,16 +249,15 @@ class KeyVerificationPageState extends State { title = Text(L10n.of(context).compareNumbersMatch); final numbers = widget.request.sasNumbers; final numbstr = '${numbers[0]}-${numbers[1]}-${numbers[2]}'; - compareWidget = - TextSpan(text: numbstr, style: const TextStyle(fontSize: 40)); + compareWidget = TextSpan( + text: numbstr, + style: const TextStyle(fontSize: 40), + ); } body = Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ - Text.rich( - compareWidget, - textAlign: TextAlign.center, - ), + Text.rich(compareWidget, textAlign: TextAlign.center), ], ); buttons.add( @@ -291,15 +281,12 @@ class KeyVerificationPageState extends State { ? L10n.of(context).waitingPartnerEmoji : L10n.of(context).waitingPartnerNumbers; body = Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const SizedBox(height: 16), const CircularProgressIndicator.adaptive(strokeWidth: 2), const SizedBox(height: 16), - Text( - acceptText, - textAlign: TextAlign.center, - ), + Text(acceptText, textAlign: TextAlign.center), ], ); break; @@ -315,9 +302,7 @@ class KeyVerificationPageState extends State { ); buttons.add( AdaptiveDialogAction( - child: Text( - L10n.of(context).close, - ), + child: Text(L10n.of(context).close), onPressed: () => Navigator.of(context, rootNavigator: false).pop(true), ), @@ -326,7 +311,7 @@ class KeyVerificationPageState extends State { case KeyVerificationState.error: title = const Text(''); body = Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const SizedBox(height: 16), Icon(Icons.cancel, color: theme.colorScheme.error, size: 64.0), @@ -340,9 +325,7 @@ class KeyVerificationPageState extends State { ); buttons.add( AdaptiveDialogAction( - child: Text( - L10n.of(context).close, - ), + child: Text(L10n.of(context).close), onPressed: () => Navigator.of(context, rootNavigator: false).pop(false), ), @@ -355,9 +338,7 @@ class KeyVerificationPageState extends State { content: SizedBox( height: 256, width: 256, - child: ListView( - children: [body], - ), + child: ListView(children: [body]), ), actions: buttons, ); @@ -399,7 +380,7 @@ class _Emoji extends StatelessWidget { @override Widget build(BuildContext context) { return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Text(emoji.emoji, style: const TextStyle(fontSize: 50)), Padding( diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart index 8dee4ba38..c1620f913 100644 --- a/lib/pages/login/login.dart +++ b/lib/pages/login/login.dart @@ -130,8 +130,9 @@ class LoginController extends State { final dialogResult = await showOkCancelAlertDialog( context: context, useRootNavigator: false, - title: L10n.of(context) - .noMatrixServer(newDomain.toString(), oldHomeserver.toString()), + title: L10n.of( + context, + ).noMatrixServer(newDomain.toString(), oldHomeserver.toString()), okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, ); @@ -165,8 +166,9 @@ class LoginController extends State { message: L10n.of(context).enterAnEmailAddress, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - initialText: - usernameController.text.isEmail ? usernameController.text : '', + initialText: usernameController.text.isEmail + ? usernameController.text + : '', hintText: L10n.of(context).enterAnEmailAddress, keyboardType: TextInputType.emailAddress, ); @@ -238,8 +240,9 @@ class LoginController extends State { } extension on String { - static final RegExp _phoneRegex = - RegExp(r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$'); + static final RegExp _phoneRegex = RegExp( + r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$', + ); static final RegExp _emailRegex = RegExp(r'(.+)@(.+)\.(.+)'); bool get isEmail => _emailRegex.hasMatch(this); diff --git a/lib/pages/login/login_view.dart b/lib/pages/login/login_view.dart index a82b5054f..77f4530c1 100644 --- a/lib/pages/login/login_view.dart +++ b/lib/pages/login/login_view.dart @@ -21,8 +21,9 @@ class LoginView extends StatelessWidget { final titleParts = title.split(homeserver); return LoginScaffold( - enforceMobileMode: - Matrix.of(context).widget.clients.any((client) => client.isLogged()), + enforceMobileMode: Matrix.of( + context, + ).widget.clients.any((client) => client.isLogged()), appBar: AppBar( leading: controller.loading ? null : const Center(child: BackButton()), automaticallyImplyLeading: !controller.loading, @@ -62,8 +63,9 @@ class LoginView extends StatelessWidget { controller: controller.usernameController, textInputAction: TextInputAction.next, keyboardType: TextInputType.emailAddress, - autofillHints: - controller.loading ? null : [AutofillHints.username], + autofillHints: controller.loading + ? null + : [AutofillHints.username], decoration: InputDecoration( prefixIcon: const Icon(Icons.account_box_outlined), errorText: controller.usernameError, @@ -79,8 +81,9 @@ class LoginView extends StatelessWidget { child: TextField( readOnly: controller.loading, autocorrect: false, - autofillHints: - controller.loading ? null : [AutofillHints.password], + autofillHints: controller.loading + ? null + : [AutofillHints.password], controller: controller.passwordController, textInputAction: TextInputAction.go, obscureText: !controller.showPassword, diff --git a/lib/pages/new_group/new_group.dart b/lib/pages/new_group/new_group.dart index 84e4564ed..f34d0b43a 100644 --- a/lib/pages/new_group/new_group.dart +++ b/lib/pages/new_group/new_group.dart @@ -13,10 +13,7 @@ import 'package:fluffychat/widgets/matrix.dart'; class NewGroup extends StatefulWidget { final CreateGroupType createGroupType; - const NewGroup({ - this.createGroupType = CreateGroupType.group, - super.key, - }); + const NewGroup({this.createGroupType = CreateGroupType.group, super.key}); @override NewGroupController createState() => NewGroupController(); @@ -66,8 +63,9 @@ class NewGroupController extends State { Future _createGroup() async { if (!mounted) return; final roomId = await Matrix.of(context).client.createGroupChat( - visibility: - groupCanBeFound ? sdk.Visibility.public : sdk.Visibility.private, + visibility: groupCanBeFound + ? sdk.Visibility.public + : sdk.Visibility.private, preset: publicGroup ? sdk.CreateRoomPreset.publicChat : sdk.CreateRoomPreset.privateChat, @@ -87,24 +85,24 @@ class NewGroupController extends State { Future _createSpace() async { if (!mounted) return; final spaceId = await Matrix.of(context).client.createRoom( - preset: publicGroup - ? sdk.CreateRoomPreset.publicChat - : sdk.CreateRoomPreset.privateChat, - creationContent: {'type': RoomCreationTypes.mSpace}, - visibility: publicGroup ? sdk.Visibility.public : null, - roomAliasName: publicGroup - ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') - : null, - name: nameController.text.trim(), - powerLevelContentOverride: {'events_default': 100}, - initialState: [ - if (avatar != null) - sdk.StateEvent( - type: sdk.EventTypes.RoomAvatar, - content: {'url': avatarUrl.toString()}, - ), - ], - ); + preset: publicGroup + ? sdk.CreateRoomPreset.publicChat + : sdk.CreateRoomPreset.privateChat, + creationContent: {'type': RoomCreationTypes.mSpace}, + visibility: publicGroup ? sdk.Visibility.public : null, + roomAliasName: publicGroup + ? nameController.text.trim().toLowerCase().replaceAll(' ', '_') + : null, + name: nameController.text.trim(), + powerLevelContentOverride: {'events_default': 100}, + initialState: [ + if (avatar != null) + sdk.StateEvent( + type: sdk.EventTypes.RoomAvatar, + content: {'url': avatarUrl.toString()}, + ), + ], + ); if (!mounted) return; context.pop(spaceId); } diff --git a/lib/pages/new_group/new_group_view.dart b/lib/pages/new_group/new_group_view.dart index 82f572aca..61f86736b 100644 --- a/lib/pages/new_group/new_group_view.dart +++ b/lib/pages/new_group/new_group_view.dart @@ -33,7 +33,7 @@ class NewGroupView extends StatelessWidget { ), body: MaxWidthBody( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Padding( padding: const EdgeInsets.all(16.0), @@ -104,8 +104,9 @@ class NewGroupView extends StatelessWidget { curve: FluffyThemes.animationCurve, child: controller.publicGroup ? SwitchListTile.adaptive( - contentPadding: - const EdgeInsets.symmetric(horizontal: 32), + contentPadding: const EdgeInsets.symmetric( + horizontal: 32, + ), secondary: const Icon(Icons.search_outlined), title: Text(L10n.of(context).groupCanBeFoundViaSearch), value: controller.groupCanBeFound, @@ -121,17 +122,16 @@ class NewGroupView extends StatelessWidget { child: controller.createGroupType == CreateGroupType.space ? const SizedBox.shrink() : SwitchListTile.adaptive( - contentPadding: - const EdgeInsets.symmetric(horizontal: 32), + contentPadding: const EdgeInsets.symmetric( + horizontal: 32, + ), secondary: Icon( Icons.lock_outlined, color: theme.colorScheme.onSurface, ), title: Text( L10n.of(context).enableEncryption, - style: TextStyle( - color: theme.colorScheme.onSurface, - ), + style: TextStyle(color: theme.colorScheme.onSurface), ), value: !controller.publicGroup, onChanged: null, @@ -142,8 +142,9 @@ class NewGroupView extends StatelessWidget { curve: FluffyThemes.animationCurve, child: controller.createGroupType == CreateGroupType.space ? ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 32), + contentPadding: const EdgeInsets.symmetric( + horizontal: 32, + ), trailing: const Padding( padding: EdgeInsets.symmetric(horizontal: 16.0), child: Icon(Icons.info_outlined), @@ -157,8 +158,9 @@ class NewGroupView extends StatelessWidget { child: SizedBox( width: double.infinity, child: ElevatedButton( - onPressed: - controller.loading ? null : controller.submitAction, + onPressed: controller.loading + ? null + : controller.submitAction, child: controller.loading ? const LinearProgressIndicator() : Text( @@ -181,9 +183,7 @@ class NewGroupView extends StatelessWidget { ), title: Text( error.toLocalizedString(context), - style: TextStyle( - color: theme.colorScheme.error, - ), + style: TextStyle(color: theme.colorScheme.error), ), ), ), diff --git a/lib/pages/new_private_chat/new_private_chat.dart b/lib/pages/new_private_chat/new_private_chat.dart index 543031c9f..982290c4b 100644 --- a/lib/pages/new_private_chat/new_private_chat.dart +++ b/lib/pages/new_private_chat/new_private_chat.dart @@ -52,8 +52,9 @@ class NewPrivateChatController extends State { } Future> _searchUser(String searchTerm) async { - final result = - await Matrix.of(context).client.searchUserDirectory(searchTerm); + final result = await Matrix.of( + context, + ).client.searchUserDirectory(searchTerm); final profiles = result.results; if (searchTerm.isValidMatrixId && @@ -73,9 +74,7 @@ class NewPrivateChatController extends State { if (info.version.sdkInt < 21) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text( - L10n.of(context).unsupportedAndroidVersionLong, - ), + content: Text(L10n.of(context).unsupportedAndroidVersionLong), ), ); return; @@ -93,15 +92,13 @@ class NewPrivateChatController extends State { await Clipboard.setData( ClipboardData(text: Matrix.of(context).client.userID!), ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context).copiedToClipboard)), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(L10n.of(context).copiedToClipboard))); } - void openUserModal(Profile profile) => UserDialog.show( - context: context, - profile: profile, - ); + void openUserModal(Profile profile) => + UserDialog.show(context: context, profile: profile); @override Widget build(BuildContext context) => NewPrivateChatView(this); diff --git a/lib/pages/new_private_chat/new_private_chat_view.dart b/lib/pages/new_private_chat/new_private_chat_view.dart index 5a5bdeee0..d72ba4c28 100644 --- a/lib/pages/new_private_chat/new_private_chat_view.dart +++ b/lib/pages/new_private_chat/new_private_chat_view.dart @@ -35,8 +35,10 @@ class NewPrivateChatView extends StatelessWidget { backgroundColor: theme.scaffoldBackgroundColor, actions: [ TextButton( - onPressed: - UrlLauncher(context, AppConfig.startChatTutorial).launchUrl, + onPressed: UrlLauncher( + context, + AppConfig.startChatTutorial, + ).launchUrl, child: Text(L10n.of(context).help), ), ], @@ -105,8 +107,9 @@ class NewPrivateChatView extends StatelessWidget { ? ListView( children: [ Padding( - padding: - const EdgeInsets.symmetric(horizontal: 18.0), + padding: const EdgeInsets.symmetric( + horizontal: 18.0, + ), child: SelectableText.rich( TextSpan( children: [ @@ -157,8 +160,9 @@ class NewPrivateChatView extends StatelessWidget { theme.colorScheme.primaryContainer, foregroundColor: theme.colorScheme.onPrimaryContainer, - child: - const Icon(Icons.qr_code_scanner_outlined), + child: const Icon( + Icons.qr_code_scanner_outlined, + ), ), title: Text(L10n.of(context).scanQrCode), onTap: controller.openScannerAction, @@ -185,15 +189,14 @@ class NewPrivateChatView extends StatelessWidget { borderRadius: BorderRadius.circular( AppConfig.borderRadius, ), - onTap: () => showQrCodeViewer( - context, - userId, - ), + onTap: () => + showQrCodeViewer(context, userId), child: Padding( padding: const EdgeInsets.all(16.0), child: ConstrainedBox( - constraints: - const BoxConstraints(maxWidth: 200), + constraints: const BoxConstraints( + maxWidth: 200, + ), child: PrettyQrView.data( data: 'https://matrix.to/#/$userId', decoration: PrettyQrDecoration( @@ -218,7 +221,7 @@ class NewPrivateChatView extends StatelessWidget { final error = snapshot.error; if (error != null) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ Text( error.toLocalizedString(context), @@ -243,7 +246,7 @@ class NewPrivateChatView extends StatelessWidget { } if (result.isEmpty) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ const Icon(Icons.search_outlined, size: 86), Padding( @@ -265,7 +268,8 @@ class NewPrivateChatView extends StatelessWidget { itemCount: result.length, itemBuilder: (context, i) { final contact = result[i]; - final displayname = contact.displayName ?? + final displayname = + contact.displayName ?? contact.userId.localpart ?? contact.userId; return ListTile( diff --git a/lib/pages/settings/settings.dart b/lib/pages/settings/settings.dart index 9e808585f..7bf4b57a2 100644 --- a/lib/pages/settings/settings.dart +++ b/lib/pages/settings/settings.dart @@ -29,9 +29,9 @@ class SettingsController extends State { bool profileUpdated = false; void updateProfile() => setState(() { - profileUpdated = true; - profileFuture = null; - }); + profileUpdated = true; + profileFuture = null; + }); void setDisplaynameAction() async { final profile = await profileFuture; @@ -132,15 +132,9 @@ class SettingsController extends State { imageQuality: 50, ); if (result == null) return; - file = MatrixFile( - bytes: await result.readAsBytes(), - name: result.path, - ); + file = MatrixFile(bytes: await result.readAsBytes(), name: result.path); } else { - final result = await selectFiles( - context, - type: FileSelectorType.images, - ); + final result = await selectFiles(context, type: FileSelectorType.images); final pickedFile = result.firstOrNull; if (pickedFile == null) return; file = MatrixFile( @@ -176,8 +170,8 @@ class SettingsController extends State { await client.encryption?.crossSigning.isCached() ?? false; final needsBootstrap = await client.encryption?.keyManager.isCached() == false || - client.encryption?.crossSigning.enabled == false || - crossSigning == false; + client.encryption?.crossSigning.enabled == false || + crossSigning == false; final isUnknownSession = client.isUnknownSession; setState(() { showChatBackupBanner = needsBootstrap || isUnknownSession; @@ -204,9 +198,7 @@ class SettingsController extends State { @override Widget build(BuildContext context) { final client = Matrix.of(context).client; - profileFuture ??= client.getProfileFromUserId( - client.userID!, - ); + profileFuture ??= client.getProfileFromUserId(client.userID!); return SettingsView(this); } } diff --git a/lib/pages/settings/settings_view.dart b/lib/pages/settings/settings_view.dart index a92ee6a84..12d70db59 100644 --- a/lib/pages/settings/settings_view.dart +++ b/lib/pages/settings/settings_view.dart @@ -25,8 +25,9 @@ class SettingsView extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final showChatBackupBanner = controller.showChatBackupBanner; - final activeRoute = - GoRouter.of(context).routeInformationProvider.value.uri.path; + final activeRoute = GoRouter.of( + context, + ).routeInformationProvider.value.uri.path; final accountManageUrl = Matrix.of(context) .client .wellKnown @@ -41,10 +42,7 @@ class SettingsView extends StatelessWidget { onGoToChats: () => context.go('/rooms'), onGoToSpaceId: (spaceId) => context.go('/rooms?spaceId=$spaceId'), ), - Container( - color: Theme.of(context).dividerColor, - width: 1, - ), + Container(color: Theme.of(context).dividerColor, width: 1), ], Expanded( child: Scaffold( @@ -53,9 +51,7 @@ class SettingsView extends StatelessWidget { : AppBar( title: Text(L10n.of(context).settings), leading: Center( - child: BackButton( - onPressed: () => context.go('/rooms'), - ), + child: BackButton(onPressed: () => context.go('/rooms')), ), ), body: ListTileTheme( @@ -68,7 +64,8 @@ class SettingsView extends StatelessWidget { builder: (context, snapshot) { final profile = snapshot.data; final avatar = profile?.avatarUrl; - final mxid = Matrix.of(context).client.userID ?? + final mxid = + Matrix.of(context).client.userID ?? L10n.of(context).user; final displayname = profile?.displayName ?? mxid.localpart ?? mxid; @@ -84,10 +81,10 @@ class SettingsView extends StatelessWidget { size: Avatar.defaultSize * 2.5, onTap: avatar != null ? () => showDialog( - context: context, - builder: (_) => - MxcImageViewer(avatar), - ) + context: context, + builder: (_) => + MxcImageViewer(avatar), + ) : null, ), if (profile != null) @@ -108,8 +105,8 @@ class SettingsView extends StatelessWidget { ), Expanded( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: .center, + crossAxisAlignment: .start, children: [ TextButton.icon( onPressed: controller.setDisplaynameAction, @@ -126,9 +123,7 @@ class SettingsView extends StatelessWidget { displayname, maxLines: 1, overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 18, - ), + style: const TextStyle(fontSize: 18), ), ), TextButton.icon( @@ -182,9 +177,7 @@ class SettingsView extends StatelessWidget { title: Text(L10n.of(context).chatBackup), onChanged: controller.firstRunBootstrapAction, ), - Divider( - color: theme.dividerColor, - ), + Divider(color: theme.dividerColor), ListTile( leading: const Icon(Icons.format_paint_outlined), title: Text(L10n.of(context).changeTheme), @@ -198,8 +191,8 @@ class SettingsView extends StatelessWidget { title: Text(L10n.of(context).notifications), tileColor: activeRoute.startsWith('/rooms/settings/notifications') - ? theme.colorScheme.surfaceContainerHigh - : null, + ? theme.colorScheme.surfaceContainerHigh + : null, onTap: () => context.go('/rooms/settings/notifications'), ), ListTile( @@ -224,8 +217,8 @@ class SettingsView extends StatelessWidget { onTap: () => context.go('/rooms/settings/security'), tileColor: activeRoute.startsWith('/rooms/settings/security') - ? theme.colorScheme.surfaceContainerHigh - : null, + ? theme.colorScheme.surfaceContainerHigh + : null, ), Divider(color: theme.dividerColor), ListTile( @@ -239,8 +232,8 @@ class SettingsView extends StatelessWidget { onTap: () => context.go('/rooms/settings/homeserver'), tileColor: activeRoute.startsWith('/rooms/settings/homeserver') - ? theme.colorScheme.surfaceContainerHigh - : null, + ? theme.colorScheme.surfaceContainerHigh + : null, ), ListTile( leading: const Icon(Icons.privacy_tip_outlined), diff --git a/lib/pages/settings_3pid/settings_3pid.dart b/lib/pages/settings_3pid/settings_3pid.dart index 264cb9331..f35c5c1fc 100644 --- a/lib/pages/settings_3pid/settings_3pid.dart +++ b/lib/pages/settings_3pid/settings_3pid.dart @@ -34,10 +34,10 @@ class Settings3PidController extends State { final response = await showFutureLoadingDialog( context: context, future: () => Matrix.of(context).client.requestTokenToRegisterEmail( - clientSecret, - input, - Settings3Pid.sendAttempt++, - ), + clientSecret, + input, + Settings3Pid.sendAttempt++, + ), ); if (response.error != null) return; final ok = await showOkAlertDialog( @@ -52,12 +52,10 @@ class Settings3PidController extends State { context: context, delay: false, future: () => Matrix.of(context).client.uiaRequestBackground( - (auth) => Matrix.of(context).client.add3PID( - clientSecret, - response.result!.sid, - auth: auth, - ), - ), + (auth) => Matrix.of( + context, + ).client.add3PID(clientSecret, response.result!.sid, auth: auth), + ), ); if (success.error != null) return; setState(() => request = null); @@ -78,10 +76,9 @@ class Settings3PidController extends State { } final success = await showFutureLoadingDialog( context: context, - future: () => Matrix.of(context).client.delete3pidFromAccount( - identifier.address, - identifier.medium, - ), + future: () => Matrix.of( + context, + ).client.delete3pidFromAccount(identifier.address, identifier.medium), ); if (success.error != null) return; setState(() => request = null); diff --git a/lib/pages/settings_3pid/settings_3pid_view.dart b/lib/pages/settings_3pid/settings_3pid_view.dart index c466b0a24..d01fdc6bf 100644 --- a/lib/pages/settings_3pid/settings_3pid_view.dart +++ b/lib/pages/settings_3pid/settings_3pid_view.dart @@ -33,67 +33,71 @@ class Settings3PidView extends StatelessWidget { withScrolling: false, child: FutureBuilder?>( future: controller.request, - builder: ( - BuildContext context, - AsyncSnapshot?> snapshot, - ) { - if (snapshot.hasError) { - return Center( - child: Text( - snapshot.error.toString(), - textAlign: TextAlign.center, - ), - ); - } - if (!snapshot.hasData) { - return const Center( - child: CircularProgressIndicator.adaptive(strokeWidth: 2), - ); - } - final identifier = snapshot.data!; - return Column( - children: [ - ListTile( - leading: CircleAvatar( - backgroundColor: theme.scaffoldBackgroundColor, - foregroundColor: - identifier.isEmpty ? Colors.orange : Colors.grey, - child: Icon( - identifier.isEmpty - ? Icons.warning_outlined - : Icons.info_outlined, + builder: + ( + BuildContext context, + AsyncSnapshot?> snapshot, + ) { + if (snapshot.hasError) { + return Center( + child: Text( + snapshot.error.toString(), + textAlign: TextAlign.center, ), - ), - title: Text( - identifier.isEmpty - ? L10n.of(context).noPasswordRecoveryDescription - : L10n.of(context) - .withTheseAddressesRecoveryDescription, - ), - ), - const Divider(), - Expanded( - child: ListView.builder( - itemCount: identifier.length, - itemBuilder: (BuildContext context, int i) => ListTile( + ); + } + if (!snapshot.hasData) { + return const Center( + child: CircularProgressIndicator.adaptive(strokeWidth: 2), + ); + } + final identifier = snapshot.data!; + return Column( + children: [ + ListTile( leading: CircleAvatar( backgroundColor: theme.scaffoldBackgroundColor, - foregroundColor: Colors.grey, - child: Icon(identifier[i].iconData), + foregroundColor: identifier.isEmpty + ? Colors.orange + : Colors.grey, + child: Icon( + identifier.isEmpty + ? Icons.warning_outlined + : Icons.info_outlined, + ), ), - title: Text(identifier[i].address), - trailing: IconButton( - tooltip: L10n.of(context).delete, - icon: const Icon(Icons.delete_forever_outlined), - color: Colors.red, - onPressed: () => controller.delete3Pid(identifier[i]), + title: Text( + identifier.isEmpty + ? L10n.of(context).noPasswordRecoveryDescription + : L10n.of( + context, + ).withTheseAddressesRecoveryDescription, ), ), - ), - ), - ], - ); - }, + const Divider(), + Expanded( + child: ListView.builder( + itemCount: identifier.length, + itemBuilder: (BuildContext context, int i) => ListTile( + leading: CircleAvatar( + backgroundColor: theme.scaffoldBackgroundColor, + foregroundColor: Colors.grey, + child: Icon(identifier[i].iconData), + ), + title: Text(identifier[i].address), + trailing: IconButton( + tooltip: L10n.of(context).delete, + icon: const Icon(Icons.delete_forever_outlined), + color: Colors.red, + onPressed: () => + controller.delete3Pid(identifier[i]), + ), + ), + ), + ), + ], + ); + }, ), ), ); diff --git a/lib/pages/settings_emotes/import_archive_dialog.dart b/lib/pages/settings_emotes/import_archive_dialog.dart index 12bc0a09c..46bca4d3a 100644 --- a/lib/pages/settings_emotes/import_archive_dialog.dart +++ b/lib/pages/settings_emotes/import_archive_dialog.dart @@ -46,11 +46,7 @@ class _ImportEmoteArchiveDialogState extends State { return AlertDialog( title: Text(L10n.of(context).importEmojis), content: _loading - ? Center( - child: CircularProgressIndicator( - value: _progress, - ), - ) + ? Center(child: CircularProgressIndicator(value: _progress)) : SingleChildScrollView( child: Wrap( alignment: WrapAlignment.spaceEvenly, @@ -79,8 +75,8 @@ class _ImportEmoteArchiveDialogState extends State { onPressed: _loading ? null : _importMap.isNotEmpty - ? _addEmotePack - : null, + ? _addEmotePack + : null, child: Text(L10n.of(context).importNow), ), ], @@ -91,12 +87,8 @@ class _ImportEmoteArchiveDialogState extends State { _importMap = Map.fromEntries( widget.archive.files .where((e) => e.isFile) - .map( - (e) => MapEntry(e, e.name.emoteNameFromPath), - ) - .sorted( - (a, b) => a.value.compareTo(b.value), - ), + .map((e) => MapEntry(e, e.name.emoteNameFromPath)) + .sorted((a, b) => a.value.compareTo(b.value)), ); } @@ -148,10 +140,7 @@ class _ImportEmoteArchiveDialogState extends State { final imageCode = entry.value; try { - var mxcFile = MatrixImageFile( - bytes: file.content, - name: file.name, - ); + var mxcFile = MatrixImageFile(bytes: file.content, name: file.name); final thumbnail = (await mxcFile.generateThumbnail( nativeImplementations: ClientManager.nativeImplementations, @@ -162,14 +151,12 @@ class _ImportEmoteArchiveDialogState extends State { mxcFile = thumbnail; } final uri = await Matrix.of(context).client.uploadContent( - mxcFile.bytes, - filename: mxcFile.name, - contentType: mxcFile.mimeType, - ); + mxcFile.bytes, + filename: mxcFile.name, + contentType: mxcFile.mimeType, + ); - final info = { - ...mxcFile.info, - }; + final info = {...mxcFile.info}; // normalize width / height to 256, required for stickers if (info['w'] is int && info['h'] is int) { @@ -184,9 +171,9 @@ class _ImportEmoteArchiveDialogState extends State { } widget.controller.pack!.images[imageCode] = ImagePackImageContent.fromJson({ - 'url': uri.toString(), - 'info': info, - }); + 'url': uri.toString(), + 'info': info, + }); successfulUploads.add(file.name); } catch (e) { Logs().d('Could not upload emote $imageCode'); @@ -204,8 +191,9 @@ class _ImportEmoteArchiveDialogState extends State { // in case we have unhandled / duplicated emotes left, don't pop if (mounted) setState(() {}); if (_importMap.isEmpty) { - WidgetsBinding.instance - .addPostFrameCallback((_) => Navigator.of(context).pop()); + WidgetsBinding.instance.addPostFrameCallback( + (_) => Navigator.of(context).pop(), + ); } } } @@ -250,21 +238,20 @@ class _EmojiImportPreviewState extends State<_EmojiImportPreview> { if (hasError) return _ImageFileError(name: widget.entry.key.name); return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: .min, + mainAxisAlignment: .center, + crossAxisAlignment: .center, children: [ Image.memory( widget.entry.key.content, height: 64, width: 64, errorBuilder: (context, e, s) { - WidgetsBinding.instance - .addPostFrameCallback((_) => _setRenderError()); - - return _ImageFileError( - name: widget.entry.key.name, + WidgetsBinding.instance.addPostFrameCallback( + (_) => _setRenderError(), ); + + return _ImageFileError(name: widget.entry.key.name); }, ), SizedBox( @@ -323,9 +310,9 @@ class _ImageFileError extends StatelessWidget { child: Tooltip( message: name, child: Column( - mainAxisAlignment: MainAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: .start, + mainAxisSize: .min, + crossAxisAlignment: .center, children: [ const Icon(Icons.error), Text( @@ -347,8 +334,7 @@ extension on String { /// Used to compute emote name proposal based on file name String get emoteNameFromPath { // ... removing leading path - return split(RegExp(r'[/\\]')) - .last + return split(RegExp(r'[/\\]')).last // ... removing file extension .split('.') .first diff --git a/lib/pages/settings_emotes/settings_emotes.dart b/lib/pages/settings_emotes/settings_emotes.dart index b1de7f161..023165764 100644 --- a/lib/pages/settings_emotes/settings_emotes.dart +++ b/lib/pages/settings_emotes/settings_emotes.dart @@ -55,10 +55,7 @@ class EmotesSettingsController extends State { final event = key == null ? null - : room?.getState( - 'im.ponies.room_emotes', - key, - ); + : room?.getState('im.ponies.room_emotes', key); final eventPack = event?.content.tryGetMap('pack'); packDisplayNameController.text = eventPack?.tryGet('display_name') ?? ''; @@ -71,13 +68,11 @@ class EmotesSettingsController extends State { ImagePackContent _getPack() { final client = Matrix.of(context).client; - final event = (room != null + final event = + (room != null ? room!.getState('im.ponies.room_emotes', stateKey ?? '') : client.accountData['im.ponies.user_emotes']) ?? - BasicEvent( - type: 'm.dummy', - content: {}, - ); + BasicEvent(type: 'm.dummy', content: {}); // make sure we work on a *copy* of the event return BasicEvent.fromJson(event.toJson()).parsedImagePackContent; } @@ -124,7 +119,8 @@ class EmotesSettingsController extends State { return; } final client = Matrix.of(context).client; - final content = client.accountData['im.ponies.emote_rooms']?.content ?? + final content = + client.accountData['im.ponies.emote_rooms']?.content ?? {}; if (active) { if (content['rooms'] is! Map) { @@ -158,14 +154,15 @@ class EmotesSettingsController extends State { TextEditingController(); void removeImageAction(String oldImageCode) => setState(() { - pack!.images.remove(oldImageCode); - showSave = true; - }); + pack!.images.remove(oldImageCode); + showSave = true; + }); void toggleUsage(String imageCode, ImagePackUsage usage) { setState(() { - final usages = - pack!.images[imageCode]!.usage ??= List.from(ImagePackUsage.values); + final usages = pack!.images[imageCode]!.usage ??= List.from( + ImagePackUsage.values, + ); if (!usages.remove(usage)) usages.add(usage); showSave = true; }); @@ -265,9 +262,7 @@ class EmotesSettingsController extends State { if (packKeys?.contains(name) ?? false) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(L10n.of(context).stickerPackNameAlreadyExists), - ), + SnackBar(content: Text(L10n.of(context).stickerPackNameAlreadyExists)), ); return; } @@ -316,20 +311,19 @@ class EmotesSettingsController extends State { bytes: await pickedFile.readAsBytes(), name: pickedFile.name, ); - file = await file.generateThumbnail( + file = + await file.generateThumbnail( nativeImplementations: ClientManager.nativeImplementations, ) ?? file; final uri = await Matrix.of(context).client.uploadContent( - file.bytes, - filename: file.name, - contentType: file.mimeType, - ); + file.bytes, + filename: file.name, + contentType: file.mimeType, + ); setState(() { - final info = { - ...file.info, - }; + final info = {...file.info}; // normalize width / height to 256, required for stickers if (info['w'] is int && info['h'] is int) { final ratio = info['w'] / info['h']; @@ -342,11 +336,9 @@ class EmotesSettingsController extends State { } } final imageCode = pickedFile.name.split('.').first; - pack!.images[imageCode] = - ImagePackImageContent.fromJson({ - 'url': uri.toString(), - 'info': info, - }); + pack!.images[imageCode] = ImagePackImageContent.fromJson( + {'url': uri.toString(), 'info': info}, + ); }); } }, @@ -363,10 +355,7 @@ class EmotesSettingsController extends State { } Future importEmojiZip() async { - final result = await selectFiles( - context, - type: FileSelectorType.zip, - ); + final result = await selectFiles(context, type: FileSelectorType.zip); if (result.isEmpty) return; @@ -378,10 +367,8 @@ class EmotesSettingsController extends State { context: context, // breaks [Matrix.of] calls otherwise useRootNavigator: false, - builder: (context) => ImportEmoteArchiveDialog( - controller: this, - archive: archive, - ), + builder: (context) => + ImportEmoteArchiveDialog(controller: this, archive: archive), ); setState(() {}); } @@ -404,11 +391,7 @@ class EmotesSettingsController extends State { ); archive.addFile( - ArchiveFile( - name, - response.bodyBytes.length, - response.bodyBytes, - ), + ArchiveFile(name, response.bodyBytes.length, response.bodyBytes), ); } final fileName = diff --git a/lib/pages/settings_emotes/settings_emotes_view.dart b/lib/pages/settings_emotes/settings_emotes_view.dart index 92a8b25c4..a5baf3979 100644 --- a/lib/pages/settings_emotes/settings_emotes_view.dart +++ b/lib/pages/settings_emotes/settings_emotes_view.dart @@ -23,9 +23,7 @@ class EmotesSettingsView extends StatelessWidget { Widget build(BuildContext context) { if (controller.widget.roomId != null && controller.room == null) { return Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).oopsSomethingWentWrong), - ), + appBar: AppBar(title: Text(L10n.of(context).oopsSomethingWentWrong)), body: Center( child: Text(L10n.of(context).youAreNoLongerParticipatingInThisChat), ), @@ -110,10 +108,7 @@ class EmotesSettingsView extends StatelessWidget { horizontal: 4.0, ), child: FilterChip( - label: const Icon( - Icons.add_outlined, - size: 20, - ), + label: const Icon(Icons.add_outlined, size: 20), onSelected: controller.showSave ? null : (_) => controller.createImagePack(), @@ -122,23 +117,24 @@ class EmotesSettingsView extends StatelessWidget { } i--; final key = packKeys[i]; - final event = controller.room - ?.getState('im.ponies.room_emotes', packKeys[i]); + final event = controller.room?.getState( + 'im.ponies.room_emotes', + packKeys[i], + ); - final eventPack = - event?.content.tryGetMap('pack'); + final eventPack = event?.content + .tryGetMap('pack'); final packName = eventPack?.tryGet('display_name') ?? - eventPack?.tryGet('name') ?? - (key.isNotEmpty ? key : 'Default'); + eventPack?.tryGet('name') ?? + (key.isNotEmpty ? key : 'Default'); return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 4.0, - ), + padding: const EdgeInsets.symmetric(horizontal: 4.0), child: FilterChip( label: Text(packName), - selected: controller.stateKey == key || + selected: + controller.stateKey == key || (controller.stateKey == null && key.isEmpty), onSelected: controller.showSave ? null @@ -153,8 +149,8 @@ class EmotesSettingsView extends StatelessWidget { ), body: MaxWidthBody( child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: .min, + crossAxisAlignment: .stretch, children: [ if (controller.room != null) ...[ const SizedBox(height: 16), @@ -188,9 +184,10 @@ class EmotesSettingsView extends StatelessWidget { ? null : IconButton( icon: const Icon(Icons.link_outlined), - onPressed: () => - UrlLauncher(context, attributionUrl.toString()) - .launchUrl(), + onPressed: () => UrlLauncher( + context, + attributionUrl.toString(), + ).launchUrl(), ), ), ), @@ -283,25 +280,23 @@ class EmotesSettingsView extends StatelessWidget { ), onSubmitted: (s) => controller.submitImageAction( - imageCode, - image, - textEditingController, - ), + imageCode, + image, + textEditingController, + ), ), ), ), ), if (!controller.readonly) PopupMenuButton( - onSelected: (usage) => controller.toggleUsage( - imageCode, - usage, - ), + onSelected: (usage) => + controller.toggleUsage(imageCode, usage), itemBuilder: (context) => [ PopupMenuItem( value: ImagePackUsage.sticker, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (image.usage?.contains( ImagePackUsage.sticker, @@ -316,7 +311,7 @@ class EmotesSettingsView extends StatelessWidget { PopupMenuItem( value: ImagePackUsage.emoticon, child: Row( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (image.usage?.contains( ImagePackUsage.emoticon, @@ -363,10 +358,8 @@ class _EmoteImage extends StatelessWidget { final key = 'sticker_preview_$mxc'; return InkWell( borderRadius: BorderRadius.circular(4), - onTap: () => showDialog( - context: context, - builder: (_) => MxcImageViewer(mxc), - ), + onTap: () => + showDialog(context: context, builder: (_) => MxcImageViewer(mxc)), child: MxcImage( key: ValueKey(key), cacheKey: key, diff --git a/lib/pages/settings_homeserver/settings_homeserver.dart b/lib/pages/settings_homeserver/settings_homeserver.dart index 76ca08232..13843336d 100644 --- a/lib/pages/settings_homeserver/settings_homeserver.dart +++ b/lib/pages/settings_homeserver/settings_homeserver.dart @@ -17,7 +17,7 @@ class SettingsHomeserver extends StatefulWidget { class SettingsHomeserverController extends State { Future<({String name, String version, Uri federationBaseUrl})> - fetchServerInfo() async { + fetchServerInfo() async { final client = Matrix.of(context).client; final domain = client.userID!.domain!; final httpClient = client.httpClient; @@ -37,15 +37,10 @@ class SettingsHomeserverController extends State { } final serverVersionResult = await http.get( - federationBaseUrl.resolveUri( - Uri(path: '/_matrix/federation/v1/version'), - ), + federationBaseUrl.resolveUri(Uri(path: '/_matrix/federation/v1/version')), ); final { - 'server': { - 'name': String name, - 'version': String version, - }, + 'server': {'name': String name, 'version': String version}, } = Map>.from( jsonDecode(serverVersionResult.body), ); diff --git a/lib/pages/settings_homeserver/settings_homeserver_view.dart b/lib/pages/settings_homeserver/settings_homeserver_view.dart index ee02337f0..3728b1e0c 100644 --- a/lib/pages/settings_homeserver/settings_homeserver_view.dart +++ b/lib/pages/settings_homeserver/settings_homeserver_view.dart @@ -30,15 +30,16 @@ class SettingsHomeserverView extends StatelessWidget { automaticallyImplyLeading: !FluffyThemes.isColumnMode(context), centerTitle: FluffyThemes.isColumnMode(context), title: Text( - L10n.of(context) - .aboutHomeserver(client.userID?.domain ?? 'Homeserver'), + L10n.of( + context, + ).aboutHomeserver(client.userID?.domain ?? 'Homeserver'), ), ), body: MaxWidthBody( withScrolling: true, child: SelectionArea( child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ ListTile( title: Text( @@ -68,9 +69,7 @@ class SettingsHomeserverView extends StatelessWidget { } if (data == null) { return const Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ); } final supportPage = data.supportPage; @@ -85,7 +84,7 @@ class SettingsHomeserverView extends StatelessWidget { ); } return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (supportPage != null) ListTile( @@ -93,32 +92,28 @@ class SettingsHomeserverView extends StatelessWidget { subtitle: Text(supportPage.toString()), ), if (contacts != null) - ...contacts.map( - (contact) { - return ListTile( - title: Text( - contact.role.localizedString( - L10n.of(context), - ), - ), - subtitle: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (contact.emailAddress != null) - TextButton( - onPressed: () {}, - child: Text(contact.emailAddress!), - ), - if (contact.matrixId != null) - TextButton( - onPressed: () {}, - child: Text(contact.matrixId!), - ), - ], - ), - ); - }, - ), + ...contacts.map((contact) { + return ListTile( + title: Text( + contact.role.localizedString(L10n.of(context)), + ), + subtitle: Column( + mainAxisSize: .min, + children: [ + if (contact.emailAddress != null) + TextButton( + onPressed: () {}, + child: Text(contact.emailAddress!), + ), + if (contact.matrixId != null) + TextButton( + onPressed: () {}, + child: Text(contact.matrixId!), + ), + ], + ), + ); + }), ], ); }, @@ -129,7 +124,7 @@ class SettingsHomeserverView extends StatelessWidget { final error = snapshot.error; if (error != null) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ Icon( Icons.error_outlined, @@ -139,9 +134,7 @@ class SettingsHomeserverView extends StatelessWidget { Text( error.toLocalizedString(context), textAlign: TextAlign.center, - style: TextStyle( - color: theme.colorScheme.error, - ), + style: TextStyle(color: theme.colorScheme.error), ), ], ); @@ -149,13 +142,11 @@ class SettingsHomeserverView extends StatelessWidget { final data = snapshot.data; if (data == null) { return const Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ); } return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ ListTile( title: Text(L10n.of(context).name), @@ -169,8 +160,9 @@ class SettingsHomeserverView extends StatelessWidget { title: const Text('Federation Base URL'), subtitle: Linkify( text: data.federationBaseUrl.toString(), - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, @@ -191,7 +183,7 @@ class SettingsHomeserverView extends StatelessWidget { final error = snapshot.error; if (error != null) { return Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ Icon( Icons.error_outlined, @@ -201,9 +193,7 @@ class SettingsHomeserverView extends StatelessWidget { Text( error.toLocalizedString(context), textAlign: TextAlign.center, - style: TextStyle( - color: theme.colorScheme.error, - ), + style: TextStyle(color: theme.colorScheme.error), ), ], ); @@ -211,14 +201,12 @@ class SettingsHomeserverView extends StatelessWidget { final wellKnown = snapshot.data; if (wellKnown == null) { return const Center( - child: CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), + child: CircularProgressIndicator.adaptive(strokeWidth: 2), ); } final identityServer = wellKnown.mIdentityServer; return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ ListTile( title: Text( @@ -233,8 +221,9 @@ class SettingsHomeserverView extends StatelessWidget { title: const Text('Base URL'), subtitle: Linkify( text: wellKnown.mHomeserver.baseUrl.toString(), - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, @@ -248,8 +237,9 @@ class SettingsHomeserverView extends StatelessWidget { title: const Text('Identity Server:'), subtitle: Linkify( text: identityServer.baseUrl.toString(), - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( color: theme.colorScheme.primary, @@ -262,15 +252,17 @@ class SettingsHomeserverView extends StatelessWidget { (entry) => ListTile( title: Text(entry.key), subtitle: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), color: theme.colorScheme.surfaceContainer, child: SingleChildScrollView( padding: const EdgeInsets.all(16), scrollDirection: Axis.horizontal, child: Text( - const JsonEncoder.withIndent(' ') - .convert(entry.value), + const JsonEncoder.withIndent( + ' ', + ).convert(entry.value), style: TextStyle( color: theme.colorScheme.onSurface, ), diff --git a/lib/pages/settings_ignore_list/settings_ignore_list_view.dart b/lib/pages/settings_ignore_list/settings_ignore_list_view.dart index 19bd17c27..7dee64d11 100644 --- a/lib/pages/settings_ignore_list/settings_ignore_list_view.dart +++ b/lib/pages/settings_ignore_list/settings_ignore_list_view.dart @@ -36,12 +36,12 @@ class SettingsIgnoreListView extends StatelessWidget { return const Center(child: CircularProgressIndicator.adaptive()); } return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ Padding( padding: const EdgeInsets.all(16.0), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ TextField( controller: controller.controller, @@ -68,9 +68,7 @@ class SettingsIgnoreListView extends StatelessWidget { ], ), ), - Divider( - color: theme.dividerColor, - ), + Divider(color: theme.dividerColor), Expanded( child: ListView.builder( itemCount: client.ignoredUsers.length, diff --git a/lib/pages/settings_notifications/settings_notifications.dart b/lib/pages/settings_notifications/settings_notifications.dart index 9ba74e930..98e430304 100644 --- a/lib/pages/settings_notifications/settings_notifications.dart +++ b/lib/pages/settings_notifications/settings_notifications.dart @@ -45,11 +45,8 @@ class SettingsNotificationsController extends State { final success = await showFutureLoadingDialog( context: context, future: () => Matrix.of(context).client.deletePusher( - PusherId( - appId: pusher.appId, - pushkey: pusher.pushkey, - ), - ), + PusherId(appId: pusher.appId, pushkey: pusher.pushkey), + ), ); if (success.error != null) return; @@ -66,10 +63,7 @@ class SettingsNotificationsController extends State { isLoading = true; }); try { - final updateFromSync = Matrix.of(context) - .client - .onSync - .stream + final updateFromSync = Matrix.of(context).client.onSync.stream .where( (syncUpdate) => syncUpdate.accountData?.any( @@ -78,17 +72,16 @@ class SettingsNotificationsController extends State { false, ) .first; - await Matrix.of(context).client.setPushRuleEnabled( - kind, - pushRule.ruleId, - !pushRule.enabled, - ); + await Matrix.of( + context, + ).client.setPushRuleEnabled(kind, pushRule.ruleId, !pushRule.enabled); await updateFromSync; } catch (e, s) { Logs().w('Unable to toggle push rule', e, s); if (!mounted) return; - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } finally { if (mounted) { setState(() { @@ -116,9 +109,7 @@ class SettingsNotificationsController extends State { scrollDirection: Axis.horizontal, child: SelectableText( prettyJson(rule.toJson()), - style: TextStyle( - color: theme.colorScheme.onSurface, - ), + style: TextStyle(color: theme.colorScheme.onSurface), ), ), ), @@ -158,10 +149,7 @@ class SettingsNotificationsController extends State { isLoading = true; }); try { - final updateFromSync = Matrix.of(context) - .client - .onSync - .stream + final updateFromSync = Matrix.of(context).client.onSync.stream .where( (syncUpdate) => syncUpdate.accountData?.any( @@ -170,17 +158,14 @@ class SettingsNotificationsController extends State { false, ) .first; - await Matrix.of(context).client.deletePushRule( - kind, - rule.ruleId, - ); + await Matrix.of(context).client.deletePushRule(kind, rule.ruleId); await updateFromSync; } catch (e, s) { Logs().w('Unable to delete push rule', e, s); if (!mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(e.toLocalizedString(context))), - ); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(e.toLocalizedString(context)))); } finally { if (mounted) { setState(() { diff --git a/lib/pages/settings_notifications/settings_notifications_view.dart b/lib/pages/settings_notifications/settings_notifications_view.dart index 548aa598c..8259cfe2b 100644 --- a/lib/pages/settings_notifications/settings_notifications_view.dart +++ b/lib/pages/settings_notifications/settings_notifications_view.dart @@ -37,12 +37,12 @@ class SettingsNotificationsView extends StatelessWidget { body: MaxWidthBody( child: StreamBuilder( stream: Matrix.of(context).client.onSync.stream.where( - (syncUpdate) => - syncUpdate.accountData?.any( - (accountData) => accountData.type == 'm.push_rules', - ) ?? - false, - ), + (syncUpdate) => + syncUpdate.accountData?.any( + (accountData) => accountData.type == 'm.push_rules', + ) ?? + false, + ), builder: (BuildContext context, _) { final theme = Theme.of(context); return SelectionArea( @@ -96,14 +96,14 @@ class SettingsNotificationsView extends StatelessWidget { onChanged: controller.isLoading ? null : rule.ruleId != '.m.rule.master' && - Matrix.of(context) - .client - .allPushNotificationsMuted - ? null - : (_) => controller.togglePushRule( - category.kind, - rule, - ), + Matrix.of( + context, + ).client.allPushNotificationsMuted + ? null + : (_) => controller.togglePushRule( + category.kind, + rule, + ), ), ), Divider(color: theme.dividerColor), @@ -118,8 +118,9 @@ class SettingsNotificationsView extends StatelessWidget { ), ), FutureBuilder?>( - future: controller.pusherFuture ??= - Matrix.of(context).client.getPushers(), + future: controller.pusherFuture ??= Matrix.of( + context, + ).client.getPushers(), builder: (context, snapshot) { if (snapshot.hasError) { Center( diff --git a/lib/pages/settings_password/settings_password.dart b/lib/pages/settings_password/settings_password.dart index bc2400c8c..413f80259 100644 --- a/lib/pages/settings_password/settings_password.dart +++ b/lib/pages/settings_password/settings_password.dart @@ -55,13 +55,11 @@ class SettingsPasswordController extends State { try { final scaffoldMessenger = ScaffoldMessenger.of(context); await Matrix.of(context).client.changePassword( - newPassword1Controller.text, - oldPassword: oldPasswordController.text, - ); + newPassword1Controller.text, + oldPassword: oldPasswordController.text, + ); scaffoldMessenger.showSnackBar( - SnackBar( - content: Text(L10n.of(context).passwordHasBeenChanged), - ), + SnackBar(content: Text(L10n.of(context).passwordHasBeenChanged)), ); if (mounted) context.pop(); } catch (e) { diff --git a/lib/pages/settings_password/settings_password_view.dart b/lib/pages/settings_password/settings_password_view.dart index b52a22340..fc0904a98 100644 --- a/lib/pages/settings_password/settings_password_view.dart +++ b/lib/pages/settings_password/settings_password_view.dart @@ -15,9 +15,7 @@ class SettingsPasswordView extends StatelessWidget { final theme = Theme.of(context); return Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).changePassword), - ), + appBar: AppBar(title: Text(L10n.of(context).changePassword)), body: ListTileTheme( iconColor: theme.colorScheme.onSurface, child: MaxWidthBody( @@ -69,8 +67,9 @@ class SettingsPasswordView extends StatelessWidget { SizedBox( width: double.infinity, child: ElevatedButton( - onPressed: - controller.loading ? null : controller.changePassword, + onPressed: controller.loading + ? null + : controller.changePassword, child: controller.loading ? const LinearProgressIndicator() : Text(L10n.of(context).changePassword), diff --git a/lib/pages/settings_security/settings_security.dart b/lib/pages/settings_security/settings_security.dart index db12783f9..5863e2578 100644 --- a/lib/pages/settings_security/settings_security.dart +++ b/lib/pages/settings_security/settings_security.dart @@ -90,13 +90,13 @@ class SettingsSecurityController extends State { await showFutureLoadingDialog( context: context, future: () => Matrix.of(context).client.deactivateAccount( - auth: AuthenticationPassword( - password: input, - identifier: AuthenticationUserIdentifier( - user: Matrix.of(context).client.userID!, - ), - ), + auth: AuthenticationPassword( + password: input, + identifier: AuthenticationUserIdentifier( + user: Matrix.of(context).client.userID!, ), + ), + ), ); } @@ -104,9 +104,7 @@ class SettingsSecurityController extends State { void changeShareKeysWith(ShareKeysWith? shareKeysWith) async { if (shareKeysWith == null) return; - AppSettings.shareKeysWith.setItem( - shareKeysWith.name, - ); + AppSettings.shareKeysWith.setItem(shareKeysWith.name); Matrix.of(context).client.shareKeysWith = shareKeysWith; setState(() {}); } diff --git a/lib/pages/settings_security/settings_security_view.dart b/lib/pages/settings_security/settings_security_view.dart index 039fd97eb..2d38a5c4e 100644 --- a/lib/pages/settings_security/settings_security_view.dart +++ b/lib/pages/settings_security/settings_security_view.dart @@ -33,10 +33,9 @@ class SettingsSecurityView extends StatelessWidget { iconColor: theme.colorScheme.onSurface, child: MaxWidthBody( child: FutureBuilder( - future: Matrix.of(context) - .client - .getCapabilities() - .timeout(const Duration(seconds: 10)), + future: Matrix.of( + context, + ).client.getCapabilities().timeout(const Duration(seconds: 10)), builder: (context, snapshot) { final capabilities = snapshot.data; final error = snapshot.error; @@ -61,8 +60,9 @@ class SettingsSecurityView extends StatelessWidget { ), SettingsSwitchListTile.adaptive( title: L10n.of(context).sendTypingNotifications, - subtitle: - L10n.of(context).sendTypingNotificationsDescription, + subtitle: L10n.of( + context, + ).sendTypingNotificationsDescription, setting: AppSettings.sendTypingNotifications, ), SettingsSwitchListTile.adaptive( @@ -103,14 +103,16 @@ class SettingsSecurityView extends StatelessWidget { ), ListTile( title: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 2), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 2, + ), color: theme.colorScheme.onInverseSurface, child: DropdownButton( isExpanded: true, padding: const EdgeInsets.symmetric(horizontal: 8.0), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 2), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius / 2, + ), underline: const SizedBox.shrink(), value: Matrix.of(context).client.shareKeysWith, items: ShareKeysWith.values diff --git a/lib/pages/settings_style/settings_style.dart b/lib/pages/settings_style/settings_style.dart index 3ec628c53..f3d559a0d 100644 --- a/lib/pages/settings_style/settings_style.dart +++ b/lib/pages/settings_style/settings_style.dart @@ -26,10 +26,7 @@ class SettingsStyleController extends State { void setWallpaper() async { final client = Matrix.of(context).client; - final picked = await selectFiles( - context, - type: FileSelectorType.images, - ); + final picked = await selectFiles(context, type: FileSelectorType.images); final pickedFile = picked.firstOrNull; if (pickedFile == null) return; @@ -103,14 +100,11 @@ class SettingsStyleController extends State { } void deleteChatWallpaper() => showFutureLoadingDialog( - context: context, - future: () => Matrix.of(context).client.setApplicationAccountConfig( - const ApplicationAccountConfig( - wallpaperUrl: null, - wallpaperBlur: null, - ), - ), - ); + context: context, + future: () => Matrix.of(context).client.setApplicationAccountConfig( + const ApplicationAccountConfig(wallpaperUrl: null, wallpaperBlur: null), + ), + ); ThemeMode get currentTheme => ThemeController.of(context).themeMode; Color? get currentColor => ThemeController.of(context).primaryColor; diff --git a/lib/pages/settings_style/settings_style_view.dart b/lib/pages/settings_style/settings_style_view.dart index 23dbe68cb..fcace2b59 100644 --- a/lib/pages/settings_style/settings_style_view.dart +++ b/lib/pages/settings_style/settings_style_view.dart @@ -39,7 +39,7 @@ class SettingsStyleView extends StatelessWidget { backgroundColor: theme.colorScheme.surface, body: MaxWidthBody( child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + crossAxisAlignment: .stretch, children: [ Padding( padding: const EdgeInsets.all(12.0), @@ -66,9 +66,7 @@ class SettingsStyleView extends StatelessWidget { ], ), ), - Divider( - color: theme.dividerColor, - ), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context).setColorTheme, @@ -82,10 +80,11 @@ class SettingsStyleView extends StatelessWidget { builder: (light, dark) { final systemColor = Theme.of(context).brightness == Brightness.light - ? light?.primary - : dark?.primary; - final colors = - List.from(SettingsStyleController.customColors); + ? light?.primary + : dark?.primary; + final colors = List.from( + SettingsStyleController.customColors, + ); if (systemColor == null) { colors.remove(null); } @@ -109,8 +108,9 @@ class SettingsStyleView extends StatelessWidget { child: Material( color: color ?? systemColor, elevation: 6, - borderRadius: - BorderRadius.circular(colorPickerSize), + borderRadius: BorderRadius.circular( + colorPickerSize, + ), child: SizedBox( width: colorPickerSize, height: colorPickerSize, @@ -119,9 +119,9 @@ class SettingsStyleView extends StatelessWidget { child: Icon( Icons.check, size: 16, - color: Theme.of(context) - .colorScheme - .onPrimary, + color: Theme.of( + context, + ).colorScheme.onPrimary, ), ) : null, @@ -134,9 +134,7 @@ class SettingsStyleView extends StatelessWidget { ); }, ), - Divider( - color: theme.dividerColor, - ), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context).messagesStyle, @@ -160,7 +158,7 @@ class SettingsStyleView extends StatelessWidget { final accountConfig = client.applicationAccountConfig; return Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ AnimatedContainer( duration: FluffyThemes.animationDuration, @@ -189,14 +187,16 @@ class SettingsStyleView extends StatelessWidget { ), ), Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ const SizedBox(height: 16), StateMessage( Event( eventId: 'style_dummy', - room: - Room(id: '!style_dummy', client: client), + room: Room( + id: '!style_dummy', + client: client, + ), content: {'membership': 'join'}, type: EventTypes.RoomMember, senderId: client.userID!, @@ -229,7 +229,8 @@ class SettingsStyleView extends StatelessWidget { 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor', style: TextStyle( color: theme.onBubbleColor, - fontSize: AppConfig.messageFontSize * + fontSize: + AppConfig.messageFontSize * AppSettings.fontSizeFactor.value, ), ), @@ -262,7 +263,8 @@ class SettingsStyleView extends StatelessWidget { 'Lorem ipsum dolor sit amet', style: TextStyle( color: theme.colorScheme.onSurface, - fontSize: AppConfig.messageFontSize * + fontSize: + AppConfig.messageFontSize * AppSettings.fontSizeFactor.value, ), ), @@ -275,9 +277,7 @@ class SettingsStyleView extends StatelessWidget { ], ), ), - Divider( - color: theme.dividerColor, - ), + Divider(color: theme.dividerColor), ListTile( title: TextButton.icon( style: TextButton.styleFrom( @@ -325,9 +325,7 @@ class SettingsStyleView extends StatelessWidget { ), ListTile( title: Text(L10n.of(context).fontSize), - trailing: Text( - '× ${AppSettings.fontSizeFactor.value}', - ), + trailing: Text('× ${AppSettings.fontSizeFactor.value}'), ), Slider.adaptive( min: 0.5, @@ -337,9 +335,7 @@ class SettingsStyleView extends StatelessWidget { semanticFormatterCallback: (d) => d.toString(), onChanged: controller.changeFontSizeFactor, ), - Divider( - color: theme.dividerColor, - ), + Divider(color: theme.dividerColor), ListTile( title: Text( L10n.of(context).overview, diff --git a/lib/utils/account_bundles.dart b/lib/utils/account_bundles.dart index 8bd296e05..7d5619267 100644 --- a/lib/utils/account_bundles.dart +++ b/lib/utils/account_bundles.dart @@ -7,9 +7,9 @@ class AccountBundles { AccountBundles({this.prefix, this.bundles}); AccountBundles.fromJson(Map json) - : prefix = json.tryGet('prefix'), - bundles = json['bundles'] is List - ? json['bundles'] + : prefix = json.tryGet('prefix'), + bundles = json['bundles'] is List + ? json['bundles'] .map((b) { try { return AccountBundle.fromJson(b); @@ -19,13 +19,12 @@ class AccountBundles { }) .whereType() .toList() - : null; + : null; Map toJson() => { - if (prefix != null) 'prefix': prefix, - if (bundles != null) - 'bundles': bundles!.map((v) => v.toJson()).toList(), - }; + if (prefix != null) 'prefix': prefix, + if (bundles != null) 'bundles': bundles!.map((v) => v.toJson()).toList(), + }; } class AccountBundle { @@ -35,13 +34,13 @@ class AccountBundle { AccountBundle({this.name, this.priority}); AccountBundle.fromJson(Map json) - : name = json.tryGet('name'), - priority = json.tryGet('priority'); + : name = json.tryGet('name'), + priority = json.tryGet('priority'); Map toJson() => { - if (name != null) 'name': name, - if (priority != null) 'priority': priority, - }; + if (name != null) 'name': name, + if (priority != null) 'priority': priority, + }; } const accountBundlesType = 'im.fluffychat.account_bundles'; @@ -50,24 +49,21 @@ extension AccountBundlesExtension on Client { List get accountBundles { List? ret; if (accountData.containsKey(accountBundlesType)) { - ret = AccountBundles.fromJson(accountData[accountBundlesType]!.content) - .bundles; + ret = AccountBundles.fromJson( + accountData[accountBundlesType]!.content, + ).bundles; } ret ??= []; if (ret.isEmpty) { - ret.add( - AccountBundle( - name: userID, - priority: 0, - ), - ); + ret.add(AccountBundle(name: userID, priority: 0)); } return ret; } Future setAccountBundle(String name, [int? priority]) async { - final data = - AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {}); + final data = AccountBundles.fromJson( + accountData[accountBundlesType]?.content ?? {}, + ); var foundBundle = false; final bundles = data.bundles ??= []; for (final bundle in bundles) { @@ -87,16 +83,18 @@ extension AccountBundlesExtension on Client { if (!accountData.containsKey(accountBundlesType)) { return; // nothing to do } - final data = - AccountBundles.fromJson(accountData[accountBundlesType]!.content); + final data = AccountBundles.fromJson( + accountData[accountBundlesType]!.content, + ); if (data.bundles == null) return; data.bundles!.removeWhere((b) => b.name == name); await setAccountData(userID!, accountBundlesType, data.toJson()); } String get sendPrefix { - final data = - AccountBundles.fromJson(accountData[accountBundlesType]?.content ?? {}); + final data = AccountBundles.fromJson( + accountData[accountBundlesType]?.content ?? {}, + ); return data.prefix!; } } diff --git a/lib/utils/account_config.dart b/lib/utils/account_config.dart index a5e2dfd00..7ac107376 100644 --- a/lib/utils/account_config.dart +++ b/lib/utils/account_config.dart @@ -8,19 +8,11 @@ extension ApplicationAccountConfigExtension on Client { accountData[accountDataKey]?.content ?? {}, ); - Future setApplicationAccountConfig( - ApplicationAccountConfig config, - ) => - setAccountData( - userID!, - accountDataKey, - config.toJson(), - ); + Future setApplicationAccountConfig(ApplicationAccountConfig config) => + setAccountData(userID!, accountDataKey, config.toJson()); /// Only updates the specified values in ApplicationAccountConfig - Future updateApplicationAccountConfig( - ApplicationAccountConfig config, - ) { + Future updateApplicationAccountConfig(ApplicationAccountConfig config) { final currentConfig = applicationAccountConfig; return setAccountData( userID!, @@ -57,14 +49,15 @@ class ApplicationAccountConfig { wallpaperUrl: json['wallpaper_url'] is String ? Uri.tryParse(json['wallpaper_url']) : null, - wallpaperOpacity: - _sanitizedOpacity(json.tryGet('wallpaper_opacity')), + wallpaperOpacity: _sanitizedOpacity( + json.tryGet('wallpaper_opacity'), + ), wallpaperBlur: json.tryGet('wallpaper_blur'), ); Map toJson() => { - 'wallpaper_url': wallpaperUrl?.toString(), - 'wallpaper_opacity': wallpaperOpacity, - 'wallpaper_blur': wallpaperBlur, - }; + 'wallpaper_url': wallpaperUrl?.toString(), + 'wallpaper_opacity': wallpaperOpacity, + 'wallpaper_blur': wallpaperBlur, + }; } diff --git a/lib/utils/adaptive_bottom_sheet.dart b/lib/utils/adaptive_bottom_sheet.dart index 7681e54f7..a0e187d3e 100644 --- a/lib/utils/adaptive_bottom_sheet.dart +++ b/lib/utils/adaptive_bottom_sheet.dart @@ -21,10 +21,7 @@ Future showAdaptiveBottomSheet({ builder: (context) => Center( child: Container( margin: const EdgeInsets.all(16), - constraints: const BoxConstraints( - maxWidth: 480, - maxHeight: 720, - ), + constraints: const BoxConstraints(maxWidth: 480, maxHeight: 720), child: Material( elevation: Theme.of(context).dialogTheme.elevation ?? 4, shadowColor: Theme.of(context).dialogTheme.shadowColor, @@ -42,11 +39,9 @@ Future showAdaptiveBottomSheet({ context: context, builder: (context) => ConstrainedBox( constraints: BoxConstraints( - maxHeight: MediaQuery.viewInsetsOf(context).bottom + - min( - MediaQuery.sizeOf(context).height - 32, - 600, - ), + maxHeight: + MediaQuery.viewInsetsOf(context).bottom + + min(MediaQuery.sizeOf(context).height - 32, 600), ), child: builder(context), ), diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart index 31a4bcd90..4e0f91f10 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart @@ -62,7 +62,8 @@ class BackgroundPush { Future loadLocale() async { final context = matrix?.context; // inspired by _lookupL10n in .dart_tool/flutter_gen/gen_l10n/l10n.dart - l10n ??= (context != null ? L10n.of(context) : null) ?? + l10n ??= + (context != null ? L10n.of(context) : null) ?? (await L10n.delegate.load(PlatformDispatcher.instance.locale)); } @@ -78,8 +79,26 @@ class BackgroundPush { void _init() async { //firebaseEnabled = true; try { - mainIsolateReceivePort?.listen( - (message) async { + mainIsolateReceivePort?.listen((message) async { + try { + await notificationTap( + NotificationResponseJson.fromJsonString(message), + client: client, + router: FluffyChatApp.router, + l10n: l10n, + ); + } catch (e, s) { + Logs().wtf('Main Notification Tap crashed', e, s); + } + }); + if (PlatformInfos.isAndroid) { + final port = ReceivePort(); + IsolateNameServer.removePortNameMapping('background_tab_port'); + IsolateNameServer.registerPortWithName( + port.sendPort, + 'background_tab_port', + ); + port.listen((message) async { try { await notificationTap( NotificationResponseJson.fromJsonString(message), @@ -90,29 +109,7 @@ class BackgroundPush { } catch (e, s) { Logs().wtf('Main Notification Tap crashed', e, s); } - }, - ); - if (PlatformInfos.isAndroid) { - final port = ReceivePort(); - IsolateNameServer.removePortNameMapping('background_tab_port'); - IsolateNameServer.registerPortWithName( - port.sendPort, - 'background_tab_port', - ); - port.listen( - (message) async { - try { - await notificationTap( - NotificationResponseJson.fromJsonString(message), - client: client, - router: FluffyChatApp.router, - l10n: l10n, - ); - } catch (e, s) { - Logs().wtf('Main Notification Tap crashed', e, s); - } - }, - ); + }); } await _flutterLocalNotificationsPlugin.initialize( const InitializationSettings( @@ -201,12 +198,14 @@ class BackgroundPush { if (PlatformInfos.isAndroid) { _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() + AndroidFlutterLocalNotificationsPlugin + >() ?.requestNotificationsPermission(); } final clientName = PlatformInfos.clientName; oldTokens ??= {}; - final pushers = await (client.getPushers().catchError((e) { + final pushers = + await (client.getPushers().catchError((e) { Logs().w('[Push] Unable to request pushers', e); return []; })) ?? @@ -235,10 +234,9 @@ class BackgroundPush { currentPushers.first.data.url.toString() == gatewayUrl && currentPushers.first.data.format == AppSettings.pushNotificationsPusherFormat.value && - mapEquals( - currentPushers.single.data.additionalProperties, - {"data_message": pusherDataMessageFormat}, - )) { + mapEquals(currentPushers.single.data.additionalProperties, { + "data_message": pusherDataMessageFormat, + })) { Logs().i('[Push] Pusher already set'); } else { Logs().i('Need to set new pusher'); @@ -290,8 +288,8 @@ class BackgroundPush { final pusherDataMessageFormat = Platform.isAndroid ? 'android' : Platform.isIOS - ? 'ios' - : null; + ? 'ios' + : null; static bool _wentToRoomOnStartup = false; @@ -315,9 +313,9 @@ class BackgroundPush { } // ignore: unawaited_futures - _flutterLocalNotificationsPlugin - .getNotificationAppLaunchDetails() - .then((details) { + _flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails().then(( + details, + ) { if (details == null || !details.didNotificationLaunchApp || _wentToRoomOnStartup) { @@ -348,9 +346,7 @@ class BackgroundPush { if (PlatformInfos.isAndroid) { onFcmError?.call( l10n!.noGoogleServicesWarning, - link: Uri.parse( - AppConfig.enablePushTutorial, - ), + link: Uri.parse(AppConfig.enablePushTutorial), ); return; } @@ -397,15 +393,13 @@ class BackgroundPush { 'https://matrix.gateway.unifiedpush.org/_matrix/push/v1/notify'; try { final url = Uri.parse(newEndpoint) - .replace( - path: '/_matrix/push/v1/notify', - query: '', - ) + .replace(path: '/_matrix/push/v1/notify', query: '') .toString() .split('?') .first; - final res = - json.decode(utf8.decode((await http.get(Uri.parse(url))).bodyBytes)); + final res = json.decode( + utf8.decode((await http.get(Uri.parse(url))).bodyBytes), + ); if (res['gateway'] == 'matrix' || (res['unifiedpush'] is Map && res['unifiedpush']['gateway'] == 'matrix')) { @@ -436,14 +430,13 @@ class BackgroundPush { upAction = true; Logs().i('[Push] Removing UnifiedPush endpoint...'); final oldEndpoint = AppSettings.unifiedPushEndpoint.value; - await AppSettings.unifiedPushEndpoint - .setItem(AppSettings.unifiedPushEndpoint.defaultValue); + await AppSettings.unifiedPushEndpoint.setItem( + AppSettings.unifiedPushEndpoint.defaultValue, + ); await AppSettings.unifiedPushRegistered.setItem(false); if (oldEndpoint.isNotEmpty) { // remove the old pusher - await setupPusher( - oldTokens: {oldEndpoint}, - ); + await setupPusher(oldTokens: {oldEndpoint}); } } diff --git a/lib/utils/client_download_content_extension.dart b/lib/utils/client_download_content_extension.dart index 3da8a1c51..b93357a0f 100644 --- a/lib/utils/client_download_content_extension.dart +++ b/lib/utils/client_download_content_extension.dart @@ -41,8 +41,9 @@ extension ClientDownloadContentExtension on Client { final response = await httpClient.get( httpUri, - headers: - accessToken == null ? null : {'authorization': 'Bearer $accessToken'}, + headers: accessToken == null + ? null + : {'authorization': 'Bearer $accessToken'}, ); if (response.statusCode != 200) { throw Exception(); diff --git a/lib/utils/client_manager.dart b/lib/utils/client_manager.dart index 716abd80c..64d5b23d3 100644 --- a/lib/utils/client_manager.dart +++ b/lib/utils/client_manager.dart @@ -38,22 +38,27 @@ abstract class ClientManager { clientNames.add(PlatformInfos.clientName); await store.setStringList(clientNamespace, clientNames.toList()); } - final clients = - await Future.wait(clientNames.map((name) => createClient(name, store))); + final clients = await Future.wait( + clientNames.map((name) => createClient(name, store)), + ); if (initialize) { await Future.wait( clients.map( - (client) => client.initWithRestore( - onMigration: () async { - final l10n = await lookupL10n(PlatformDispatcher.instance.locale); - sendInitNotification( - l10n.databaseMigrationTitle, - l10n.databaseMigrationBody, - ); - }, - ).catchError( - (e, s) => Logs().e('Unable to initialize client', e, s), - ), + (client) => client + .initWithRestore( + onMigration: () async { + final l10n = await lookupL10n( + PlatformDispatcher.instance.locale, + ); + sendInitNotification( + l10n.databaseMigrationTitle, + l10n.databaseMigrationBody, + ); + }, + ) + .catchError( + (e, s) => Logs().e('Unable to initialize client', e, s), + ), ), ); } @@ -122,25 +127,26 @@ abstract class ClientManager { AuthenticationTypes.sso, }, nativeImplementations: nativeImplementations, - customImageResizer: - PlatformInfos.isMobile || kIsWeb ? customImageResizer : null, + customImageResizer: PlatformInfos.isMobile || kIsWeb + ? customImageResizer + : null, defaultNetworkRequestTimeout: const Duration(minutes: 30), enableDehydratedDevices: true, - shareKeysWith: ShareKeysWith.values - .singleWhereOrNull((share) => share.name == shareKeysWith) ?? + shareKeysWith: + ShareKeysWith.values.singleWhereOrNull( + (share) => share.name == shareKeysWith, + ) ?? ShareKeysWith.all, convertLinebreaksInFormatting: false, - onSoftLogout: - enableSoftLogout ? (client) => client.refreshAccessToken() : null, + onSoftLogout: enableSoftLogout + ? (client) => client.refreshAccessToken() + : null, ); } static void sendInitNotification(String title, String body) async { if (kIsWeb) { - html.Notification( - title, - body: body, - ); + html.Notification(title, body: body); return; } if (Platform.isLinux) { @@ -148,9 +154,7 @@ abstract class ClientManager { title, body: body, appName: AppSettings.applicationName.value, - hints: [ - NotificationHint.soundName('message-new-instant'), - ], + hints: [NotificationHint.soundName('message-new-instant')], ); return; } diff --git a/lib/utils/custom_http_client.dart b/lib/utils/custom_http_client.dart index b0a3dcb28..66b1dcad2 100644 --- a/lib/utils/custom_http_client.dart +++ b/lib/utils/custom_http_client.dart @@ -33,8 +33,8 @@ class CustomHttpClient { } static http.Client createHTTPClient() => retry.RetryClient( - PlatformInfos.isAndroid - ? IOClient(customHttpClient(ISRG_X1)) - : http.Client(), - ); + PlatformInfos.isAndroid + ? IOClient(customHttpClient(ISRG_X1)) + : http.Client(), + ); } diff --git a/lib/utils/custom_image_resizer.dart b/lib/utils/custom_image_resizer.dart index 3431bfc6f..b25ecbbff 100644 --- a/lib/utils/custom_image_resizer.dart +++ b/lib/utils/custom_image_resizer.dart @@ -55,7 +55,8 @@ Future customImageResizer( // scale down image for blurhashing to speed it up final (blurW, blurH) = _scaleToBox(width, height, boxSize: 100); final blurhashImg = nativeImg.resample( - blurW, blurH, + blurW, + blurH, // nearest is unsupported... native.Transform.bilinear, ); @@ -73,8 +74,11 @@ Future customImageResizer( if (width > max || height > max) { (width, height) = _scaleToBox(width, height, boxSize: max); - final scaledImg = - nativeImg.resample(width, height, native.Transform.lanczos); + final scaledImg = nativeImg.resample( + width, + height, + native.Transform.lanczos, + ); nativeImg.free(); nativeImg = scaledImg; } diff --git a/lib/utils/custom_scroll_behaviour.dart b/lib/utils/custom_scroll_behaviour.dart index ba25e9564..32baa332c 100644 --- a/lib/utils/custom_scroll_behaviour.dart +++ b/lib/utils/custom_scroll_behaviour.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; class CustomScrollBehavior extends MaterialScrollBehavior { @override Set get dragDevices => { - PointerDeviceKind.touch, - PointerDeviceKind.trackpad, - }; + PointerDeviceKind.touch, + PointerDeviceKind.trackpad, + }; } diff --git a/lib/utils/date_time_extension.dart b/lib/utils/date_time_extension.dart index ece0a5c49..508f13e29 100644 --- a/lib/utils/date_time_extension.dart +++ b/lib/utils/date_time_extension.dart @@ -42,7 +42,8 @@ extension DateTimeExtension on DateTime { final sameDay = sameYear && now.month == month && now.day == day; - final sameWeek = sameYear && + final sameWeek = + sameYear && !sameDay && now.millisecondsSinceEpoch - millisecondsSinceEpoch < 1000 * 60 * 60 * 24 * 7; @@ -50,14 +51,17 @@ extension DateTimeExtension on DateTime { if (sameDay) { return localizedTimeOfDay(context); } else if (sameWeek) { - return DateFormat.E(Localizations.localeOf(context).languageCode) - .format(this); + return DateFormat.E( + Localizations.localeOf(context).languageCode, + ).format(this); } else if (sameYear) { - return DateFormat.MMMd(Localizations.localeOf(context).languageCode) - .format(this); + return DateFormat.MMMd( + Localizations.localeOf(context).languageCode, + ).format(this); } - return DateFormat.yMMMd(Localizations.localeOf(context).languageCode) - .format(this); + return DateFormat.yMMMd( + Localizations.localeOf(context).languageCode, + ).format(this); } /// If the DateTime is today, this returns [localizedTimeOfDay()], if not it also diff --git a/lib/utils/error_reporter.dart b/lib/utils/error_reporter.dart index 5e90afcb5..c0ed2a3e7 100644 --- a/lib/utils/error_reporter.dart +++ b/lib/utils/error_reporter.dart @@ -40,10 +40,7 @@ class ErrorReporter { child: SingleChildScrollView( child: Text( text, - style: const TextStyle( - fontSize: 14, - fontFamily: 'RobotoMono', - ), + style: const TextStyle(fontSize: 14, fontFamily: 'RobotoMono'), ), ), ), @@ -53,9 +50,7 @@ class ErrorReporter { child: Text(L10n.of(context).close), ), AdaptiveDialogAction( - onPressed: () => Clipboard.setData( - ClipboardData(text: text), - ), + onPressed: () => Clipboard.setData(ClipboardData(text: text)), child: Text(L10n.of(context).copy), ), AdaptiveDialogAction( diff --git a/lib/utils/event_checkbox_extension.dart b/lib/utils/event_checkbox_extension.dart index cf3832ba6..61e20c408 100644 --- a/lib/utils/event_checkbox_extension.dart +++ b/lib/utils/event_checkbox_extension.dart @@ -6,18 +6,17 @@ extension EventCheckboxRoomExtension on Room { String eventId, int checkboxId, { String? txid, - }) => - sendEvent( - { - 'm.relates_to': { - 'rel_type': relationshipType, - 'event_id': eventId, - 'checkbox_id': checkboxId, - }, - }, - type: EventTypes.Reaction, - txid: txid, - ); + }) => sendEvent( + { + 'm.relates_to': { + 'rel_type': relationshipType, + 'event_id': eventId, + 'checkbox_id': checkboxId, + }, + }, + type: EventTypes.Reaction, + txid: txid, + ); } extension EventCheckboxExtension on Event { diff --git a/lib/utils/fluffy_share.dart b/lib/utils/fluffy_share.dart index b699175b9..c2bd2a5de 100644 --- a/lib/utils/fluffy_share.dart +++ b/lib/utils/fluffy_share.dart @@ -23,12 +23,10 @@ abstract class FluffyShare { ); return; } - await Clipboard.setData( - ClipboardData(text: text), - ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context).copiedToClipboard)), - ); + await Clipboard.setData(ClipboardData(text: text)); + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(L10n.of(context).copiedToClipboard))); return; } diff --git a/lib/utils/init_with_restore.dart b/lib/utils/init_with_restore.dart index feb95e003..71cc7f8b4 100644 --- a/lib/utils/init_with_restore.dart +++ b/lib/utils/init_with_restore.dart @@ -31,22 +31,22 @@ class SessionBackup { SessionBackup.fromJson(jsonDecode(json)); factory SessionBackup.fromJson(Map json) => SessionBackup( - olmAccount: json['olm_account'], - accessToken: json['access_token'], - userId: json['user_id'], - homeserver: json['homeserver'], - deviceId: json['device_id'], - deviceName: json['device_name'], - ); + olmAccount: json['olm_account'], + accessToken: json['access_token'], + userId: json['user_id'], + homeserver: json['homeserver'], + deviceId: json['device_id'], + deviceName: json['device_name'], + ); Map toJson() => { - 'olm_account': olmAccount, - 'access_token': accessToken, - 'user_id': userId, - 'homeserver': homeserver, - 'device_id': deviceId, - if (deviceName != null) 'device_name': deviceName, - }; + 'olm_account': olmAccount, + 'access_token': accessToken, + 'user_id': userId, + 'homeserver': homeserver, + 'device_id': deviceId, + if (deviceName != null) 'device_name': deviceName, + }; @override String toString() => jsonEncode(toJson()); @@ -82,7 +82,8 @@ extension InitWithRestoreExtension on Client { final homeserver = this.homeserver?.toString(); final deviceId = deviceID; final userId = userID; - final hasBackup = accessToken != null && + final hasBackup = + accessToken != null && homeserver != null && deviceId != null && userId != null; diff --git a/lib/utils/localized_exception_extension.dart b/lib/utils/localized_exception_extension.dart index 838d7ed73..44990b37f 100644 --- a/lib/utils/localized_exception_extension.dart +++ b/lib/utils/localized_exception_extension.dart @@ -20,8 +20,8 @@ extension LocalizedExceptionExtension on Object { final numString = round < 10 ? num.toStringAsFixed(2) : round < 100 - ? num.toStringAsFixed(1) - : round.toString(); + ? num.toStringAsFixed(1) + : round.toString(); return '$numString ${'kMGTPEZY'[i - 1]}B'; } @@ -31,9 +31,9 @@ extension LocalizedExceptionExtension on Object { ]) { if (this is FileTooBigMatrixException) { final exception = this as FileTooBigMatrixException; - return L10n.of(context).fileIsTooBigForServer( - _formatFileSize(exception.maxFileSize), - ); + return L10n.of( + context, + ).fileIsTooBigForServer(_formatFileSize(exception.maxFileSize)); } if (this is OtherPartyCanNotReceiveMessages) { return L10n.of(context).otherPartyNotLoggedIn; diff --git a/lib/utils/markdown_context_builder.dart b/lib/utils/markdown_context_builder.dart index 9404d3504..18b5d5117 100644 --- a/lib/utils/markdown_context_builder.dart +++ b/lib/utils/markdown_context_builder.dart @@ -64,8 +64,10 @@ Widget markdownContextBuilder( if (start == -1) start = 0; final end = selection.end; - final fullLineSelection = - TextSelection(baseOffset: start, extentOffset: end); + final fullLineSelection = TextSelection( + baseOffset: start, + extentOffset: end, + ); const checkBox = '- [ ]'; @@ -78,8 +80,11 @@ Widget markdownContextBuilder( : '$checkBox $line', ) .join('\n'); - controller.text = - controller.text.replaceRange(start, end, replacedRange); + controller.text = controller.text.replaceRange( + start, + end, + replacedRange, + ); ContextMenuController.removeAny(); }, ), diff --git a/lib/utils/matrix_sdk_extensions/device_extension.dart b/lib/utils/matrix_sdk_extensions/device_extension.dart index 55f3ebfc9..3872309ca 100644 --- a/lib/utils/matrix_sdk_extensions/device_extension.dart +++ b/lib/utils/matrix_sdk_extensions/device_extension.dart @@ -22,8 +22,13 @@ IconData _getIconFromName(String displayname) { }.any((s) => name.contains(s))) { return Icons.web_outlined; } - if ({'desktop', 'windows', 'macos', 'linux', 'ubuntu'} - .any((s) => name.contains(s))) { + if ({ + 'desktop', + 'windows', + 'macos', + 'linux', + 'ubuntu', + }.any((s) => name.contains(s))) { return Icons.desktop_mac_outlined; } return Icons.device_unknown_outlined; diff --git a/lib/utils/matrix_sdk_extensions/event_extension.dart b/lib/utils/matrix_sdk_extensions/event_extension.dart index 046df2598..c078bb909 100644 --- a/lib/utils/matrix_sdk_extensions/event_extension.dart +++ b/lib/utils/matrix_sdk_extensions/event_extension.dart @@ -15,8 +15,9 @@ extension LocalizedBody on Event { showFutureLoadingDialog( context: context, futureWithProgress: (onProgress) { - final fileSize = - infoMap['size'] is int ? infoMap['size'] as int : null; + final fileSize = infoMap['size'] is int + ? infoMap['size'] as int + : null; return downloadAndDecryptAttachment( onDownloadProgress: fileSize == null ? null @@ -47,8 +48,11 @@ extension LocalizedBody on Event { thumbnailInfoMap['size'] < room.client.database.maxFileSize; bool get showThumbnail => - [MessageTypes.Image, MessageTypes.Sticker, MessageTypes.Video] - .contains(messageType) && + [ + MessageTypes.Image, + MessageTypes.Sticker, + MessageTypes.Video, + ].contains(messageType) && (kIsWeb || isAttachmentSmallEnough || isThumbnailSmallEnough || diff --git a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart index 1ab307021..0e9724a39 100644 --- a/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart +++ b/lib/utils/matrix_sdk_extensions/filtered_timeline_extension.dart @@ -6,29 +6,28 @@ extension VisibleInGuiExtension on List { List filterByVisibleInGui({ String? exceptionEventId, String? threadId, - }) => - where( - (event) { - if (threadId != null && - event.relationshipType != RelationshipTypes.reaction) { - if ((event.relationshipType != RelationshipTypes.thread || - event.relationshipEventId != threadId) && - event.eventId != threadId) { - return false; - } - } else if (event.relationshipType == RelationshipTypes.thread) { - return false; - } - return event.isVisibleInGui || event.eventId == exceptionEventId; - }, - ).toList(); + }) => where((event) { + if (threadId != null && + event.relationshipType != RelationshipTypes.reaction) { + if ((event.relationshipType != RelationshipTypes.thread || + event.relationshipEventId != threadId) && + event.eventId != threadId) { + return false; + } + } else if (event.relationshipType == RelationshipTypes.thread) { + return false; + } + return event.isVisibleInGui || event.eventId == exceptionEventId; + }).toList(); } extension IsStateExtension on Event { bool get isVisibleInGui => // always filter out edit and reaction relationships - !{RelationshipTypes.edit, RelationshipTypes.reaction} - .contains(relationshipType) && + !{ + RelationshipTypes.edit, + RelationshipTypes.reaction, + }.contains(relationshipType) && // always filter out m.key.* and other known but unimportant events !isKnownHiddenStates && // event types to hide: redaction and reaction events @@ -40,22 +39,20 @@ extension IsStateExtension on Event { (!AppSettings.hideUnknownEvents.value || isEventTypeKnown); bool get isState => !{ - EventTypes.Message, - EventTypes.Sticker, - EventTypes.Encrypted, - }.contains(type); + EventTypes.Message, + EventTypes.Sticker, + EventTypes.Encrypted, + }.contains(type); bool get isCollapsedState => !{ - EventTypes.Message, - EventTypes.Sticker, - EventTypes.Encrypted, - EventTypes.RoomCreate, - EventTypes.RoomTombstone, - }.contains(type); + EventTypes.Message, + EventTypes.Sticker, + EventTypes.Encrypted, + EventTypes.RoomCreate, + EventTypes.RoomTombstone, + }.contains(type); bool get isKnownHiddenStates => - { - PollEventContent.responseType, - }.contains(type) || + {PollEventContent.responseType}.contains(type) || type.startsWith('m.key.verification.'); } diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart index 3387fdf38..54b0d453b 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/builder.dart @@ -28,22 +28,19 @@ Future flutterMatrixSdkDatabaseBuilder(String clientName) async { try { // Send error notification: final l10n = await lookupL10n(PlatformDispatcher.instance.locale); - ClientManager.sendInitNotification( - l10n.initAppError, - e.toString(), - ); + ClientManager.sendInitNotification(l10n.initAppError, e.toString()); } catch (e, s) { Logs().e('Unable to send error notification', e, s); } // Try to delete database so that it can created again on next init: database?.delete().catchError( - (e, s) => Logs().wtf( - 'Unable to delete database, after failed construction', - e, - s, - ), - ); + (e, s) => Logs().wtf( + 'Unable to delete database, after failed construction', + e, + s, + ), + ); // Delete database file: if (!kIsWeb) { @@ -77,8 +74,9 @@ Future _constructDatabase(String clientName) async { // fix dlopen for old Android await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions(); // import the SQLite / SQLCipher shared objects / dynamic libraries - final factory = - createDatabaseFactoryFfi(ffiInit: SQfLiteEncryptionHelper.ffiInit); + final factory = createDatabaseFactoryFfi( + ffiInit: SQfLiteEncryptionHelper.ffiInit, + ); // required for [getDatabasesPath] databaseFactory = factory; @@ -90,11 +88,7 @@ Future _constructDatabase(String clientName) async { // to manage SQLite encryption final helper = cipher == null ? null - : SQfLiteEncryptionHelper( - factory: factory, - path: path, - cipher: cipher, - ); + : SQfLiteEncryptionHelper(factory: factory, path: path, cipher: cipher); // check whether the DB is already encrypted and otherwise do so await helper?.ensureDatabaseFileEncrypted(); diff --git a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart index 293053759..a91c79f20 100644 --- a/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart +++ b/lib/utils/matrix_sdk_extensions/flutter_matrix_dart_sdk_database/cipher.dart @@ -25,10 +25,7 @@ Future getDatabaseCipher() async { final list = Uint8List(32); list.setAll(0, Iterable.generate(list.length, (i) => rng.nextInt(256))); final newPassword = base64UrlEncode(list); - await secureStorage.write( - key: _passwordStorageKey, - value: newPassword, - ); + await secureStorage.write(key: _passwordStorageKey, value: newPassword); } // workaround for if we just wrote to the key and it still doesn't exist password = await secureStorage.read(key: _passwordStorageKey); diff --git a/lib/utils/matrix_sdk_extensions/matrix_file_extension.dart b/lib/utils/matrix_sdk_extensions/matrix_file_extension.dart index 09e5d5ded..dffea0c63 100644 --- a/lib/utils/matrix_sdk_extensions/matrix_file_extension.dart +++ b/lib/utils/matrix_sdk_extensions/matrix_file_extension.dart @@ -39,8 +39,9 @@ extension MatrixFileExtension on MatrixFile { await SharePlus.instance.share( ShareParams( files: [XFile.fromData(bytes, name: name, mimeType: mimeType)], - sharePositionOrigin: - box == null ? null : box.localToGlobal(Offset.zero) & box.size, + sharePositionOrigin: box == null + ? null + : box.localToGlobal(Offset.zero) & box.size, ), ); return; diff --git a/lib/utils/matrix_sdk_extensions/matrix_locals.dart b/lib/utils/matrix_sdk_extensions/matrix_locals.dart index 11f09a9ab..4f818d533 100644 --- a/lib/utils/matrix_sdk_extensions/matrix_locals.dart +++ b/lib/utils/matrix_sdk_extensions/matrix_locals.dart @@ -353,13 +353,15 @@ class MatrixLocals extends MatrixLocalizations { String get cancelledSend => l10n.sendCanceled; @override - String voiceMessage(String senderName, Duration? duration) => - l10n.sentVoiceMessage( - senderName, - duration == null - ? '' - : '${duration.inMinutes.toString().padLeft(2, '0')}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}', - ); + String voiceMessage( + String senderName, + Duration? duration, + ) => l10n.sentVoiceMessage( + senderName, + duration == null + ? '' + : '${duration.inMinutes.toString().padLeft(2, '0')}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}', + ); @override String get refreshingLastEvent => l10n.loadingPleaseWait; diff --git a/lib/utils/notification_background_handler.dart b/lib/utils/notification_background_handler.dart index 1a694615a..eaaeb7c67 100644 --- a/lib/utils/notification_background_handler.dart +++ b/lib/utils/notification_background_handler.dart @@ -21,19 +21,20 @@ bool _vodInitialized = false; extension NotificationResponseJson on NotificationResponse { String toJsonString() => jsonEncode({ - 'type': notificationResponseType.name, - 'id': id, - 'actionId': actionId, - 'input': input, - 'payload': payload, - 'data': data, - }); + 'type': notificationResponseType.name, + 'id': id, + 'actionId': actionId, + 'input': input, + 'payload': payload, + 'data': data, + }); static NotificationResponse fromJsonString(String jsonString) { final json = jsonDecode(jsonString) as Map; return NotificationResponse( - notificationResponseType: NotificationResponseType.values - .singleWhere((t) => t.name == json['type']), + notificationResponseType: NotificationResponseType.values.singleWhere( + (t) => t.name == json['type'], + ), id: json['id'] as int?, actionId: json['actionId'] as String?, input: json['input'] as String?, @@ -55,8 +56,9 @@ Future waitForPushIsolateDone() async { void notificationTapBackground( NotificationResponse notificationResponse, ) async { - final sendPort = - IsolateNameServer.lookupPortByName(AppConfig.mainIsolatePortName); + final sendPort = IsolateNameServer.lookupPortByName( + AppConfig.mainIsolatePortName, + ); if (sendPort != null) { sendPort.send(notificationResponse.toJsonString()); Logs().i('Notification tap sent to main isolate!'); @@ -80,8 +82,7 @@ void notificationTapBackground( final client = (await ClientManager.getClients( initialize: false, store: store, - )) - .first; + )).first; await client.abortSync(); await client.init( waitForFirstSync: false, @@ -111,8 +112,9 @@ Future notificationTap( 'Notification action handler started', notificationResponse.notificationResponseType.name, ); - final payload = - FluffyChatPushPayload.fromString(notificationResponse.payload ?? ''); + final payload = FluffyChatPushPayload.fromString( + notificationResponse.payload ?? '', + ); switch (notificationResponse.notificationResponseType) { case NotificationResponseType.selectedNotification: final roomId = payload.roomId; @@ -182,16 +184,16 @@ Future notificationTap( final avatarFile = avatar == null ? null : await client - .downloadMxcCached( - avatar, - thumbnailMethod: ThumbnailMethod.crop, - width: notificationAvatarDimension, - height: notificationAvatarDimension, - animated: false, - isThumbnail: true, - rounded: true, - ) - .timeout(const Duration(seconds: 3)); + .downloadMxcCached( + avatar, + thumbnailMethod: ThumbnailMethod.crop, + width: notificationAvatarDimension, + height: notificationAvatarDimension, + animated: false, + isThumbnail: true, + rounded: true, + ) + .timeout(const Duration(seconds: 3)); final messagingStyleInformation = await AndroidFlutterLocalNotificationsPlugin() .getActiveNotificationMessagingStyle(room.id.hashCode); diff --git a/lib/utils/push_helper.dart b/lib/utils/push_helper.dart index 0aa60418f..6c9f9338f 100644 --- a/lib/utils/push_helper.dart +++ b/lib/utils/push_helper.dart @@ -89,8 +89,7 @@ Future _tryPushHelper( client ??= (await ClientManager.getClients( initialize: false, store: await AppSettings.init(), - )) - .first; + )).first; final event = await client.getEventByPushNotification( notification, storeInDatabase: false, @@ -105,8 +104,8 @@ Future _tryPushHelper( // Make sure client is fully loaded and synced before dismiss notifications: await client.roomsLoading; await client.oneShotSync(); - final activeNotifications = - await flutterLocalNotificationsPlugin.getActiveNotifications(); + final activeNotifications = await flutterLocalNotificationsPlugin + .getActiveNotifications(); for (final activeNotification in activeNotifications) { final room = client.rooms.singleWhereOrNull( (room) => room.id.hashCode == activeNotification.id, @@ -168,16 +167,16 @@ Future _tryPushHelper( roomAvatarFile = avatar == null ? null : await client - .downloadMxcCached( - avatar, - thumbnailMethod: ThumbnailMethod.crop, - width: notificationAvatarDimension, - height: notificationAvatarDimension, - animated: false, - isThumbnail: true, - rounded: true, - ) - .timeout(const Duration(seconds: 3)); + .downloadMxcCached( + avatar, + thumbnailMethod: ThumbnailMethod.crop, + width: notificationAvatarDimension, + height: notificationAvatarDimension, + animated: false, + isThumbnail: true, + rounded: true, + ) + .timeout(const Duration(seconds: 3)); } catch (e, s) { Logs().e('Unable to get avatar picture', e, s); } @@ -185,18 +184,18 @@ Future _tryPushHelper( senderAvatarFile = event.room.isDirectChat ? roomAvatarFile : senderAvatar == null - ? null - : await client - .downloadMxcCached( - senderAvatar, - thumbnailMethod: ThumbnailMethod.crop, - width: notificationAvatarDimension, - height: notificationAvatarDimension, - animated: false, - isThumbnail: true, - rounded: true, - ) - .timeout(const Duration(seconds: 3)); + ? null + : await client + .downloadMxcCached( + senderAvatar, + thumbnailMethod: ThumbnailMethod.crop, + width: notificationAvatarDimension, + height: notificationAvatarDimension, + animated: false, + isThumbnail: true, + rounded: true, + ) + .timeout(const Duration(seconds: 3)); } catch (e, s) { Logs().e('Unable to get avatar picture', e, s); } @@ -221,14 +220,15 @@ Future _tryPushHelper( final messagingStyleInformation = PlatformInfos.isAndroid ? await AndroidFlutterLocalNotificationsPlugin() - .getActiveNotificationMessagingStyle(id) + .getActiveNotificationMessagingStyle(id) : null; messagingStyleInformation?.messages?.add(newMessage); final roomName = event.room.getLocalizedDisplayname(MatrixLocals(l10n)); - final notificationGroupId = - event.room.isDirectChat ? 'directChats' : 'groupChats'; + final notificationGroupId = event.room.isDirectChat + ? 'directChats' + : 'groupChats'; final groupName = event.room.isDirectChat ? l10n.directChats : l10n.groups; final messageRooms = AndroidNotificationChannelGroup( @@ -243,11 +243,13 @@ Future _tryPushHelper( await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() + AndroidFlutterLocalNotificationsPlugin + >() ?.createNotificationChannelGroup(messageRooms); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>() + AndroidFlutterLocalNotificationsPlugin + >() ?.createNotificationChannel(roomsChannel); final androidPlatformChannelSpecifics = AndroidNotificationDetails( @@ -256,7 +258,8 @@ Future _tryPushHelper( number: notification.counts?.unread, category: AndroidNotificationCategory.message, shortcutId: event.room.id, - styleInformation: messagingStyleInformation ?? + styleInformation: + messagingStyleInformation ?? MessagingStyleInformation( Person( name: senderName, @@ -288,9 +291,7 @@ Future _tryPushHelper( FluffyChatNotificationActions.reply.name, l10n.reply, inputs: [ - AndroidNotificationActionInput( - label: l10n.writeAMessage, - ), + AndroidNotificationActionInput(label: l10n.writeAMessage), ], cancelNotification: false, allowGeneratedReplies: true, @@ -320,9 +321,11 @@ Future _tryPushHelper( title, body, platformChannelSpecifics, - payload: - FluffyChatPushPayload(client.clientName, event.room.id, event.eventId) - .toString(), + payload: FluffyChatPushPayload( + client.clientName, + event.room.id, + event.eventId, + ).toString(), ); Logs().v('Push helper has been completed!'); } diff --git a/lib/utils/resize_video.dart b/lib/utils/resize_video.dart index 99a4c6b0a..ae249818e 100644 --- a/lib/utils/resize_video.dart +++ b/lib/utils/resize_video.dart @@ -39,10 +39,7 @@ extension ResizeImage on XFile { try { final bytes = await VideoCompress.getByteThumbnail(path); if (bytes == null) return null; - return MatrixImageFile( - bytes: bytes, - name: name, - ); + return MatrixImageFile(bytes: bytes, name: name); } catch (e, s) { Logs().w('Error while compressing video', e, s); } diff --git a/lib/utils/room_status_extension.dart b/lib/utils/room_status_extension.dart index 7c978064b..3021a3147 100644 --- a/lib/utils/room_status_extension.dart +++ b/lib/utils/room_status_extension.dart @@ -19,8 +19,9 @@ extension RoomStatusExtension on Room { } else if (typingUsers.length == 1) { typingText = L10n.of(context).isTyping; if (typingUsers.first.id != directChatMatrixID) { - typingText = - L10n.of(context).userIsTyping(typingUsers.first.calcDisplayname()); + typingText = L10n.of( + context, + ).userIsTyping(typingUsers.first.calcDisplayname()); } } else if (typingUsers.length == 2) { typingText = L10n.of(context).userAndUserAreTyping( diff --git a/lib/utils/show_scaffold_dialog.dart b/lib/utils/show_scaffold_dialog.dart index 9a0a0c610..7e552f90d 100644 --- a/lib/utils/show_scaffold_dialog.dart +++ b/lib/utils/show_scaffold_dialog.dart @@ -10,28 +10,25 @@ Future showScaffoldDialog({ double maxWidth = 480, double maxHeight = 720, required Widget Function(BuildContext context) builder, -}) => - showDialog( - context: context, - useSafeArea: false, - builder: FluffyThemes.isColumnMode(context) - ? (context) => Center( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - color: containerColor ?? - Theme.of(context).scaffoldBackgroundColor, - ), - clipBehavior: Clip.hardEdge, - margin: const EdgeInsets.all(16), - constraints: BoxConstraints( - maxWidth: maxWidth, - maxHeight: maxHeight, - ), - child: builder(context), - ), - ) - : builder, - ); +}) => showDialog( + context: context, + useSafeArea: false, + builder: FluffyThemes.isColumnMode(context) + ? (context) => Center( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(AppConfig.borderRadius), + color: + containerColor ?? Theme.of(context).scaffoldBackgroundColor, + ), + clipBehavior: Clip.hardEdge, + margin: const EdgeInsets.all(16), + constraints: BoxConstraints( + maxWidth: maxWidth, + maxHeight: maxHeight, + ), + child: builder(context), + ), + ) + : builder, +); diff --git a/lib/utils/sync_status_localization.dart b/lib/utils/sync_status_localization.dart index 6d3a10311..c48e71252 100644 --- a/lib/utils/sync_status_localization.dart +++ b/lib/utils/sync_status_localization.dart @@ -12,8 +12,9 @@ extension SyncStatusLocalization on SyncStatusUpdate { case SyncStatus.waitingForResponse: return L10n.of(context).waitingForServer; case SyncStatus.error: - return ((error?.exception ?? Object()) as Object) - .toLocalizedString(context); + return ((error?.exception ?? Object()) as Object).toLocalizedString( + context, + ); case SyncStatus.processing: case SyncStatus.cleaningUp: case SyncStatus.finished: diff --git a/lib/utils/uia_request_manager.dart b/lib/utils/uia_request_manager.dart index 4a2736e1c..34a51b1cf 100644 --- a/lib/utils/uia_request_manager.dart +++ b/lib/utils/uia_request_manager.dart @@ -16,7 +16,7 @@ extension UiaRequestManager on MatrixState { final l10n = L10n.of(context); final navigatorContext = FluffyChatApp.router.routerDelegate.navigatorKey.currentContext ?? - context; + context; try { if (uiaRequest.state != UiaRequestState.waitForUser || uiaRequest.nextStages.isEmpty) { @@ -27,7 +27,8 @@ extension UiaRequestManager on MatrixState { Logs().d('Uia Request Stage: $stage'); switch (stage) { case AuthenticationTypes.password: - final input = cachedPassword ?? + final input = + cachedPassword ?? (await showTextInputDialog( context: navigatorContext, title: l10n.pleaseEnterYourPassword, @@ -87,9 +88,7 @@ extension UiaRequestManager on MatrixState { ?.tryGet('url'); final fallbackUrl = client.homeserver!.replace( path: '/_matrix/client/v3/auth/$stage/fallback/web', - queryParameters: { - 'session': uiaRequest.session, - }, + queryParameters: {'session': uiaRequest.session}, ); final url = stageUrl != null ? (Uri.tryParse(stageUrl) ?? fallbackUrl) @@ -106,8 +105,9 @@ extension UiaRequestManager on MatrixState { launchUrl(url, mode: LaunchMode.inAppBrowserView); final completer = Completer(); - final listener = - AppLifecycleListener(onResume: () => completer.complete()); + final listener = AppLifecycleListener( + onResume: () => completer.complete(), + ); await completer.future; listener.dispose(); diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart index e4e9b1b3b..45c93e1b2 100644 --- a/lib/utils/url_launcher.dart +++ b/lib/utils/url_launcher.dart @@ -99,13 +99,16 @@ class UrlLauncher { // okay, we have either an http or an https URI. // As some platforms have issues with opening unicode URLs, we are going to help // them out by punycode-encoding them for them ourself. - final newHost = uri.host.split('.').map((hostPartEncoded) { - final hostPart = Uri.decodeComponent(hostPartEncoded); - final hostPartPunycode = punycodeEncode(hostPart); - return hostPartPunycode != '$hostPart-' - ? 'xn--$hostPartPunycode' - : hostPart; - }).join('.'); + final newHost = uri.host + .split('.') + .map((hostPartEncoded) { + final hostPart = Uri.decodeComponent(hostPartEncoded); + final hostPartPunycode = punycodeEncode(hostPart); + return hostPartPunycode != '$hostPart-' + ? 'xn--$hostPartPunycode' + : hostPart; + }) + .join('.'); // Force LaunchMode.externalApplication, otherwise url_launcher will default // to opening links in a webview on mobile platforms. launchUrlString( @@ -117,17 +120,17 @@ class UrlLauncher { void openMatrixToUrl() async { final matrix = Matrix.of(context); final url = this.url!.replaceFirst( - AppConfig.deepLinkPrefix, - AppConfig.inviteLinkPrefix, - ); + AppConfig.deepLinkPrefix, + AppConfig.inviteLinkPrefix, + ); // The identifier might be a matrix.to url and needs escaping. Or, it might have multiple // identifiers (room id & event id), or it might also have a query part. // All this needs parsing. - final identityParts = url.parseIdentifierIntoParts() ?? + final identityParts = + url.parseIdentifierIntoParts() ?? Uri.tryParse(url)?.host.parseIdentifierIntoParts() ?? - Uri.tryParse(url) - ?.pathSegments + Uri.tryParse(url)?.pathSegments .lastWhereOrNull((_) => true) ?.parseIdentifierIntoParts(); if (identityParts == null) { @@ -138,7 +141,8 @@ class UrlLauncher { // we got a room! Let's open that one final roomIdOrAlias = identityParts.primaryIdentifier; final event = identityParts.secondaryIdentifier; - var room = matrix.client.getRoomByAlias(roomIdOrAlias) ?? + var room = + matrix.client.getRoomByAlias(roomIdOrAlias) ?? matrix.client.getRoomById(roomIdOrAlias); var roomId = room?.id; // we make the servers a set and later on convert to a list, so that we can easily @@ -168,10 +172,7 @@ class UrlLauncher { // we have the room, so....just open it if (event != null) { context.go( - '/${Uri( - pathSegments: ['rooms', room.id], - queryParameters: {'event': event}, - )}', + '/${Uri(pathSegments: ['rooms', room.id], queryParameters: {'event': event})}', ); } else { context.go('/rooms/${room.id}'); @@ -180,9 +181,8 @@ class UrlLauncher { } else { await showAdaptiveDialog( context: context, - builder: (c) => PublicRoomDialog( - roomAlias: identityParts.primaryIdentifier, - ), + builder: (c) => + PublicRoomDialog(roomAlias: identityParts.primaryIdentifier), ); } if (roomIdOrAlias.sigil == '!') { @@ -223,12 +223,11 @@ class UrlLauncher { var noProfileWarning = false; final profileResult = await showFutureLoadingDialog( context: context, - future: () => matrix.client.getProfileFromUserId(userId).catchError( - (_) { - noProfileWarning = true; - return Profile(userId: userId); - }, - ), + future: () => + matrix.client.getProfileFromUserId(userId).catchError((_) { + noProfileWarning = true; + return Profile(userId: userId); + }), ); await UserDialog.show( context: context, diff --git a/lib/utils/voip/video_renderer.dart b/lib/utils/voip/video_renderer.dart index afdd9be2e..935b3984c 100644 --- a/lib/utils/voip/video_renderer.dart +++ b/lib/utils/voip/video_renderer.dart @@ -45,8 +45,9 @@ class _VideoRendererState extends State { @override void initState() { - _streamChangeSubscription = - widget.stream?.onStreamChanged.stream.listen((stream) { + _streamChangeSubscription = widget.stream?.onStreamChanged.stream.listen(( + stream, + ) { setState(() { _renderer?.srcObject = stream; }); diff --git a/lib/utils/voip_plugin.dart b/lib/utils/voip_plugin.dart index c5120d604..adef19dd6 100644 --- a/lib/utils/voip_plugin.dart +++ b/lib/utils/voip_plugin.dart @@ -33,13 +33,15 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate { @override void didChangeAppLifecycleState(AppLifecycleState? state) { - background = (state == AppLifecycleState.detached || + background = + (state == AppLifecycleState.detached || state == AppLifecycleState.paused); } void addCallingOverlay(String callId, CallSession call) { - final context = - kIsWeb ? ChatList.contextForVoip! : this.context; // web is weird + final context = kIsWeb + ? ChatList.contextForVoip! + : this.context; // web is weird if (overlayEntry != null) { Logs().e('[VOIP] addCallingOverlay: The call session already exists?'); @@ -85,8 +87,7 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate { Future createPeerConnection( Map configuration, [ Map constraints = const {}, - ]) => - webrtc_impl.createPeerConnection(configuration, constraints); + ]) => webrtc_impl.createPeerConnection(configuration, constraints); Future get hasCallingAccount async => false; diff --git a/lib/widgets/adaptive_dialogs/adaptive_dialog_action.dart b/lib/widgets/adaptive_dialogs/adaptive_dialog_action.dart index 4a1929dd1..40fc3f96d 100644 --- a/lib/widgets/adaptive_dialogs/adaptive_dialog_action.dart +++ b/lib/widgets/adaptive_dialogs/adaptive_dialog_action.dart @@ -49,7 +49,8 @@ class AdaptiveDialogAction extends StatelessWidget { child: ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( - borderRadius: borderRadius ?? + borderRadius: + borderRadius ?? BorderRadius.circular(AppConfig.borderRadius), ), backgroundColor: autofocus diff --git a/lib/widgets/adaptive_dialogs/dialog_text_field.dart b/lib/widgets/adaptive_dialogs/dialog_text_field.dart index 73d96ed9d..4870882da 100644 --- a/lib/widgets/adaptive_dialogs/dialog_text_field.dart +++ b/lib/widgets/adaptive_dialogs/dialog_text_field.dart @@ -86,10 +86,7 @@ class DialogTextField extends StatelessWidget { if (errorText != null) Text( errorText, - style: TextStyle( - fontSize: 11, - color: theme.colorScheme.error, - ), + style: TextStyle(fontSize: 11, color: theme.colorScheme.error), textAlign: TextAlign.left, ), ], diff --git a/lib/widgets/adaptive_dialogs/public_room_dialog.dart b/lib/widgets/adaptive_dialogs/public_room_dialog.dart index 6b11d45c9..7fee87bfb 100644 --- a/lib/widgets/adaptive_dialogs/public_room_dialog.dart +++ b/lib/widgets/adaptive_dialogs/public_room_dialog.dart @@ -37,10 +37,7 @@ class PublicRoomDialog extends StatelessWidget { } final roomId = chunk != null && knock ? await client.knockRoom(chunk.roomId, via: via) - : await client.joinRoom( - roomAlias ?? chunk!.roomId, - via: via, - ); + : await client.joinRoom(roomAlias ?? chunk!.roomId, via: via); if (!knock && client.getRoomById(roomId) == null) { await client.waitForRoomInSync(roomId); @@ -78,11 +75,9 @@ class PublicRoomDialog extends StatelessWidget { final chunk = this.chunk; if (chunk != null) return chunk; final query = await Matrix.of(context).client.queryPublicRooms( - server: roomAlias!.domain, - filter: PublicRoomQueryFilter( - genericSearchTerm: roomAlias, - ), - ); + server: roomAlias!.domain, + filter: PublicRoomQueryFilter(genericSearchTerm: roomAlias), + ); if (!query.chunk.any(_testRoom)) { throw (L10n.of(context).noRoomsFound); } @@ -115,8 +110,8 @@ class PublicRoomDialog extends StatelessWidget { return SingleChildScrollView( child: Column( spacing: 8, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: .min, + crossAxisAlignment: .stretch, children: [ if (roomLink != null) HoverBuilder( @@ -125,9 +120,7 @@ class PublicRoomDialog extends StatelessWidget { cursor: SystemMouseCursors.click, child: GestureDetector( onTap: () { - Clipboard.setData( - ClipboardData(text: roomLink), - ); + Clipboard.setData(ClipboardData(text: roomLink)); setState(() { copied = true; }); @@ -137,8 +130,9 @@ class PublicRoomDialog extends StatelessWidget { children: [ WidgetSpan( child: Padding( - padding: - const EdgeInsets.only(right: 4.0), + padding: const EdgeInsets.only( + right: 4.0, + ), child: AnimatedScale( duration: FluffyThemes.animationDuration, @@ -146,8 +140,8 @@ class PublicRoomDialog extends StatelessWidget { scale: hovered ? 1.33 : copied - ? 1.25 - : 1.0, + ? 1.25 + : 1.0, child: Icon( copied ? Icons.check_circle @@ -160,8 +154,9 @@ class PublicRoomDialog extends StatelessWidget { ), TextSpan(text: roomLink), ], - style: theme.textTheme.bodyMedium - ?.copyWith(fontSize: 10), + style: theme.textTheme.bodyMedium?.copyWith( + fontSize: 10, + ), ), textAlign: TextAlign.center, ), @@ -176,25 +171,26 @@ class PublicRoomDialog extends StatelessWidget { size: Avatar.defaultSize * 2, onTap: avatar != null ? () => showDialog( - context: context, - builder: (_) => MxcImageViewer(avatar), - ) + context: context, + builder: (_) => MxcImageViewer(avatar), + ) : null, ), ), if (profile?.numJoinedMembers != null) Text( - L10n.of(context).countParticipants( - profile?.numJoinedMembers ?? 0, - ), + L10n.of( + context, + ).countParticipants(profile?.numJoinedMembers ?? 0), style: const TextStyle(fontSize: 10), textAlign: TextAlign.center, ), if (topic != null && topic.isNotEmpty) SelectableLinkify( text: topic, - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), textAlign: TextAlign.center, options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( @@ -221,8 +217,8 @@ class PublicRoomDialog extends StatelessWidget { Matrix.of(context).client.getRoomById(chunk!.roomId) == null ? L10n.of(context).knock : chunk?.roomType == 'm.space' - ? L10n.of(context).joinSpace - : L10n.of(context).joinRoom, + ? L10n.of(context).joinSpace + : L10n.of(context).joinRoom, ), ), AdaptiveDialogAction( diff --git a/lib/widgets/adaptive_dialogs/show_modal_action_popup.dart b/lib/widgets/adaptive_dialogs/show_modal_action_popup.dart index 47db330f1..f99e69353 100644 --- a/lib/widgets/adaptive_dialogs/show_modal_action_popup.dart +++ b/lib/widgets/adaptive_dialogs/show_modal_action_popup.dart @@ -32,10 +32,7 @@ Future showModalActionPopup({ ListTile( title: title == null ? null - : Text( - title, - style: theme.textTheme.labelSmall, - ), + : Text(title, style: theme.textTheme.labelSmall), subtitle: message == null ? null : Text(message), ), const Divider(height: 1), @@ -49,8 +46,9 @@ Future showModalActionPopup({ style: action.isDestructive ? TextStyle( color: theme.colorScheme.error, - fontWeight: - action.isDefaultAction ? FontWeight.bold : null, + fontWeight: action.isDefaultAction + ? FontWeight.bold + : null, ) : null, ), diff --git a/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart b/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart index 542bdb7a0..3b6c72684 100644 --- a/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart +++ b/lib/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart @@ -16,50 +16,49 @@ Future showOkCancelAlertDialog({ String? cancelLabel, bool isDestructive = false, bool useRootNavigator = true, -}) => - showAdaptiveDialog( - context: context, - useRootNavigator: useRootNavigator, - builder: (context) => AlertDialog.adaptive( - title: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), - child: Text(title), - ), - content: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), - child: message == null - ? null - : SelectableLinkify( - text: message, - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - linkStyle: TextStyle( - color: Theme.of(context).colorScheme.primary, - decorationColor: Theme.of(context).colorScheme.primary, - ), - options: const LinkifyOptions(humanize: false), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), - ), - ), - actions: [ - AdaptiveDialogAction( - onPressed: () => Navigator.of(context) - .pop(OkCancelResult.cancel), - child: Text(cancelLabel ?? L10n.of(context).cancel), - ), - AdaptiveDialogAction( - onPressed: () => - Navigator.of(context).pop(OkCancelResult.ok), - autofocus: true, - child: Text( - okLabel ?? L10n.of(context).ok, - style: isDestructive - ? TextStyle(color: Theme.of(context).colorScheme.error) - : null, +}) => showAdaptiveDialog( + context: context, + useRootNavigator: useRootNavigator, + builder: (context) => AlertDialog.adaptive( + title: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 256), + child: Text(title), + ), + content: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 256), + child: message == null + ? null + : SelectableLinkify( + text: message, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + linkStyle: TextStyle( + color: Theme.of(context).colorScheme.primary, + decorationColor: Theme.of(context).colorScheme.primary, + ), + options: const LinkifyOptions(humanize: false), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), ), - ), - ], + ), + actions: [ + AdaptiveDialogAction( + onPressed: () => + Navigator.of(context).pop(OkCancelResult.cancel), + child: Text(cancelLabel ?? L10n.of(context).cancel), ), - ); + AdaptiveDialogAction( + onPressed: () => + Navigator.of(context).pop(OkCancelResult.ok), + autofocus: true, + child: Text( + okLabel ?? L10n.of(context).ok, + style: isDestructive + ? TextStyle(color: Theme.of(context).colorScheme.error) + : null, + ), + ), + ], + ), +); Future showOkAlertDialog({ required BuildContext context, @@ -67,37 +66,36 @@ Future showOkAlertDialog({ String? message, String? okLabel, bool useRootNavigator = true, -}) => - showAdaptiveDialog( - context: context, - useRootNavigator: useRootNavigator, - builder: (context) => AlertDialog.adaptive( - title: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), - child: Text(title), - ), - content: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 256), - child: message == null - ? null - : SelectableLinkify( - text: message, - textScaleFactor: MediaQuery.textScalerOf(context).scale(1), - linkStyle: TextStyle( - color: Theme.of(context).colorScheme.primary, - decorationColor: Theme.of(context).colorScheme.primary, - ), - options: const LinkifyOptions(humanize: false), - onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), - ), - ), - actions: [ - AdaptiveDialogAction( - onPressed: () => - Navigator.of(context).pop(OkCancelResult.ok), - autofocus: true, - child: Text(okLabel ?? L10n.of(context).close), - ), - ], +}) => showAdaptiveDialog( + context: context, + useRootNavigator: useRootNavigator, + builder: (context) => AlertDialog.adaptive( + title: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 256), + child: Text(title), + ), + content: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 256), + child: message == null + ? null + : SelectableLinkify( + text: message, + textScaleFactor: MediaQuery.textScalerOf(context).scale(1), + linkStyle: TextStyle( + color: Theme.of(context).colorScheme.primary, + decorationColor: Theme.of(context).colorScheme.primary, + ), + options: const LinkifyOptions(humanize: false), + onOpen: (url) => UrlLauncher(context, url.url).launchUrl(), + ), + ), + actions: [ + AdaptiveDialogAction( + onPressed: () => + Navigator.of(context).pop(OkCancelResult.ok), + autofocus: true, + child: Text(okLabel ?? L10n.of(context).close), ), - ); + ], + ), +); diff --git a/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart b/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart index 77806ab47..38331eafc 100644 --- a/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart +++ b/lib/widgets/adaptive_dialogs/show_text_input_dialog.dart @@ -42,7 +42,7 @@ Future showTextInputDialog({ content: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 256), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ if (message != null) SelectableLinkify( diff --git a/lib/widgets/adaptive_dialogs/user_dialog.dart b/lib/widgets/adaptive_dialogs/user_dialog.dart index e3a07c7fb..503615197 100644 --- a/lib/widgets/adaptive_dialogs/user_dialog.dart +++ b/lib/widgets/adaptive_dialogs/user_dialog.dart @@ -22,15 +22,12 @@ class UserDialog extends StatelessWidget { required BuildContext context, required Profile profile, bool noProfileWarning = false, - }) => - showAdaptiveDialog( - context: context, - barrierDismissible: true, - builder: (context) => UserDialog( - profile, - noProfileWarning: noProfileWarning, - ), - ); + }) => showAdaptiveDialog( + context: context, + barrierDismissible: true, + builder: (context) => + UserDialog(profile, noProfileWarning: noProfileWarning), + ); final Profile profile; final bool noProfileWarning; @@ -41,7 +38,8 @@ class UserDialog extends StatelessWidget { Widget build(BuildContext context) { final client = Matrix.of(context).client; final dmRoomId = client.getDirectChatFromUserId(profile.userId); - final displayname = profile.displayName ?? + final displayname = + profile.displayName ?? profile.userId.localpart ?? L10n.of(context).user; var copied = false; @@ -64,15 +62,15 @@ class UserDialog extends StatelessWidget { final presenceText = presence.currentlyActive == true ? L10n.of(context).currentlyActive : lastActiveTimestamp != null - ? L10n.of(context).lastActiveAgo( - lastActiveTimestamp.localizedTimeShort(context), - ) - : null; + ? L10n.of(context).lastActiveAgo( + lastActiveTimestamp.localizedTimeShort(context), + ) + : null; return SingleChildScrollView( child: Column( spacing: 8, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: .min, + crossAxisAlignment: .stretch, children: [ Center( child: Avatar( @@ -81,9 +79,9 @@ class UserDialog extends StatelessWidget { size: Avatar.defaultSize * 2, onTap: avatar != null ? () => showDialog( - context: context, - builder: (_) => MxcImageViewer(avatar), - ) + context: context, + builder: (_) => MxcImageViewer(avatar), + ) : null, ), ), @@ -112,8 +110,8 @@ class UserDialog extends StatelessWidget { scale: hovered ? 1.33 : copied - ? 1.25 - : 1.0, + ? 1.25 + : 1.0, child: Icon( copied ? Icons.check_circle @@ -126,8 +124,9 @@ class UserDialog extends StatelessWidget { ), TextSpan(text: profile.userId), ], - style: theme.textTheme.bodyMedium - ?.copyWith(fontSize: 10), + style: theme.textTheme.bodyMedium?.copyWith( + fontSize: 10, + ), ), textAlign: TextAlign.center, ), @@ -144,8 +143,9 @@ class UserDialog extends StatelessWidget { if (statusMsg != null) SelectableLinkify( text: statusMsg, - textScaleFactor: - MediaQuery.textScalerOf(context).scale(1), + textScaleFactor: MediaQuery.textScalerOf( + context, + ).scale(1), textAlign: TextAlign.center, options: const LinkifyOptions(humanize: false), linkStyle: TextStyle( diff --git a/lib/widgets/app_lock.dart b/lib/widgets/app_lock.dart index ff379c5d8..a8b933011 100644 --- a/lib/widgets/app_lock.dart +++ b/lib/widgets/app_lock.dart @@ -82,8 +82,8 @@ class AppLock extends State with WidgetsBindingObserver { } void showLockScreen() => setState(() { - _isLocked = true; - }); + _isLocked = true; + }); Future pauseWhile(Future future) async { _paused = true; @@ -94,20 +94,15 @@ class AppLock extends State with WidgetsBindingObserver { } } - static AppLock of(BuildContext context) => Provider.of( - context, - listen: false, - ); + static AppLock of(BuildContext context) => + Provider.of(context, listen: false); @override Widget build(BuildContext context) => Provider( - create: (_) => this, - child: Stack( - fit: StackFit.expand, - children: [ - widget.child, - if (isLocked) const LockScreen(), - ], - ), - ); + create: (_) => this, + child: Stack( + fit: StackFit.expand, + children: [widget.child, if (isLocked) const LockScreen()], + ), + ); } diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index fdecdb5d7..b1e9637c7 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -42,10 +42,12 @@ class Avatar extends StatelessWidget { final theme = Theme.of(context); final name = this.name; - final fallbackLetters = - name == null || name.isEmpty ? '@' : name.substring(0, 1); + final fallbackLetters = name == null || name.isEmpty + ? '@' + : name.substring(0, 1); - final noPic = mxContent == null || + final noPic = + mxContent == null || mxContent.toString().isEmpty || mxContent.toString() == 'null'; final borderRadius = this.borderRadius ?? BorderRadius.circular(size / 2); @@ -113,8 +115,8 @@ class Avatar extends StatelessWidget { final dotColor = presence.presence.isOnline ? Colors.green : presence.presence.isUnavailable - ? Colors.orange - : Colors.grey; + ? Colors.orange + : Colors.grey; return Positioned( bottom: -3, right: -3, @@ -147,10 +149,7 @@ class Avatar extends StatelessWidget { if (onTap == null) return container; return MouseRegion( cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: onTap, - child: container, - ), + child: GestureDetector(onTap: onTap, child: container), ); } } diff --git a/lib/widgets/avatar_page_header.dart b/lib/widgets/avatar_page_header.dart index e00eca90e..bff0d3881 100644 --- a/lib/widgets/avatar_page_header.dart +++ b/lib/widgets/avatar_page_header.dart @@ -25,8 +25,8 @@ class AvatarPageHeader extends StatelessWidget { child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: FluffyThemes.columnWidth), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: .min, + crossAxisAlignment: .center, spacing: 8.0, children: [ Stack( @@ -58,7 +58,7 @@ class AvatarPageHeader extends StatelessWidget { child: LayoutBuilder( builder: (context, constraints) { return Row( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: .center, children: [ ConstrainedBox( constraints: BoxConstraints( @@ -87,7 +87,7 @@ class AvatarPageHeader extends StatelessWidget { ), ), child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisAlignment: .spaceEvenly, children: iconButtons, ), ), diff --git a/lib/widgets/blur_hash.dart b/lib/widgets/blur_hash.dart index d4ad1dd47..a7fc4fac0 100644 --- a/lib/widgets/blur_hash.dart +++ b/lib/widgets/blur_hash.dart @@ -25,9 +25,7 @@ class BlurHash extends StatefulWidget { class _BlurHashState extends State { Uint8List? _data; - static Future getBlurhashData( - BlurhashData blurhashData, - ) async { + static Future getBlurhashData(BlurhashData blurhashData) async { final blurhash = b.BlurHash.decode(blurhashData.hsh); final img = blurhash.toImage(blurhashData.w, blurhashData.h); return Uint8List.fromList(image.encodePng(img)); @@ -46,11 +44,7 @@ class _BlurHashState extends State { return _data ??= await compute( getBlurhashData, - BlurhashData( - hsh: widget.blurhash, - w: width, - h: height, - ), + BlurhashData(hsh: widget.blurhash, w: width, h: height), ); } @@ -84,21 +78,10 @@ class BlurhashData { final int w; final int h; - const BlurhashData({ - required this.hsh, - required this.w, - required this.h, - }); + const BlurhashData({required this.hsh, required this.w, required this.h}); - factory BlurhashData.fromJson(Map json) => BlurhashData( - hsh: json['hsh'], - w: json['w'], - h: json['h'], - ); + factory BlurhashData.fromJson(Map json) => + BlurhashData(hsh: json['hsh'], w: json['w'], h: json['h']); - Map toJson() => { - 'hsh': hsh, - 'w': w, - 'h': h, - }; + Map toJson() => {'hsh': hsh, 'w': w, 'h': h}; } diff --git a/lib/widgets/chat_settings_popup_menu.dart b/lib/widgets/chat_settings_popup_menu.dart index 81123f62f..6e90a6a29 100644 --- a/lib/widgets/chat_settings_popup_menu.dart +++ b/lib/widgets/chat_settings_popup_menu.dart @@ -36,10 +36,7 @@ class ChatSettingsPopupMenuState extends State { @override Widget build(BuildContext context) { - notificationChangeSub ??= Matrix.of(context) - .client - .onSync - .stream + notificationChangeSub ??= Matrix.of(context).client.onSync.stream .where( (syncUpdate) => syncUpdate.accountData?.any( @@ -47,9 +44,7 @@ class ChatSettingsPopupMenuState extends State { ) ?? false, ) - .listen( - (u) => setState(() {}), - ); + .listen((u) => setState(() {})); return Stack( alignment: Alignment.center, children: [ diff --git a/lib/widgets/config_viewer.dart b/lib/widgets/config_viewer.dart index b0537317c..c4c23a338 100644 --- a/lib/widgets/config_viewer.dart +++ b/lib/widgets/config_viewer.dart @@ -53,9 +53,7 @@ class _ConfigViewerState extends State { return Scaffold( appBar: AppBar( title: const Text('Advanced configurations'), - leading: BackButton( - onPressed: () => context.go('/'), - ), + leading: BackButton(onPressed: () => context.go('/')), ), body: Column( children: [ @@ -65,9 +63,7 @@ class _ConfigViewerState extends State { color: theme.colorScheme.errorContainer, child: Text( 'Changing configs by hand is untested! Use without any warranty!', - style: TextStyle( - color: theme.colorScheme.onErrorContainer, - ), + style: TextStyle(color: theme.colorScheme.onErrorContainer), ), ), Expanded( diff --git a/lib/widgets/error_widget.dart b/lib/widgets/error_widget.dart index b14a18b31..7e786d46e 100644 --- a/lib/widgets/error_widget.dart +++ b/lib/widgets/error_widget.dart @@ -21,10 +21,10 @@ class _FluffyChatErrorWidgetState extends State { } knownExceptions.add(widget.details.exception.toString()); WidgetsBinding.instance.addPostFrameCallback((_) { - ErrorReporter(context, 'Error Widget').onErrorCallback( - widget.details.exception, - widget.details.stack, - ); + ErrorReporter( + context, + 'Error Widget', + ).onErrorCallback(widget.details.exception, widget.details.stack); }); } diff --git a/lib/widgets/fluffy_chat_app.dart b/lib/widgets/fluffy_chat_app.dart index 8c37c814d..4a72d07dd 100644 --- a/lib/widgets/fluffy_chat_app.dart +++ b/lib/widgets/fluffy_chat_app.dart @@ -46,8 +46,11 @@ class FluffyChatApp extends StatelessWidget { title: AppSettings.applicationName.value, themeMode: themeMode, theme: FluffyThemes.buildTheme(context, Brightness.light, primaryColor), - darkTheme: - FluffyThemes.buildTheme(context, Brightness.dark, primaryColor), + darkTheme: FluffyThemes.buildTheme( + context, + Brightness.dark, + primaryColor, + ), scrollBehavior: CustomScrollBehavior(), localizationsDelegates: L10n.localizationsDelegates, supportedLocales: L10n.supportedLocales, diff --git a/lib/widgets/future_loading_dialog.dart b/lib/widgets/future_loading_dialog.dart index 7fde990f8..cc6b1b409 100644 --- a/lib/widgets/future_loading_dialog.dart +++ b/lib/widgets/future_loading_dialog.dart @@ -54,10 +54,7 @@ Future> showFutureLoadingDialog({ ), ); return result ?? - Result.error( - Exception('FutureDialog canceled'), - StackTrace.current, - ); + Result.error(Exception('FutureDialog canceled'), StackTrace.current); } class LoadingDialog extends StatefulWidget { @@ -114,15 +111,13 @@ class LoadingDialogState extends State { content: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 256), child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: .center, children: [ if (exception == null) ...[ StreamBuilder( stream: widget.onProgressStream, builder: (context, snapshot) => - CircularProgressIndicator.adaptive( - value: snapshot.data, - ), + CircularProgressIndicator.adaptive(value: snapshot.data), ), const SizedBox(width: 20), ], @@ -141,12 +136,9 @@ class LoadingDialogState extends State { ? null : [ AdaptiveDialogAction( - onPressed: () => Navigator.of(context).pop>( - Result.error( - exception, - stackTrace, - ), - ), + onPressed: () => Navigator.of( + context, + ).pop>(Result.error(exception, stackTrace)), child: Text(widget.backLabel ?? L10n.of(context).close), ), ], diff --git a/lib/widgets/layouts/login_scaffold.dart b/lib/widgets/layouts/login_scaffold.dart index 6559fad8f..b15f8bafa 100644 --- a/lib/widgets/layouts/login_scaffold.dart +++ b/lib/widgets/layouts/login_scaffold.dart @@ -71,7 +71,7 @@ class LoginScaffold extends StatelessWidget { ), ), ), - const _PrivacyButtons(mainAxisAlignment: MainAxisAlignment.center), + const _PrivacyButtons(mainAxisAlignment: .center), ], ), ); @@ -95,31 +95,19 @@ class _PrivacyButtons extends StatelessWidget { children: [ TextButton( onPressed: () => launchUrlString(AppConfig.website), - child: Text( - L10n.of(context).website, - style: shadowTextStyle, - ), + child: Text(L10n.of(context).website, style: shadowTextStyle), ), TextButton( onPressed: () => launchUrlString(AppConfig.supportUrl), - child: Text( - L10n.of(context).help, - style: shadowTextStyle, - ), + child: Text(L10n.of(context).help, style: shadowTextStyle), ), TextButton( onPressed: () => launchUrl(AppConfig.privacyUrl), - child: Text( - L10n.of(context).privacy, - style: shadowTextStyle, - ), + child: Text(L10n.of(context).privacy, style: shadowTextStyle), ), TextButton( onPressed: () => PlatformInfos.showDialog(context), - child: Text( - L10n.of(context).about, - style: shadowTextStyle, - ), + child: Text(L10n.of(context).about, style: shadowTextStyle), ), ], ), diff --git a/lib/widgets/layouts/max_width_body.dart b/lib/widgets/layouts/max_width_body.dart index 5720d94bb..c0afc7077 100644 --- a/lib/widgets/layouts/max_width_body.dart +++ b/lib/widgets/layouts/max_width_body.dart @@ -35,11 +35,10 @@ class MaxWidthBody extends StatelessWidget { ), child: Material( shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), - side: BorderSide( - color: theme.dividerColor, + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, ), + side: BorderSide(color: theme.dividerColor), ), clipBehavior: Clip.hardEdge, child: Padding( diff --git a/lib/widgets/layouts/two_column_layout.dart b/lib/widgets/layouts/two_column_layout.dart index 86a6f56c5..4c43d424a 100644 --- a/lib/widgets/layouts/two_column_layout.dart +++ b/lib/widgets/layouts/two_column_layout.dart @@ -25,15 +25,8 @@ class TwoColumnLayout extends StatelessWidget { width: FluffyThemes.columnWidth + FluffyThemes.navRailWidth, child: mainView, ), - Container( - width: 1.0, - color: theme.dividerColor, - ), - Expanded( - child: ClipRRect( - child: sideView, - ), - ), + Container(width: 1.0, color: theme.dividerColor), + Expanded(child: ClipRRect(child: sideView)), ], ), ), diff --git a/lib/widgets/local_notifications_extension.dart b/lib/widgets/local_notifications_extension.dart index 443ed6c83..62b295c12 100644 --- a/lib/widgets/local_notifications_extension.dart +++ b/lib/widgets/local_notifications_extension.dart @@ -33,11 +33,13 @@ extension LocalNotificationsExtension on MatrixState { } } - final title = - event.room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))); + final title = event.room.getLocalizedDisplayname( + MatrixLocals(L10n.of(context)), + ); final body = await event.calcLocalizedBody( MatrixLocals(L10n.of(context)), - withSenderNamePrefix: !event.room.isDirectChat || + withSenderNamePrefix: + !event.room.isDirectChat || event.room.lastEvent?.senderId == client.userID, plaintextBody: true, hideReply: true, @@ -66,13 +68,13 @@ extension LocalNotificationsExtension on MatrixState { Logs().d('Unable to pre-download avatar for web notification', e, s); } - thumbnailUri = - await event.senderFromMemoryOrFallback.avatarUrl?.getThumbnailUri( - client, - width: size, - height: size, - method: thumbnailMethod, - ); + thumbnailUri = await event.senderFromMemoryOrFallback.avatarUrl + ?.getThumbnailUri( + client, + width: size, + height: size, + method: thumbnailMethod, + ); } _audioPlayer.play(); @@ -133,8 +135,9 @@ extension LocalNotificationsExtension on MatrixState { hints: hints, ); notification.action.then((actionStr) { - var action = DesktopNotificationActions.values - .singleWhereOrNull((a) => a.name == actionStr); + var action = DesktopNotificationActions.values.singleWhereOrNull( + (a) => a.name == actionStr, + ); if (action == null && actionStr == "default") { action = DesktopNotificationActions.openChat; } diff --git a/lib/widgets/lock_screen.dart b/lib/widgets/lock_screen.dart index ab31e5edb..ea4bcf8c2 100644 --- a/lib/widgets/lock_screen.dart +++ b/lib/widgets/lock_screen.dart @@ -79,10 +79,7 @@ class _LockScreenState extends State { shrinkWrap: true, children: [ Center( - child: Image.asset( - 'assets/info-logo.png', - width: 256, - ), + child: Image.asset('assets/info-logo.png', width: 256), ), TextField( controller: _textEditingController, @@ -95,9 +92,7 @@ class _LockScreenState extends State { onChanged: tryUnlock, onSubmitted: tryUnlock, style: const TextStyle(fontSize: 40), - inputFormatters: [ - LengthLimitingTextInputFormatter(4), - ], + inputFormatters: [LengthLimitingTextInputFormatter(4)], decoration: InputDecoration( errorText: _errorText, hintText: '****', diff --git a/lib/widgets/log_view.dart b/lib/widgets/log_view.dart index 0779af6e6..402e64064 100644 --- a/lib/widgets/log_view.dart +++ b/lib/widgets/log_view.dart @@ -15,17 +15,14 @@ class LogViewerState extends State { double fontSize = 14; @override Widget build(BuildContext context) { - final outputEvents = Logs() - .outputEvents + final outputEvents = Logs().outputEvents .where((e) => e.level.index <= logLevel.index) .toList(); return Scaffold( backgroundColor: Colors.black, appBar: AppBar( title: Text(logLevel.toString()), - leading: BackButton( - onPressed: () => context.go('/'), - ), + leading: BackButton(onPressed: () => context.go('/')), actions: [ IconButton( icon: const Icon(Icons.zoom_in_outlined), @@ -55,9 +52,7 @@ class LogViewerState extends State { scrollDirection: Axis.horizontal, child: SelectableText( outputEvents[i].toDisplayString(), - style: TextStyle( - color: outputEvents[i].color, - ), + style: TextStyle(color: outputEvents[i].color), ), ), ), diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index 63b7ee117..bec319de8 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -120,10 +120,7 @@ class MatrixState extends State with WidgetsBindingObserver { } resBundles[bundle.name] ??= []; resBundles[bundle.name]!.add( - _AccountBundleWithClient( - client: widget.clients[i], - bundle: bundle, - ), + _AccountBundleWithClient(client: widget.clients[i], bundle: bundle), ); } } @@ -132,12 +129,13 @@ class MatrixState extends State with WidgetsBindingObserver { (a, b) => a.bundle!.priority == null ? 1 : b.bundle!.priority == null - ? -1 - : a.bundle!.priority!.compareTo(b.bundle!.priority!), + ? -1 + : a.bundle!.priority!.compareTo(b.bundle!.priority!), ); } - return resBundles - .map((k, v) => MapEntry(k, v.map((vv) => vv.client).toList())); + return resBundles.map( + (k, v) => MapEntry(k, v.map((vv) => vv.client).toList()), + ); } bool get hasComplexBundles => accountBundles.values.any((v) => v.length > 1); @@ -151,27 +149,26 @@ class MatrixState extends State with WidgetsBindingObserver { if (widget.clients.isNotEmpty && !client.isLogged()) { return client; } - final candidate = - _loginClientCandidate ??= await ClientManager.createClient( - '${AppSettings.applicationName.value}-${DateTime.now().millisecondsSinceEpoch}', - store, - ) - ..onLoginStateChanged - .stream + final candidate = _loginClientCandidate ??= + await ClientManager.createClient( + '${AppSettings.applicationName.value}-${DateTime.now().millisecondsSinceEpoch}', + store, + ) + ..onLoginStateChanged.stream .where((l) => l == LoginState.loggedIn) .first .then((_) { - if (!widget.clients.contains(_loginClientCandidate)) { - widget.clients.add(_loginClientCandidate!); - } - ClientManager.addClientNameToStore( - _loginClientCandidate!.clientName, - store, - ); - _registerSubs(_loginClientCandidate!.clientName); - _loginClientCandidate = null; - FluffyChatApp.router.go('/backup'); - }); + if (!widget.clients.contains(_loginClientCandidate)) { + widget.clients.add(_loginClientCandidate!); + } + ClientManager.addClientNameToStore( + _loginClientCandidate!.clientName, + store, + ); + _registerSubs(_loginClientCandidate!.clientName); + _loginClientCandidate = null; + FluffyChatApp.router.go('/backup'); + }); if (widget.clients.isEmpty) widget.clients.add(candidate); return candidate; } @@ -210,8 +207,9 @@ class MatrixState extends State with WidgetsBindingObserver { return route.split('/')[2]; } - final linuxNotifications = - PlatformInfos.isLinux ? NotificationsClient() : null; + final linuxNotifications = PlatformInfos.isLinux + ? NotificationsClient() + : null; final Map linuxNotificationIds = {}; @override @@ -229,8 +227,9 @@ class MatrixState extends State with WidgetsBindingObserver { ); return; } - onRoomKeyRequestSub[name] ??= - c.onRoomKeyRequest.stream.listen((RoomKeyRequest request) async { + onRoomKeyRequestSub[name] ??= c.onRoomKeyRequest.stream.listen(( + RoomKeyRequest request, + ) async { if (widget.clients.any( ((cl) => cl.userID == request.requestingDevice.userId && @@ -244,22 +243,24 @@ class MatrixState extends State with WidgetsBindingObserver { }); onKeyVerificationRequestSub[name] ??= c.onKeyVerificationRequest.stream .listen((KeyVerification request) async { - var hidPopup = false; - request.onUpdate = () { - if (!hidPopup && - {KeyVerificationState.done, KeyVerificationState.error} - .contains(request.state)) { - FluffyChatApp.router.pop('dialog'); - } - hidPopup = true; - }; - request.onUpdate = null; - hidPopup = true; - await KeyVerificationDialog(request: request).show( - FluffyChatApp.router.routerDelegate.navigatorKey.currentContext ?? - context, - ); - }); + var hidPopup = false; + request.onUpdate = () { + if (!hidPopup && + { + KeyVerificationState.done, + KeyVerificationState.error, + }.contains(request.state)) { + FluffyChatApp.router.pop('dialog'); + } + hidPopup = true; + }; + request.onUpdate = null; + hidPopup = true; + await KeyVerificationDialog(request: request).show( + FluffyChatApp.router.routerDelegate.navigatorKey.currentContext ?? + context, + ); + }); onLoginStateChanged[name] ??= c.onLoginStateChanged.stream.listen((state) { final loggedInWithMultipleClients = widget.clients.length > 1; if (state == LoginState.loggedOut) { @@ -273,25 +274,25 @@ class MatrixState extends State with WidgetsBindingObserver { FluffyChatApp.router.routerDelegate.navigatorKey.currentContext ?? context, ).showSnackBar( - SnackBar( - content: Text(L10n.of(context).oneClientLoggedOut), - ), + SnackBar(content: Text(L10n.of(context).oneClientLoggedOut)), ); if (state != LoginState.loggedIn) { FluffyChatApp.router.go('/rooms'); } } else { - FluffyChatApp.router - .go(state == LoginState.loggedIn ? '/backup' : '/home'); + FluffyChatApp.router.go( + state == LoginState.loggedIn ? '/backup' : '/home', + ); } }); onUiaRequest[name] ??= c.onUiaRequest.stream.listen(uiaRequestHandler); if (PlatformInfos.isWeb || PlatformInfos.isLinux) { c.onSync.stream.first.then((s) { html.Notification.requestPermission(); - onNotification[name] ??= - c.onNotification.stream.listen(showLocalNotification); + onNotification[name] ??= c.onNotification.stream.listen( + showLocalNotification, + ); }); } } @@ -322,13 +323,18 @@ class MatrixState extends State with WidgetsBindingObserver { this, onFcmError: (errorMsg, {Uri? link}) async { final result = await showOkCancelAlertDialog( - context: FluffyChatApp - .router.routerDelegate.navigatorKey.currentContext ?? + context: + FluffyChatApp + .router + .routerDelegate + .navigatorKey + .currentContext ?? context, title: L10n.of(context).pushNotificationsNotAvailable, message: errorMsg, - okLabel: - link == null ? L10n.of(context).ok : L10n.of(context).learnMore, + okLabel: link == null + ? L10n.of(context).ok + : L10n.of(context).learnMore, cancelLabel: L10n.of(context).doNotShowAgain, ); if (result == OkCancelResult.ok && link != null) { @@ -357,11 +363,13 @@ class MatrixState extends State with WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { - final foreground = state != AppLifecycleState.inactive && + final foreground = + state != AppLifecycleState.inactive && state != AppLifecycleState.paused; for (final client in widget.clients) { - client.syncPresence = - state == AppLifecycleState.resumed ? null : PresenceType.unavailable; + client.syncPresence = state == AppLifecycleState.resumed + ? null + : PresenceType.unavailable; if (PlatformInfos.isMobile) { client.backgroundSync = foreground; client.requestHistoryOnLimitedTimeline = !foreground; @@ -389,10 +397,7 @@ class MatrixState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - return Provider( - create: (_) => this, - child: widget.child, - ); + return Provider(create: (_) => this, child: widget.child); } Future dehydrateAction(BuildContext context) async { @@ -412,9 +417,7 @@ class MatrixState extends State with WidgetsBindingObserver { final export = result.result; if (export == null) return; - final exportBytes = Uint8List.fromList( - const Utf8Codec().encode(export), - ); + final exportBytes = Uint8List.fromList(const Utf8Codec().encode(export)); final exportFileName = 'fluffychat-export-${DateFormat(DateFormat.YEAR_MONTH_DAY).format(DateTime.now())}.fluffybackup'; diff --git a/lib/widgets/member_actions_popup_menu_button.dart b/lib/widgets/member_actions_popup_menu_button.dart index a1164203a..56ecd9935 100644 --- a/lib/widgets/member_actions_popup_menu_button.dart +++ b/lib/widgets/member_actions_popup_menu_button.dart @@ -50,8 +50,8 @@ void showMemberActionsPopupMenu({ presenceBackgroundColor: theme.colorScheme.surfaceContainer, ), Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ ConstrainedBox( constraints: const BoxConstraints(maxWidth: 128), @@ -109,16 +109,16 @@ void showMemberActionsPopupMenu({ const Icon(Icons.admin_panel_settings_outlined), const SizedBox(width: 18), Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: .min, + crossAxisAlignment: .start, children: [ Text(L10n.of(context).chatPermissions), Text( user.powerLevel < 50 ? L10n.of(context).userLevel(user.powerLevel) : user.powerLevel < 100 - ? L10n.of(context).moderatorLevel(user.powerLevel) - : L10n.of(context).adminLevel(user.powerLevel), + ? L10n.of(context).moderatorLevel(user.powerLevel) + : L10n.of(context).adminLevel(user.powerLevel), style: const TextStyle(fontSize: 10), ), ], @@ -267,10 +267,7 @@ void showMemberActionsPopupMenu({ final result = await showFutureLoadingDialog( context: context, - future: () => user.room.client.reportUser( - user.id, - reason, - ), + future: () => user.room.client.reportUser(user.id, reason), ); if (result.error != null) return; ScaffoldMessenger.of(context).showSnackBar( diff --git a/lib/widgets/navigation_rail.dart b/lib/widgets/navigation_rail.dart index 7cb4be43b..f6df4e29a 100644 --- a/lib/widgets/navigation_rail.dart +++ b/lib/widgets/navigation_rail.dart @@ -27,24 +27,20 @@ class SpacesNavigationRail extends StatelessWidget { @override Widget build(BuildContext context) { final client = Matrix.of(context).client; - final isSettings = GoRouter.of(context) - .routeInformationProvider - .value - .uri - .path - .startsWith('/rooms/settings'); + final isSettings = GoRouter.of( + context, + ).routeInformationProvider.value.uri.path.startsWith('/rooms/settings'); return Material( child: SafeArea( child: StreamBuilder( - key: ValueKey( - client.userID.toString(), - ), + key: ValueKey(client.userID.toString()), stream: client.onSync.stream .where((s) => s.hasRoomUpdate) .rateLimit(const Duration(seconds: 1)), builder: (context, _) { - final allSpaces = - client.rooms.where((room) => room.isSpace).toList(); + final allSpaces = client.rooms + .where((room) => room.isSpace) + .toList(); return SizedBox( width: FluffyThemes.isColumnMode(context) @@ -86,12 +82,13 @@ class SpacesNavigationRail extends StatelessWidget { ); } final space = allSpaces[i]; - final displayname = - allSpaces[i].getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ); - final spaceChildrenIds = - space.spaceChildren.map((c) => c.roomId).toSet(); + final displayname = allSpaces[i] + .getLocalizedDisplayname( + MatrixLocals(L10n.of(context)), + ); + final spaceChildrenIds = space.spaceChildren + .map((c) => c.roomId) + .toSet(); return NaviRailItem( toolTip: displayname, isSelected: activeSpaceId == space.id, diff --git a/lib/widgets/permission_slider_dialog.dart b/lib/widgets/permission_slider_dialog.dart index d02b43ecf..dd613eedd 100644 --- a/lib/widgets/permission_slider_dialog.dart +++ b/lib/widgets/permission_slider_dialog.dart @@ -18,8 +18,8 @@ Future showPermissionChooser( content: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 256, maxHeight: 256), child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: .min, + crossAxisAlignment: .stretch, spacing: 12.0, children: [ Text(L10n.of(context).setPermissionsLevelDescription), diff --git a/lib/widgets/qr_code_viewer.dart b/lib/widgets/qr_code_viewer.dart index 769380df2..f8653a68c 100644 --- a/lib/widgets/qr_code_viewer.dart +++ b/lib/widgets/qr_code_viewer.dart @@ -13,10 +13,7 @@ import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dar import 'package:fluffychat/widgets/future_loading_dialog.dart'; import '../config/themes.dart'; -Future showQrCodeViewer( - BuildContext context, - String content, -) => +Future showQrCodeViewer(BuildContext context, String content) => showDialog( context: context, builder: (context) => QrCodeViewer(content: content), @@ -32,11 +29,7 @@ class QrCodeViewer extends StatelessWidget { context: context, future: () async { final inviteLink = 'https://matrix.to/#/$content'; - final image = QRImage( - inviteLink, - size: 256, - radius: 1, - ).generate(); + final image = QRImage(inviteLink, size: 256, radius: 1).generate(); return compute(encodePng, image); }, ); @@ -76,10 +69,7 @@ class QrCodeViewer extends StatelessWidget { backgroundColor: Colors.black.withAlpha(128), ), icon: Icon(Icons.adaptive.share_outlined), - onPressed: () => FluffyShare.share( - inviteLink, - context, - ), + onPressed: () => FluffyShare.share(inviteLink, context), color: Colors.white, tooltip: L10n.of(context).share, ), @@ -105,11 +95,12 @@ class QrCodeViewer extends StatelessWidget { borderRadius: BorderRadius.circular(AppConfig.borderRadius), ), child: Column( - mainAxisSize: MainAxisSize.min, + mainAxisSize: .min, children: [ ConstrainedBox( - constraints: - const BoxConstraints(maxWidth: FluffyThemes.columnWidth), + constraints: const BoxConstraints( + maxWidth: FluffyThemes.columnWidth, + ), child: PrettyQrView.data( data: inviteLink, decoration: PrettyQrDecoration( diff --git a/lib/widgets/share_scaffold_dialog.dart b/lib/widgets/share_scaffold_dialog.dart index 4a4001866..fa80896b4 100644 --- a/lib/widgets/share_scaffold_dialog.dart +++ b/lib/widgets/share_scaffold_dialog.dart @@ -64,9 +64,7 @@ class _ShareScaffoldDialogState extends State { @override Widget build(BuildContext context) { final theme = Theme.of(context); - final rooms = Matrix.of(context) - .client - .rooms + final rooms = Matrix.of(context).client.rooms .where( (room) => room.canSendDefaultMessages && @@ -138,8 +136,9 @@ class _ShareScaffoldDialogState extends State { ), controlAffinity: ListTileControlAffinity.trailing, shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius), + borderRadius: BorderRadius.circular( + AppConfig.borderRadius, + ), ), secondary: Avatar( mxContent: room.avatar, diff --git a/lib/widgets/theme_builder.dart b/lib/widgets/theme_builder.dart index b526aadfd..669c88913 100644 --- a/lib/widgets/theme_builder.dart +++ b/lib/widgets/theme_builder.dart @@ -12,7 +12,8 @@ class ThemeBuilder extends StatefulWidget { BuildContext context, ThemeMode themeMode, Color? primaryColor, - ) builder; + ) + builder; final String themeModeSettingsKey; final String primaryColorSettingsKey; @@ -38,28 +39,26 @@ class ThemeController extends State { Color? get primaryColor => _primaryColor; static ThemeController of(BuildContext context) => - Provider.of( - context, - listen: false, - ); + Provider.of(context, listen: false); void _loadData(dynamic _) async { - final preferences = - _sharedPreferences ??= await SharedPreferences.getInstance(); + final preferences = _sharedPreferences ??= + await SharedPreferences.getInstance(); final rawThemeMode = preferences.getString(widget.themeModeSettingsKey); final rawColor = preferences.getInt(widget.primaryColorSettingsKey); setState(() { - _themeMode = ThemeMode.values - .singleWhereOrNull((value) => value.name == rawThemeMode); + _themeMode = ThemeMode.values.singleWhereOrNull( + (value) => value.name == rawThemeMode, + ); _primaryColor = rawColor == null ? null : Color(rawColor); }); } Future setThemeMode(ThemeMode newThemeMode) async { - final preferences = - _sharedPreferences ??= await SharedPreferences.getInstance(); + final preferences = _sharedPreferences ??= + await SharedPreferences.getInstance(); await preferences.setString(widget.themeModeSettingsKey, newThemeMode.name); setState(() { _themeMode = newThemeMode; @@ -67,8 +66,8 @@ class ThemeController extends State { } Future setPrimaryColor(Color? newPrimaryColor) async { - final preferences = - _sharedPreferences ??= await SharedPreferences.getInstance(); + final preferences = _sharedPreferences ??= + await SharedPreferences.getInstance(); if (newPrimaryColor == null) { await preferences.remove(widget.primaryColorSettingsKey); } else { @@ -93,11 +92,8 @@ class ThemeController extends State { return Provider( create: (_) => this, child: DynamicColorBuilder( - builder: (light, _) => widget.builder( - context, - themeMode, - primaryColor ?? light?.primary, - ), + builder: (light, _) => + widget.builder(context, themeMode, primaryColor ?? light?.primary), ), ); } diff --git a/lib/widgets/unread_rooms_badge.dart b/lib/widgets/unread_rooms_badge.dart index 495173496..986316bd1 100644 --- a/lib/widgets/unread_rooms_badge.dart +++ b/lib/widgets/unread_rooms_badge.dart @@ -21,9 +21,7 @@ class UnreadRoomsBadge extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); - final unreadCount = Matrix.of(context) - .client - .rooms + final unreadCount = Matrix.of(context).client.rooms .where(filter) .where((r) => (r.isUnread || r.membership == Membership.invite)) .length; @@ -31,17 +29,11 @@ class UnreadRoomsBadge extends StatelessWidget { badgeStyle: b.BadgeStyle( badgeColor: theme.colorScheme.primary, elevation: 4, - borderSide: BorderSide( - color: theme.colorScheme.surface, - width: 2, - ), + borderSide: BorderSide(color: theme.colorScheme.surface, width: 2), ), badgeContent: Text( unreadCount.toString(), - style: TextStyle( - color: theme.colorScheme.onPrimary, - fontSize: 12, - ), + style: TextStyle(color: theme.colorScheme.onPrimary, fontSize: 12), ), showBadge: unreadCount != 0, badgeAnimation: const b.BadgeAnimation.scale(), diff --git a/pubspec.lock b/pubspec.lock index dc4dcda09..00e5f83d2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -2251,5 +2251,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.9.0 <4.0.0" + dart: ">=3.10.0 <4.0.0" flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8f4b981d8..202ca1edb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ publish_to: none version: 2.3.0+3545 environment: - sdk: ">=3.0.0 <4.0.0" + sdk: ">=3.10.0 <4.0.0" dependencies: animations: ^2.1.1