From 1ebae21ea21ff3addf029bfa5ae5ed9da5191d22 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sun, 23 May 2021 13:11:55 +0200 Subject: [PATCH] feat: Switch to VRouter --- lib/config/app_config.dart | 1 + lib/config/routes.dart | 447 ++++++++++-------- lib/main.dart | 104 ++-- lib/pages/archive.dart | 2 +- lib/pages/bootstrap_dialog.dart | 3 - lib/pages/chat.dart | 58 ++- lib/pages/chat_details.dart | 61 ++- lib/pages/chat_encryption_settings.dart | 8 +- lib/pages/chat_list.dart | 17 +- lib/pages/chat_permissions_settings.dart | 22 +- lib/pages/device_settings.dart | 2 - lib/pages/homeserver_picker.dart | 9 +- lib/pages/image_viewer.dart | 4 +- lib/pages/invitation_selection.dart | 18 +- lib/pages/key_verification_dialog.dart | 4 - lib/pages/login.dart | 7 +- lib/pages/new_group.dart | 9 +- lib/pages/new_private_chat.dart | 5 +- lib/pages/permission_slider_dialog.dart | 2 - lib/pages/search.dart | 23 +- lib/pages/settings.dart | 19 +- lib/pages/settings_3pid.dart | 3 - lib/pages/settings_emotes.dart | 9 +- lib/pages/settings_multiple_emotes.dart | 6 +- lib/pages/sign_up.dart | 11 +- lib/pages/sign_up_password.dart | 36 +- lib/pages/user_bottom_sheet.dart | 7 +- lib/pages/views/chat_details_view.dart | 20 +- .../views/chat_encryption_settings_view.dart | 9 +- lib/pages/views/chat_list_view.dart | 14 +- .../views/chat_permissions_settings_view.dart | 2 +- lib/pages/views/chat_view.dart | 31 +- lib/pages/views/empty_page_view.dart | 1 + .../views/invitation_selection_view.dart | 3 +- lib/pages/views/new_private_chat_view.dart | 5 +- lib/pages/views/search_view.dart | 17 +- .../views/settings_multiple_emotes_view.dart | 13 +- lib/pages/views/settings_view.dart | 28 +- lib/pages/views/sign_up_view.dart | 19 +- lib/utils/background_push.dart | 16 +- lib/utils/fluffy_share.dart | 3 +- lib/utils/platform_infos.dart | 1 - lib/utils/url_launcher.dart | 29 +- lib/widgets/chat_settings_popup_menu.dart | 14 +- lib/widgets/contacts_list.dart | 7 +- lib/widgets/encryption_button.dart | 9 +- lib/widgets/event_content/audio_player.dart | 5 +- .../event_content/message_content.dart | 5 +- lib/widgets/layouts/loading_view.dart | 9 +- lib/widgets/layouts/two_column_layout.dart | 40 ++ lib/widgets/list_items/chat_list_item.dart | 10 +- .../list_items/public_room_list_item.dart | 5 +- lib/widgets/log_view.dart | 29 +- lib/widgets/matrix.dart | 20 +- pubspec.lock | 35 +- pubspec.yaml | 2 +- test/sign_up_password_test.dart | 5 +- 57 files changed, 682 insertions(+), 621 deletions(-) create mode 100644 lib/widgets/layouts/two_column_layout.dart diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 98f32030..962aa4db 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -42,6 +42,7 @@ abstract class AppConfig { static const String emojiFontUrl = 'https://github.com/googlefonts/noto-emoji/'; static const double borderRadius = 12.0; + static const double columnWidth = 360.0; static void loadFromJson(Map json) { if (json['application_name'] is String) { diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 4f02e0a5..bbcf7d0a 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,5 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; -import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/archive.dart'; import 'package:fluffychat/pages/homeserver_picker.dart'; import 'package:fluffychat/pages/invitation_selection.dart'; @@ -7,7 +5,7 @@ import 'package:fluffychat/pages/settings_emotes.dart'; import 'package:fluffychat/pages/settings_multiple_emotes.dart'; import 'package:fluffychat/pages/sign_up.dart'; import 'package:fluffychat/pages/sign_up_password.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +import 'package:fluffychat/widgets/layouts/two_column_layout.dart'; import 'package:fluffychat/pages/chat.dart'; import 'package:fluffychat/pages/chat_details.dart'; import 'package:fluffychat/pages/chat_encryption_settings.dart'; @@ -27,200 +25,261 @@ import 'package:fluffychat/pages/settings_ignore_list.dart'; import 'package:fluffychat/pages/settings_notifications.dart'; import 'package:fluffychat/pages/settings_style.dart'; import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; -class FluffyRoutes { - final BuildContext context; +class AppRoutes { + final int columns; - const FluffyRoutes(this.context); + AppRoutes(this.columns); - ViewData onGenerateRoute(RouteSettings settings) { - final parts = settings.name.split('/'); - - // Routes if the app is loading - if (Matrix.of(context).loginState == null) { - return ViewData(mainView: (_) => LoadingView()); - // Routes if user is NOT logged in - } else if (Matrix.of(context).loginState == LoginState.loggedOut) { - switch (parts[1]) { - case '': - return ViewData(mainView: (_) => HomeserverPicker()); - case 'login': - return ViewData(mainView: (_) => Login()); - case 'signup': - if (parts.length == 5 && parts[2] == 'password') { - return ViewData( - mainView: (_) => SignUpPassword( - parts[3], - displayname: parts[4], - avatar: settings.arguments, + List get routes => [ + VWidget(path: '/', widget: LoadingView()), + VWidget( + path: '/home', + widget: HomeserverPicker(), + buildTransition: _fadeTransition, + stackedRoutes: [ + VWidget( + path: '/signup', + widget: SignUp(), + buildTransition: _fadeTransition, + stackedRoutes: [ + VWidget( + path: 'password/:username', + widget: SignUpPassword(), + buildTransition: _fadeTransition, + ), + VWidget( + path: '/login', + widget: Login(), + buildTransition: _fadeTransition, + ), + ]), + ], + ), + if (columns > 1) ...{ + VNester( + path: '/rooms', + widgetBuilder: (child) => TwoColumnLayout( + mainView: ChatList(), + sideView: child, + ), + buildTransition: _fadeTransition, + nestedRoutes: [ + VWidget( + path: '', + widget: EmptyPage(), + buildTransition: _fadeTransition, + stackedRoutes: [ + VWidget( + path: '/newprivatechat', + widget: NewPrivateChat(), + buildTransition: _fadeTransition, + ), + VWidget( + path: '/newgroup', + widget: NewGroup(), + buildTransition: _fadeTransition, + ), + if (columns == 2) + VWidget( + path: ':roomid', + widget: Chat(), + buildTransition: _fadeTransition, + stackedRoutes: [ + VWidget( + path: 'encryption', + widget: ChatEncryptionSettings(), + buildTransition: _fadeTransition, + ), + VWidget( + path: 'details', + widget: ChatDetails(), + buildTransition: _fadeTransition, + stackedRoutes: _chatDetailsRoutes, + ), + VWidget( + path: 'invite', + widget: InvitationSelection(), + buildTransition: _fadeTransition, + ), + ]), + if (columns > 2) + VNester( + path: ':roomid', + widgetBuilder: (child) => Chat(sideView: child), + buildTransition: _fadeTransition, + nestedRoutes: [ + VWidget( + path: '', + widget: EmptyPage(), + buildTransition: _fadeTransition, + ), + VWidget( + path: 'encryption', + widget: ChatEncryptionSettings(), + buildTransition: _fadeTransition, + ), + VWidget( + path: 'details', + widget: ChatDetails(), + buildTransition: _fadeTransition, + stackedRoutes: _chatDetailsRoutes, + ), + VWidget( + path: 'invite', + widget: InvitationSelection(), + buildTransition: _fadeTransition, + ), + ], + ), + ], ), - ); - } - return ViewData(mainView: (_) => SignUp()); - } - } - // Routes IF user is logged in - else { - switch (parts[1]) { - case '': - return ViewData( - mainView: (_) => ChatList(), emptyView: (_) => EmptyPage()); - case 'rooms': - final roomId = parts[2]; - if (parts.length == 3) { - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId), - ); - } else if (parts.length == 4) { - final action = parts[3]; - switch (action) { - case 'details': - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId), - rightView: (_) => ChatDetails(roomId), - ); - case 'encryption': - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId), - rightView: (_) => ChatEncryptionSettings(roomId), - ); - case 'permissions': - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId), - rightView: (_) => ChatPermissionsSettings(roomId), - ); - case 'invite': - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId), - rightView: (_) => InvitationSelection(roomId), - ); - case 'emotes': - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId), - rightView: (_) => MultipleEmotesSettings(roomId), - ); - default: - return ViewData( - leftView: (_) => ChatList(activeChat: roomId), - mainView: (_) => Chat(roomId, - scrollToEventId: action.sigil == '\$' ? action : null), - ); - } - } - return ViewData( - mainView: (_) => ChatList(), emptyView: (_) => EmptyPage()); - case 'archive': - return ViewData( - mainView: (_) => Archive(), - emptyView: (_) => EmptyPage(), - ); - case 'logs': - return ViewData( - mainView: (_) => LogViewer(), - ); - case 'newgroup': - return ViewData( - leftView: (_) => ChatList(), - mainView: (_) => NewGroup(), - ); - case 'newprivatechat': - return ViewData( - leftView: (_) => ChatList(), - mainView: (_) => NewPrivateChat(), - ); - case 'search': - if (parts.length == 3) { - return ViewData( - mainView: (_) => Search(alias: parts[2]), - emptyView: (_) => EmptyPage()); - } - return ViewData( - mainView: (_) => Search(), emptyView: (_) => EmptyPage()); - case 'settings': - if (parts.length == 3) { - final action = parts[2]; - switch (action) { - case '3pid': - return ViewData( - leftView: (_) => Settings(), - mainView: (_) => Settings3Pid(), - ); - case 'devices': - return ViewData( - leftView: (_) => Settings(), - mainView: (_) => DevicesSettings(), - ); - case 'emotes': - return ViewData( - leftView: (_) => Settings(), - mainView: (_) => EmotesSettings( - room: ((settings.arguments ?? {}) as Map)['room'], - stateKey: ((settings.arguments ?? {}) as Map)['stateKey'], - ), - ); - case 'ignore': - return ViewData( - leftView: (_) => Settings(), - mainView: (_) => SettingsIgnoreList( - initialUserId: settings.arguments, - ), - ); - case 'notifications': - return ViewData( - leftView: (_) => Settings(), - mainView: (_) => SettingsNotifications(), - ); - case 'style': - return ViewData( - leftView: (_) => Settings(), - mainView: (_) => SettingsStyle(), - ); - } - } else { - return ViewData( - mainView: (_) => Settings(), emptyView: (_) => EmptyPage()); - } - return ViewData( - mainView: (_) => ChatList(), emptyView: (_) => EmptyPage()); - } - } - - // If route cant be found: - return ViewData( - mainView: (_) => Center( - child: Text('Route "${settings.name}" not found...'), - ), - ); - } -} - -class SettingsDevices {} - -class FadeRoute extends PageRouteBuilder { - final Widget page; - FadeRoute({this.page}) - : super( - pageBuilder: ( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - ) => - page, - transitionsBuilder: ( - BuildContext context, - Animation animation, - Animation secondaryAnimation, - Widget child, - ) => - FadeTransition( - opacity: animation, - child: child, + ], ), - ); + VWidget( + path: '/rooms', + widget: TwoColumnLayout( + mainView: ChatList(), + sideView: EmptyPage(), + ), + buildTransition: _fadeTransition, + stackedRoutes: [ + _settingsRoute, + VWidget( + path: '/search', + widget: TwoColumnLayout( + mainView: Search(), + sideView: EmptyPage(), + ), + buildTransition: _fadeTransition, + ), + VWidget( + path: '/archive', + widget: TwoColumnLayout( + mainView: Archive(), + sideView: EmptyPage(), + ), + buildTransition: _fadeTransition, + ), + ], + ), + }, + if (columns == 1) + VWidget( + path: '/rooms', + widget: ChatList(), + stackedRoutes: [ + VWidget(path: ':roomid', widget: Chat(), stackedRoutes: [ + VWidget( + path: 'encryption', + widget: ChatEncryptionSettings(), + ), + VWidget( + path: 'invite', + widget: InvitationSelection(), + ), + VWidget( + path: 'details', + widget: ChatDetails(), + stackedRoutes: _chatDetailsRoutes, + ), + ]), + _settingsRoute, + VWidget( + path: '/search', + widget: Search(), + ), + VWidget( + path: '/archive', + widget: Archive(), + ), + VWidget( + path: '/newprivatechat', + widget: NewPrivateChat(), + ), + VWidget( + path: '/newgroup', + widget: NewGroup(), + ), + ], + ), + ]; + + List get _chatDetailsRoutes => [ + VWidget( + path: 'permissions', + widget: ChatPermissionsSettings(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: 'invite', + widget: InvitationSelection(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: 'emotes', + widget: MultipleEmotesSettings(), + buildTransition: _dynamicTransition, + ), + ]; + + VNester get _settingsRoute => VNester( + path: '/settings', + widgetBuilder: (child) => TwoColumnLayout( + mainView: Settings(), + sideView: child, + ), + buildTransition: _dynamicTransition, + nestedRoutes: [ + VWidget( + path: '', + widget: EmptyPage(), + buildTransition: _dynamicTransition, + stackedRoutes: [ + VWidget( + path: 'emotes', + widget: EmotesSettings(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: 'notifications', + widget: SettingsNotifications(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: 'ignorelist', + widget: SettingsIgnoreList(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: 'style', + widget: SettingsStyle(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: 'devices', + widget: DevicesSettings(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: '/logs', + widget: LogViewer(), + buildTransition: _dynamicTransition, + ), + VWidget( + path: '3pid', + widget: Settings3Pid(), + buildTransition: _dynamicTransition, + ), + ], + ), + ], + ); + + final _fadeTransition = (animation1, _, child) => + FadeTransition(opacity: animation1, child: child); + + FadeTransition Function(dynamic, dynamic, dynamic) get _dynamicTransition => + columns > 1 ? _fadeTransition : null; } diff --git a/lib/main.dart b/lib/main.dart index 9823808e..bdd7d94c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:adaptive_theme/adaptive_theme.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/config/routes.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -10,10 +9,12 @@ import 'package:fluffychat/utils/sentry_controller.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; +import 'utils/localized_exception_extension.dart'; import 'package:flutter_app_lock/flutter_app_lock.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:universal_html/html.dart' as html; +import 'package:vrouter/vrouter.dart'; import 'widgets/lock_screen.dart'; import 'widgets/matrix.dart'; @@ -47,11 +48,9 @@ void main() async { ); } -class FluffyChatApp extends StatelessWidget { +class FluffyChatApp extends StatefulWidget { final Widget testWidget; final Client testClient; - static final GlobalKey _apl = - GlobalKey(); const FluffyChatApp({Key key, this.testWidget, this.testClient}) : super(key: key); @@ -61,60 +60,59 @@ class FluffyChatApp extends StatelessWidget { /// in with qr code or magic link. static bool gotInitialLink = false; + @override + _FluffyChatAppState createState() => _FluffyChatAppState(); +} + +class _FluffyChatAppState extends State { + GlobalKey _router; + int columns; + String _initialUrl = '/'; @override Widget build(BuildContext context) { return AdaptiveTheme( light: FluffyThemes.light, dark: FluffyThemes.dark, initial: AdaptiveThemeMode.system, - builder: (theme, darkTheme) => MaterialApp( - title: '${AppConfig.applicationName}', - theme: theme, - darkTheme: darkTheme, - localizationsDelegates: L10n.localizationsDelegates, - supportedLocales: L10n.supportedLocales, - locale: kIsWeb - ? Locale(html.window.navigator.language.split('-').first) - : null, - home: Builder( - builder: (context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - SystemChrome.setSystemUIOverlayStyle( - SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - systemNavigationBarColor: Theme.of(context).backgroundColor, - systemNavigationBarIconBrightness: - Theme.of(context).brightness == Brightness.light - ? Brightness.dark - : Brightness.light, - ), - ); - }); - return Matrix( - context: context, - apl: _apl, - testClient: testClient, - child: Builder( - builder: (context) => AdaptivePageLayout( - key: _apl, - safeAreaOnColumnView: false, - onGenerateRoute: testWidget == null - ? FluffyRoutes(context).onGenerateRoute - : (_) => ViewData(mainView: (_) => testWidget), - dividerColor: Theme.of(context).dividerColor, - columnWidth: FluffyThemes.columnWidth, - dividerWidth: 1.0, - routeBuilder: (builder, settings) => - Matrix.of(context).loginState == LoginState.logged && - !{ - '/', - '/search', - '/contacts', - }.contains(settings.name) - ? MaterialPageRoute(builder: builder) - : FadeRoute(page: builder(context)), - ), - ), + builder: (theme, darkTheme) => Matrix( + context: context, + router: _router, + testClient: widget.testClient, + child: LayoutBuilder( + builder: (context, constraints) { + var newColumns = + (constraints.maxWidth / AppConfig.columnWidth).floor(); + if (newColumns > 3) newColumns = 3; + columns ??= newColumns; + _router ??= GlobalKey(); + if (columns != newColumns) { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + _initialUrl = _router.currentState.url; + columns = newColumns; + _router = GlobalKey(); + }); + }); + } + return VRouter( + key: _router, + title: '${AppConfig.applicationName}', + theme: theme, + darkTheme: darkTheme, + localizationsDelegates: L10n.localizationsDelegates, + supportedLocales: L10n.supportedLocales, + initialUrl: _initialUrl, + locale: kIsWeb + ? Locale(html.window.navigator.language.split('-').first) + : null, + routes: AppRoutes(columns).routes, + builder: (context, child) { + LoadingDialog.defaultTitle = L10n.of(context).loadingPleaseWait; + LoadingDialog.defaultBackLabel = L10n.of(context).close; + LoadingDialog.defaultOnError = + (Object e) => e.toLocalizedString(context); + return child; + }, ); }, ), diff --git a/lib/pages/archive.dart b/lib/pages/archive.dart index cb870392..1c44f403 100644 --- a/lib/pages/archive.dart +++ b/lib/pages/archive.dart @@ -28,7 +28,7 @@ class ArchiveController extends State { okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).cancel, message: L10n.of(context).clearArchive, - useRootNavigator: false, + ) != OkCancelResult.ok) { return; diff --git a/lib/pages/bootstrap_dialog.dart b/lib/pages/bootstrap_dialog.dart index 91fd4da3..bd876b9b 100644 --- a/lib/pages/bootstrap_dialog.dart +++ b/lib/pages/bootstrap_dialog.dart @@ -25,13 +25,11 @@ class BootstrapDialog extends StatefulWidget { ? showCupertinoDialog( context: context, builder: (context) => this, - useRootNavigator: false, barrierDismissible: true, ) : showDialog( context: context, builder: (context) => this, - useRootNavigator: false, barrierDismissible: true, ); @@ -196,7 +194,6 @@ class _BootstrapDialogState extends State { if (OkCancelResult.ok == await showOkCancelAlertDialog( context: context, - useRootNavigator: false, title: L10n.of(context).securityKeyLost, message: L10n.of(context).wipeChatBackup, okLabel: L10n.of(context).ok, diff --git a/lib/pages/chat.dart b/lib/pages/chat.dart index 7c12b254..23d48f92 100644 --- a/lib/pages/chat.dart +++ b/lib/pages/chat.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:file_picker_cross/file_picker_cross.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -23,17 +23,16 @@ import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:vrouter/vrouter.dart'; import 'send_file_dialog.dart'; import '../utils/matrix_sdk_extensions.dart/filtered_timeline_extension.dart'; import '../utils/matrix_sdk_extensions.dart/matrix_file_extension.dart'; class Chat extends StatefulWidget { - final String id; - final String scrollToEventId; + final Widget sideView; - Chat(this.id, {Key key, this.scrollToEventId}) - : super(key: key ?? Key('chatroom-$id')); + Chat({Key key, this.sideView}) : super(key: key); @override ChatController createState() => ChatController(); @@ -46,6 +45,8 @@ class ChatController extends State { MatrixState matrix; + String get roomId => context.vRouter.pathParameters['roomid']; + final AutoScrollController scrollController = AutoScrollController(); FocusNode inputFocus = FocusNode(); @@ -97,7 +98,7 @@ class ChatController extends State { try { await timeline.requestHistory(historyCount: _loadHistoryCount); } catch (err) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(err.toLocalizedString(context)))); } } @@ -167,8 +168,9 @@ class ChatController extends State { // "load more" button is visible on the screen SchedulerBinding.instance.addPostFrameCallback((_) async { if (mounted) { - if (widget.scrollToEventId != null) { - scrollToEventId(widget.scrollToEventId); + final event = VRouter.of(context).queryParameters['event']; + if (event != null) { + scrollToEventId(event); } _updateScrollController(); } @@ -231,7 +233,6 @@ class ChatController extends State { if (result == null) return; await showDialog( context: context, - useRootNavigator: false, builder: (c) => SendFileDialog( file: MatrixFile( bytes: result.toUint8List(), @@ -248,7 +249,6 @@ class ChatController extends State { if (result == null) return; await showDialog( context: context, - useRootNavigator: false, builder: (c) => SendFileDialog( file: MatrixImageFile( bytes: result.toUint8List(), @@ -265,7 +265,6 @@ class ChatController extends State { final bytes = await file.readAsBytes(); await showDialog( context: context, - useRootNavigator: false, builder: (c) => SendFileDialog( file: MatrixImageFile( bytes: bytes, @@ -284,7 +283,6 @@ class ChatController extends State { final result = await showDialog( context: context, builder: (c) => RecordingDialog(), - useRootNavigator: false, ); if (result == null) return; final audioFile = File(result); @@ -325,7 +323,6 @@ class ChatController extends State { final score = await showConfirmationDialog( context: context, title: L10n.of(context).howOffensiveIsThisContent, - useRootNavigator: false, actions: [ AlertDialogAction( key: -100, @@ -346,7 +343,6 @@ class ChatController extends State { title: L10n.of(context).whyDoYouWantToReportThis, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [DialogTextField(hintText: L10n.of(context).reason)]); if (reason == null || reason.single.isEmpty) return; final result = await showFutureLoadingDialog( @@ -360,7 +356,7 @@ class ChatController extends State { ); if (result.error != null) return; setState(() => selectedEvents.clear()); - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).contentHasBeenReported))); } @@ -370,7 +366,6 @@ class ChatController extends State { title: L10n.of(context).messageWillBeRemovedWarning, okLabel: L10n.of(context).remove, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.ok; if (!confirmed) return; @@ -400,7 +395,7 @@ class ChatController extends State { }; } setState(() => selectedEvents.clear()); - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/rooms'); } void sendAgainAction() { @@ -566,8 +561,7 @@ class ChatController extends State { future: room.leave, ); if (result.error == null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${result.result}'); + VRouter.of(context).push('/rooms/${result.result}'); } } @@ -653,5 +647,29 @@ class ChatController extends State { }); @override - Widget build(BuildContext context) => ChatView(this); + Widget build(BuildContext context) { + var currentUrl = Uri.decodeFull(VRouter.of(context).url); + if (!currentUrl.endsWith('/')) currentUrl += '/'; + final hideSideView = currentUrl == '/rooms/$roomId/'; + return widget.sideView == null + ? ChatView(this) + : Row( + children: [ + Expanded( + child: ClipRRect(child: ChatView(this)), + ), + Container( + width: 1.0, + color: Theme.of(context).dividerColor, + ), + AnimatedContainer( + duration: Duration(milliseconds: 300), + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(), + width: hideSideView ? 0 : 360.0, + child: hideSideView ? null : widget.sideView, + ), + ], + ); + } } diff --git a/lib/pages/chat_details.dart b/lib/pages/chat_details.dart index e6a58aa6..9ae86a96 100644 --- a/lib/pages/chat_details.dart +++ b/lib/pages/chat_details.dart @@ -1,5 +1,4 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; @@ -13,13 +12,12 @@ import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:vrouter/vrouter.dart'; enum AliasActions { copy, delete, setCanonical } class ChatDetails extends StatefulWidget { - final String roomId; - - const ChatDetails(this.roomId); + const ChatDetails(); @override ChatDetailsController createState() => ChatDetailsController(); @@ -28,21 +26,16 @@ class ChatDetails extends StatefulWidget { class ChatDetailsController extends State { List members; - @override - void initState() { - super.initState(); - members ??= - Matrix.of(context).client.getRoomById(widget.roomId).getParticipants(); - } + String get roomId => VRouter.of(context).pathParameters['roomid']; void setDisplaynameAction() async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final input = await showTextInputDialog( context: context, title: L10n.of(context).changeTheNameOfTheGroup, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, + textFields: [ DialogTextField( initialText: room.getLocalizedDisplayname( @@ -59,13 +52,13 @@ class ChatDetailsController extends State { future: () => room.setName(input.single), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).displaynameHasBeenChanged))); } } void editAliases() async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); // The current endpoint doesnt seem to be implemented in Synapse. This may // change in the future and then we just need to switch to this api call: @@ -136,7 +129,7 @@ class ChatDetailsController extends State { switch (option) { case AliasActions.copy: await Clipboard.setData(ClipboardData(text: select)); - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).copiedToClipboard)), ); break; @@ -159,7 +152,7 @@ class ChatDetailsController extends State { } void setAliasAction() async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final domain = room.client.userID.domain; final input = await showTextInputDialog( @@ -167,7 +160,7 @@ class ChatDetailsController extends State { title: L10n.of(context).setInvitationLink, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, + textFields: [ DialogTextField( prefixText: '#', @@ -186,13 +179,13 @@ class ChatDetailsController extends State { } void setTopicAction() async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final input = await showTextInputDialog( context: context, title: L10n.of(context).setGroupDescription, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, + textFields: [ DialogTextField( hintText: L10n.of(context).setGroupDescription, @@ -208,7 +201,7 @@ class ChatDetailsController extends State { future: () => room.setDescription(input.single), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar(SnackBar( + ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(L10n.of(context).groupDescriptionHasBeenChanged))); } } @@ -217,7 +210,7 @@ class ChatDetailsController extends State { context: context, future: () => Matrix.of(context) .client - .getRoomById(widget.roomId) + .getRoomById(roomId) .setGuestAccess(guestAccess), ); @@ -226,7 +219,7 @@ class ChatDetailsController extends State { context: context, future: () => Matrix.of(context) .client - .getRoomById(widget.roomId) + .getRoomById(roomId) .setHistoryVisibility(historyVisibility), ); @@ -234,23 +227,21 @@ class ChatDetailsController extends State { context: context, future: () => Matrix.of(context) .client - .getRoomById(widget.roomId) + .getRoomById(roomId) .setJoinRules(joinRule), ); void goToEmoteSettings() async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); // okay, we need to test if there are any emote state events other than the default one // if so, we need to be directed to a selection screen for which pack we want to look at // otherwise, we just open the normal one. if ((room.states['im.ponies.room_emotes'] ?? {}) .keys .any((String s) => s.isNotEmpty)) { - await AdaptivePageLayout.of(context) - .pushNamed('/rooms/${room.id}/emotes'); + VRouter.of(context).pushNamed('/rooms/${room.id}/emotes'); } else { - await AdaptivePageLayout.of(context) - .pushNamed('/settings/emotes', arguments: {'room': room}); + VRouter.of(context).pushNamed('/settings/emotes'); } } @@ -277,20 +268,20 @@ class ChatDetailsController extends State { name: result.fileName, ); } - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final success = await showFutureLoadingDialog( context: context, future: () => room.setAvatar(file), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).avatarHasBeenChanged))); } } void requestMoreMembersAction() async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final participants = await showFutureLoadingDialog( context: context, future: () => room.requestParticipants()); if (participants.error == null) { @@ -299,5 +290,11 @@ class ChatDetailsController extends State { } @override - Widget build(BuildContext context) => ChatDetailsView(this); + Widget build(BuildContext context) { + members ??= Matrix.of(context).client.getRoomById(roomId).getParticipants(); + return Container( + width: 360.0, + child: ChatDetailsView(this), + ); + } } diff --git a/lib/pages/chat_encryption_settings.dart b/lib/pages/chat_encryption_settings.dart index 263af4d0..282cc49f 100644 --- a/lib/pages/chat_encryption_settings.dart +++ b/lib/pages/chat_encryption_settings.dart @@ -3,12 +3,11 @@ import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/views/chat_encryption_settings_view.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; import 'key_verification_dialog.dart'; class ChatEncryptionSettings extends StatefulWidget { - final String id; - - const ChatEncryptionSettings(this.id, {Key key}) : super(key: key); + const ChatEncryptionSettings({Key key}) : super(key: key); @override ChatEncryptionSettingsController createState() => @@ -16,9 +15,10 @@ class ChatEncryptionSettings extends StatefulWidget { } class ChatEncryptionSettingsController extends State { + String get roomId => VRouter.of(context).pathParameters['roomid']; Future onSelected( BuildContext context, String action, DeviceKeys key) async { - final room = Matrix.of(context).client.getRoomById(widget.id); + final room = Matrix.of(context).client.getRoomById(roomId); final unblock = () async { if (key.blocked) { await key.setBlocked(false); diff --git a/lib/pages/chat_list.dart b/lib/pages/chat_list.dart index 8363c050..75baff73 100644 --- a/lib/pages/chat_list.dart +++ b/lib/pages/chat_list.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/utils/fluffy_share.dart'; import 'package:fluffychat/pages/views/chat_list_view.dart'; @@ -14,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:uni_links/uni_links.dart'; +import 'package:vrouter/vrouter.dart'; import '../main.dart'; import '../widgets/matrix.dart'; import '../utils/matrix_sdk_extensions.dart/matrix_file_extension.dart'; @@ -43,7 +44,7 @@ class ChatListController extends State { void _processIncomingSharedFiles(List files) { if (files?.isEmpty ?? true) return; - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/rooms'); final file = File(files.first.path); Matrix.of(context).shareContent = { @@ -57,7 +58,7 @@ class ChatListController extends State { void _processIncomingSharedText(String text) { if (text == null) return; - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/rooms'); if (text.toLowerCase().startsWith(AppConfig.inviteLinkPrefix) || (text.toLowerCase().startsWith(AppConfig.schemePrefix) && !RegExp(r'\s').hasMatch(text))) { @@ -74,7 +75,7 @@ class ChatListController extends State { if (text.toLowerCase().startsWith(AppConfig.inviteLinkPrefix) || (text.toLowerCase().startsWith(AppConfig.schemePrefix) && !RegExp(r'\s').hasMatch(text))) { - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/rooms'); UrlLauncher(context, text).openMatrixToUrl(); return; } @@ -158,7 +159,6 @@ class ChatListController extends State { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.ok; if (!confirmed) return; @@ -175,7 +175,6 @@ class ChatListController extends State { title: L10n.of(context).setStatus, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: L10n.of(context).statusExampleMessage, @@ -198,7 +197,7 @@ class ChatListController extends State { setStatus(); break; case PopupMenuAction.settings: - AdaptivePageLayout.of(context).pushNamed('/settings'); + VRouter.of(context).push('/settings'); break; case PopupMenuAction.invite: FluffyShare.share( @@ -207,10 +206,10 @@ class ChatListController extends State { context); break; case PopupMenuAction.newGroup: - AdaptivePageLayout.of(context).pushNamed('/newgroup'); + VRouter.of(context).push('/newgroup'); break; case PopupMenuAction.archive: - AdaptivePageLayout.of(context).pushNamed('/archive'); + VRouter.of(context).push('/archive'); break; } } diff --git a/lib/pages/chat_permissions_settings.dart b/lib/pages/chat_permissions_settings.dart index 4b8258dd..5b297794 100644 --- a/lib/pages/chat_permissions_settings.dart +++ b/lib/pages/chat_permissions_settings.dart @@ -1,7 +1,7 @@ import 'dart:developer'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:fluffychat/pages/views/chat_permissions_settings_view.dart'; import 'package:fluffychat/pages/permission_slider_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; @@ -10,11 +10,10 @@ import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:famedlysdk/famedlysdk.dart'; +import 'package:vrouter/vrouter.dart'; class ChatPermissionsSettings extends StatefulWidget { - final String roomId; - - const ChatPermissionsSettings(this.roomId, {Key key}) : super(key: key); + const ChatPermissionsSettings({Key key}) : super(key: key); @override ChatPermissionsSettingsController createState() => @@ -22,11 +21,12 @@ class ChatPermissionsSettings extends StatefulWidget { } class ChatPermissionsSettingsController extends State { + String get roomId => VRouter.of(context).pathParameters['roomid']; void editPowerLevel(BuildContext context, String key, int currentLevel, {String category}) async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); if (!room.canSendEvent(EventTypes.RoomPowerLevels)) { - AdaptivePageLayout.of(context) + ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(L10n.of(context).noPermission))); return; } @@ -54,14 +54,14 @@ class ChatPermissionsSettingsController extends State { Stream get onChanged => Matrix.of(context).client.onSync.stream.where( (e) => - (e?.rooms?.join?.containsKey(widget.roomId) ?? false) && - (e.rooms.join[widget.roomId]?.timeline?.events + (e?.rooms?.join?.containsKey(roomId) ?? false) && + (e.rooms.join[roomId]?.timeline?.events ?.any((s) => s.type == EventTypes.RoomPowerLevels) ?? false), ); void updateRoomAction(ServerCapabilities capabilities) async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final String roomVersion = room.getState(EventTypes.RoomCreate).content['room_version'] ?? '1'; final newVersion = await showConfirmationDialog( @@ -87,8 +87,8 @@ class ChatPermissionsSettingsController extends State { } await showFutureLoadingDialog( context: context, - future: () => room.client.upgradeRoom(widget.roomId, newVersion), - ).then((_) => AdaptivePageLayout.of(context).pop()); + future: () => room.client.upgradeRoom(roomId, newVersion), + ).then((_) => VRouter.of(context).pop()); } @override diff --git a/lib/pages/device_settings.dart b/lib/pages/device_settings.dart index e0093f56..bb19320a 100644 --- a/lib/pages/device_settings.dart +++ b/lib/pages/device_settings.dart @@ -33,7 +33,6 @@ class DevicesSettingsController extends State { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.cancel) return; final matrix = Matrix.of(context); @@ -68,7 +67,6 @@ class DevicesSettingsController extends State { title: L10n.of(context).changeDeviceName, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: device.displayName, diff --git a/lib/pages/homeserver_picker.dart b/lib/pages/homeserver_picker.dart index ecf01b2d..1a5b3cd7 100644 --- a/lib/pages/homeserver_picker.dart +++ b/lib/pages/homeserver_picker.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/views/homeserver_picker_view.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -7,6 +6,7 @@ import 'package:fluffychat/config/setting_keys.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter/material.dart'; import '../utils/localized_exception_extension.dart'; +import 'package:vrouter/vrouter.dart'; class HomeserverPicker extends StatefulWidget { @override @@ -51,10 +51,11 @@ class HomeserverPickerController extends State { AppConfig.jitsiInstance = jitsi; } - await AdaptivePageLayout.of(context) - .pushNamed(AppConfig.enableRegistration ? '/signup' : '/login'); + VRouter.of(context).push( + AppConfig.enableRegistration ? '/signup' : '/login', + historyState: {'/home': '/signup'}); } catch (e) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text((e as Object).toLocalizedString(context)))); } finally { if (mounted) { diff --git a/lib/pages/image_viewer.dart b/lib/pages/image_viewer.dart index c3ca1287..eba2a46d 100644 --- a/lib/pages/image_viewer.dart +++ b/lib/pages/image_viewer.dart @@ -1,9 +1,9 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/pages/views/image_viewer_view.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; import '../utils/matrix_sdk_extensions.dart/event_extension.dart'; @@ -21,7 +21,7 @@ class ImageViewerController extends State { /// Forward this image to another room. void forwardAction() { Matrix.of(context).shareContent = widget.event.content; - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/rooms'); } /// Open this file with a system call. diff --git a/lib/pages/invitation_selection.dart b/lib/pages/invitation_selection.dart index 5c28acf5..f76b5740 100644 --- a/lib/pages/invitation_selection.dart +++ b/lib/pages/invitation_selection.dart @@ -1,19 +1,17 @@ import 'dart:async'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; - import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/views/invitation_selection_view.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:vrouter/vrouter.dart'; import '../utils/localized_exception_extension.dart'; class InvitationSelection extends StatefulWidget { - final String roomId; - const InvitationSelection(this.roomId, {Key key}) : super(key: key); + const InvitationSelection({Key key}) : super(key: key); @override InvitationSelectionController createState() => @@ -27,9 +25,11 @@ class InvitationSelectionController extends State { List foundProfiles = []; Timer coolDown; + String get roomId => VRouter.of(context).pathParameters['roomid']; + Future> getContacts(BuildContext context) async { final client = Matrix.of(context).client; - final room = client.getRoomById(widget.roomId); + final room = client.getRoomById(roomId); final participants = await room.requestParticipants(); participants.removeWhere( (u) => ![Membership.join, Membership.invite].contains(u.membership), @@ -56,13 +56,13 @@ class InvitationSelectionController extends State { } void inviteAction(BuildContext context, String id) async { - final room = Matrix.of(context).client.getRoomById(widget.roomId); + final room = Matrix.of(context).client.getRoomById(roomId); final success = await showFutureLoadingDialog( context: context, future: () => room.invite(id), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar(SnackBar( + ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(L10n.of(context).contactHasBeenInvitedToTheGroup))); } } @@ -89,7 +89,7 @@ class InvitationSelectionController extends State { try { response = await matrix.client.searchUserDirectory(text, limit: 10); } catch (e) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text((e as Object).toLocalizedString(context)))); return; } finally { @@ -105,7 +105,7 @@ class InvitationSelectionController extends State { } final participants = Matrix.of(context) .client - .getRoomById(widget.roomId) + .getRoomById(roomId) .getParticipants() .where((user) => [Membership.join, Membership.invite].contains(user.membership)) diff --git a/lib/pages/key_verification_dialog.dart b/lib/pages/key_verification_dialog.dart index 61e5ece6..c8bde86b 100644 --- a/lib/pages/key_verification_dialog.dart +++ b/lib/pages/key_verification_dialog.dart @@ -16,13 +16,11 @@ class KeyVerificationDialog extends StatefulWidget { context: context, barrierDismissible: true, builder: (context) => this, - useRootNavigator: false, ) : showDialog( context: context, barrierDismissible: true, builder: (context) => this, - useRootNavigator: false, ); final KeyVerification request; @@ -100,7 +98,6 @@ class _KeyVerificationPageState extends State { await showOkAlertDialog( context: context, message: L10n.of(context).incorrectPassphraseOrKey, - useRootNavigator: false, ); } }; @@ -187,7 +184,6 @@ class _KeyVerificationPageState extends State { onPressed: () async { final result = await showOkCancelAlertDialog( context: context, - useRootNavigator: false, title: L10n.of(context).verifyManual, message: key.ed25519Key.beautified, ); diff --git a/lib/pages/login.dart b/lib/pages/login.dart index fa5b52d9..1da03125 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -119,7 +119,6 @@ class LoginController extends State { title: L10n.of(context).enterAnEmailAddress, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: L10n.of(context).enterAnEmailAddress, @@ -143,7 +142,6 @@ class LoginController extends State { title: L10n.of(context).weSentYouAnEmail, message: L10n.of(context).pleaseClickOnLink, okLabel: L10n.of(context).iHaveClickedOnLink, - useRootNavigator: false, ); if (ok == null) return; final password = await showTextInputDialog( @@ -151,7 +149,6 @@ class LoginController extends State { title: L10n.of(context).chooseAStrongPassword, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: '******', @@ -178,7 +175,7 @@ class LoginController extends State { ), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).passwordHasBeenChanged))); } } diff --git a/lib/pages/new_group.dart b/lib/pages/new_group.dart index 2173a1f0..02c1927d 100644 --- a/lib/pages/new_group.dart +++ b/lib/pages/new_group.dart @@ -1,9 +1,9 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart' as sdk; import 'package:fluffychat/pages/views/new_group_view.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; class NewGroup extends StatefulWidget { @override @@ -31,11 +31,8 @@ class NewGroupController extends State { name: controller.text.isNotEmpty ? controller.text : null, ), ); - AdaptivePageLayout.of(context).popUntilIsFirst(); - if (roomID != null) { - await AdaptivePageLayout.of(context).pushNamed('/rooms/${roomID.result}'); - await AdaptivePageLayout.of(context) - .pushNamed('/rooms/${roomID.result}/invite'); + if (roomID.error == null) { + VRouter.of(context).push('/rooms/${roomID.result}/invite'); } } diff --git a/lib/pages/new_private_chat.dart b/lib/pages/new_private_chat.dart index 62198ebf..1421f00e 100644 --- a/lib/pages/new_private_chat.dart +++ b/lib/pages/new_private_chat.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/utils/fluffy_share.dart'; import 'package:fluffychat/pages/views/new_private_chat_view.dart'; @@ -8,6 +7,7 @@ import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:vrouter/vrouter.dart'; class NewPrivateChat extends StatefulWidget { @override @@ -47,8 +47,7 @@ class NewPrivateChatController extends State { ); if (roomID.error == null) { - await AdaptivePageLayout.of(context) - .popAndPushNamed('/rooms/${roomID.result}'); + VRouter.of(context).push('/rooms/${roomID.result}'); } } diff --git a/lib/pages/permission_slider_dialog.dart b/lib/pages/permission_slider_dialog.dart index fe1fac59..c1016e19 100644 --- a/lib/pages/permission_slider_dialog.dart +++ b/lib/pages/permission_slider_dialog.dart @@ -14,12 +14,10 @@ class PermissionSliderDialog extends StatefulWidget { ? showCupertinoDialog( context: context, builder: (context) => this, - useRootNavigator: false, ) : showDialog( context: context, builder: (context) => this, - useRootNavigator: false, ); final int initialPermission; diff --git a/lib/pages/search.dart b/lib/pages/search.dart index 8bc8f1f7..c9d60ae0 100644 --- a/lib/pages/search.dart +++ b/lib/pages/search.dart @@ -1,18 +1,17 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; +import 'package:vrouter/vrouter.dart'; import 'views/search_view.dart'; class Search extends StatefulWidget { - final String alias; - - const Search({Key key, this.alias}) : super(key: key); + const Search({Key key}) : super(key: key); @override SearchController createState() => SearchController(); @@ -24,6 +23,7 @@ class SearchController extends State { String lastServer; Timer _coolDown; String genericSearchTerm; + String alias; void search(String query) async { setState(() => null); @@ -64,7 +64,6 @@ class SearchController extends State { title: '${room.name} (${room.numJoinedMembers ?? 0})', message: room.topic ?? L10n.of(context).noDescription, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.cancel) { return; @@ -78,8 +77,7 @@ class SearchController extends State { ), ); if (success.error == null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${success.result}'); + VRouter.of(context).push('/rooms/${success.result}'); } } @@ -91,7 +89,6 @@ class SearchController extends State { context: context, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( prefixText: 'https://', @@ -133,11 +130,9 @@ class SearchController extends State { } @override - void initState() { - genericSearchTerm = widget.alias; - super.initState(); + Widget build(BuildContext context) { + alias = VRouter.of(context).queryParameters['query']; + genericSearchTerm = alias; + return SearchView(this); } - - @override - Widget build(BuildContext context) => SearchView(this); } diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index cb9995cf..3b64f529 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:file_picker_cross/file_picker_cross.dart'; @@ -13,6 +13,7 @@ import 'package:flutter_app_lock/flutter_app_lock.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:vrouter/vrouter.dart'; import 'views/settings_view.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; @@ -40,7 +41,6 @@ class SettingsController extends State { title: L10n.of(context).areYouSureYouWantToLogout, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.cancel) { return; @@ -58,7 +58,6 @@ class SettingsController extends State { title: L10n.of(context).changePassword, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: L10n.of(context).pleaseEnterYourPassword, @@ -82,7 +81,7 @@ class SettingsController extends State { .changePassword(input.last, oldPassword: input.first), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).passwordHasBeenChanged))); } } @@ -94,7 +93,6 @@ class SettingsController extends State { message: L10n.of(context).deactivateAccountWarning, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.cancel) { return; @@ -104,7 +102,6 @@ class SettingsController extends State { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) == OkCancelResult.cancel) { return; @@ -114,7 +111,6 @@ class SettingsController extends State { title: L10n.of(context).pleaseEnterYourPassword, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( obscureText: true, @@ -145,7 +141,6 @@ class SettingsController extends State { title: L10n.of(context).editJitsiInstance, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( initialText: AppConfig.jitsiInstance.replaceFirst(prefix, ''), @@ -169,7 +164,6 @@ class SettingsController extends State { title: L10n.of(context).editDisplayname, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( initialText: profile?.displayname ?? @@ -234,7 +228,6 @@ class SettingsController extends State { title: L10n.of(context).askSSSSCache, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: L10n.of(context).passphraseOrKey, @@ -266,7 +259,6 @@ class SettingsController extends State { context: context, message: L10n.of(context).cachedKeys, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); setState(() { crossSigningCachedFuture = null; @@ -279,7 +271,6 @@ class SettingsController extends State { context: context, message: L10n.of(context).incorrectPassphraseOrKey, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); } } @@ -296,7 +287,6 @@ class SettingsController extends State { title: L10n.of(context).pleaseChooseAPasscode, message: L10n.of(context).pleaseEnter4Digits, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( validator: (text) { @@ -333,7 +323,6 @@ class SettingsController extends State { isDestructiveAction: true, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, )) { await BootstrapDialog( client: Matrix.of(context).client, @@ -351,7 +340,7 @@ class SettingsController extends State { await BootstrapDialog( client: Matrix.of(context).client, ).show(context); - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/rooms'); } @override diff --git a/lib/pages/settings_3pid.dart b/lib/pages/settings_3pid.dart index 7fb5a2e6..200dd77f 100644 --- a/lib/pages/settings_3pid.dart +++ b/lib/pages/settings_3pid.dart @@ -21,7 +21,6 @@ class Settings3PidController extends State { title: L10n.of(context).enterAnEmailAddress, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( hintText: L10n.of(context).enterAnEmailAddress, @@ -45,7 +44,6 @@ class Settings3PidController extends State { title: L10n.of(context).weSentYouAnEmail, message: L10n.of(context).pleaseClickOnLink, okLabel: L10n.of(context).iHaveClickedOnLink, - useRootNavigator: false, ); if (ok == null) return; final success = await showFutureLoadingDialog( @@ -70,7 +68,6 @@ class Settings3PidController extends State { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, ) != OkCancelResult.ok) { return; diff --git a/lib/pages/settings_emotes.dart b/lib/pages/settings_emotes.dart index 2db462c1..89d33b4f 100644 --- a/lib/pages/settings_emotes.dart +++ b/lib/pages/settings_emotes.dart @@ -1,5 +1,5 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:file_picker_cross/file_picker_cross.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -138,7 +138,6 @@ class EmotesSettingsController extends State { context: context, message: L10n.of(context).emoteExists, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); return; } @@ -148,7 +147,6 @@ class EmotesSettingsController extends State { context: context, message: L10n.of(context).emoteInvalid, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); return; } @@ -187,7 +185,6 @@ class EmotesSettingsController extends State { context: context, message: L10n.of(context).emoteWarnNeedToPick, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); return; } @@ -198,7 +195,6 @@ class EmotesSettingsController extends State { context: context, message: L10n.of(context).emoteExists, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); return; } @@ -207,7 +203,6 @@ class EmotesSettingsController extends State { context: context, message: L10n.of(context).emoteInvalid, okLabel: L10n.of(context).ok, - useRootNavigator: false, ); return; } @@ -222,7 +217,7 @@ class EmotesSettingsController extends State { void emoteImagePickerAction(TextEditingController controller) async { if (kIsWeb) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).notSupportedInWeb))); return; } diff --git a/lib/pages/settings_multiple_emotes.dart b/lib/pages/settings_multiple_emotes.dart index 06d9fb77..e35e3626 100644 --- a/lib/pages/settings_multiple_emotes.dart +++ b/lib/pages/settings_multiple_emotes.dart @@ -1,11 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; import 'views/settings_multiple_emotes_view.dart'; class MultipleEmotesSettings extends StatefulWidget { - final String roomId; - - MultipleEmotesSettings(this.roomId, {Key key}) : super(key: key); + MultipleEmotesSettings({Key key}) : super(key: key); @override MultipleEmotesSettingsController createState() => @@ -13,6 +12,7 @@ class MultipleEmotesSettings extends StatefulWidget { } class MultipleEmotesSettingsController extends State { + String get roomId => VRouter.of(context).pathParameters['roomid']; @override Widget build(BuildContext context) => MultipleEmotesSettingsView(this); } diff --git a/lib/pages/sign_up.dart b/lib/pages/sign_up.dart index db0451b6..c998c653 100644 --- a/lib/pages/sign_up.dart +++ b/lib/pages/sign_up.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:file_picker_cross/file_picker_cross.dart'; import 'package:fluffychat/config/app_config.dart'; @@ -17,6 +16,7 @@ import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:uni_links/uni_links.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:universal_html/html.dart' as html; +import 'package:vrouter/vrouter.dart'; import '../main.dart'; @@ -29,7 +29,7 @@ class SignUpController extends State { final TextEditingController usernameController = TextEditingController(); String usernameError; bool loading = false; - MatrixFile avatar; + static MatrixFile avatar; LoginTypes _loginTypes; StreamSubscription _intentDataStreamSubscription; @@ -48,7 +48,7 @@ class SignUpController extends State { void _processIncomingUris(String text) async { if (text == null || !text.startsWith(AppConfig.appOpenUrlScheme)) return; - AdaptivePageLayout.of(context).popUntilIsFirst(); + VRouter.of(context).push('/home'); final token = Uri.parse(text).queryParameters['loginToken']; if (token != null) _loginWithToken(token); } @@ -151,9 +151,10 @@ class SignUpController extends State { return setState(() => loading = false); } setState(() => loading = false); - await AdaptivePageLayout.of(context).pushNamed( + + VRouter.of(context).push( '/signup/password/${Uri.encodeComponent(preferredUsername)}/${Uri.encodeComponent(usernameController.text)}', - arguments: avatar, + queryParameters: {'displayname': usernameController.text}, ); } diff --git a/lib/pages/sign_up_password.dart b/lib/pages/sign_up_password.dart index d8ae631e..37f780ea 100644 --- a/lib/pages/sign_up_password.dart +++ b/lib/pages/sign_up_password.dart @@ -1,21 +1,20 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:email_validator/email_validator.dart'; import 'package:famedlysdk/famedlysdk.dart'; +import 'package:fluffychat/pages/sign_up.dart'; import 'package:fluffychat/utils/get_client_secret.dart'; import 'package:fluffychat/pages/views/sign_up_password_view.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:vrouter/vrouter.dart'; import '../utils/platform_infos.dart'; class SignUpPassword extends StatefulWidget { - final MatrixFile avatar; - final String username; - final String displayname; - const SignUpPassword(this.username, {this.avatar, this.displayname}); + const SignUpPassword(); @override SignUpPasswordController createState() => SignUpPasswordController(); } @@ -70,8 +69,10 @@ class SignUpPasswordController extends State { } } final waitForLogin = matrix.client.onLoginStateChanged.stream.first; + final username = VRouter.of(context).pathParameters['username']; + await matrix.client.uiaRequestBackground((auth) => matrix.client.register( - username: widget.username, + username: username, password: passwordController.text, initialDeviceDisplayName: PlatformInfos.clientName, auth: auth, @@ -91,19 +92,20 @@ class SignUpPasswordController extends State { } await matrix.client.onLoginStateChanged.stream .firstWhere((l) => l == LoginState.logged); - // tchncs.de - try { - await matrix.client - .setDisplayName(matrix.client.userID, widget.displayname); - } catch (exception) { - AdaptivePageLayout.of(context).showSnackBar( - SnackBar(content: Text(L10n.of(context).couldNotSetDisplayname))); - } - if (widget.avatar != null) { + final displayname = VRouter.of(context).queryParameters['displayname']; + if (displayname != null) { try { - await matrix.client.setAvatar(widget.avatar); + await matrix.client.setDisplayName(matrix.client.userID, displayname); } catch (exception) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(L10n.of(context).couldNotSetDisplayname))); + } + } + if (SignUpController.avatar != null) { + try { + await matrix.client.setAvatar(SignUpController.avatar); + } catch (exception) { + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).couldNotSetAvatar))); } } diff --git a/lib/pages/user_bottom_sheet.dart b/lib/pages/user_bottom_sheet.dart index dd161d15..0e7c2203 100644 --- a/lib/pages/user_bottom_sheet.dart +++ b/lib/pages/user_bottom_sheet.dart @@ -1,11 +1,12 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/permission_slider_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; +import 'package:vrouter/vrouter.dart'; import 'views/user_bottom_sheet_view.dart'; @@ -30,7 +31,6 @@ class UserBottomSheetController extends State { final Function _askConfirmation = () async => (await showOkCancelAlertDialog( context: context, - useRootNavigator: false, title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).no, @@ -83,8 +83,7 @@ class UserBottomSheetController extends State { break; case 'message': final roomId = await widget.user.startDirectChat(); - await AdaptivePageLayout.of(widget.outerContext) - .pushNamedAndRemoveUntilIsFirst('/rooms/$roomId'); + VRouter.of(widget.outerContext).push('/rooms/$roomId'); Navigator.of(context, rootNavigator: false).pop(); break; } diff --git a/lib/pages/views/chat_details_view.dart b/lib/pages/views/chat_details_view.dart index f873ef60..f2bc343a 100644 --- a/lib/pages/views/chat_details_view.dart +++ b/lib/pages/views/chat_details_view.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat_details.dart'; import 'package:fluffychat/widgets/avatar.dart'; @@ -15,6 +14,7 @@ import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix_link_text/link_text.dart'; +import 'package:vrouter/vrouter.dart'; import '../../utils/url_launcher.dart'; @@ -25,12 +25,10 @@ class ChatDetailsView 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.roomId); if (room == null) { return Scaffold( appBar: AppBar( - leading: BackButton(), title: Text(L10n.of(context).oopsSomethingWentWrong), ), body: Center( @@ -52,8 +50,12 @@ class ChatDetailsView extends StatelessWidget { headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => [ SliverAppBar( + leading: IconButton( + icon: Icon(Icons.close_outlined), + onPressed: () => + VRouter.of(context).push('/rooms/${controller.roomId}'), + ), elevation: Theme.of(context).appBarTheme.elevation, - leading: BackButton(), expandedHeight: 300.0, floating: true, pinned: true, @@ -308,8 +310,8 @@ class ChatDetailsView extends StatelessWidget { foregroundColor: Colors.grey, child: Icon(Icons.edit_attributes_outlined), ), - onTap: () => AdaptivePageLayout.of(context) - .pushNamed('/rooms/${room.id}/permissions'), + onTap: () => VRouter.of(context).push( + '/rooms/${room.id}/details/permissions'), ), Divider(thickness: 1), ListTile( @@ -334,8 +336,8 @@ class ChatDetailsView extends StatelessWidget { radius: Avatar.defaultSize / 2, child: Icon(Icons.add_outlined), ), - onTap: () => AdaptivePageLayout.of(context) - .pushNamed('/rooms/${room.id}/invite'), + onTap: () => VRouter.of(context) + .push('/rooms/${room.id}/invite'), ) : Container(), ], diff --git a/lib/pages/views/chat_encryption_settings_view.dart b/lib/pages/views/chat_encryption_settings_view.dart index f66d31a6..0a86ac6b 100644 --- a/lib/pages/views/chat_encryption_settings_view.dart +++ b/lib/pages/views/chat_encryption_settings_view.dart @@ -5,6 +5,7 @@ import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/layouts/max_width_body.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:vrouter/vrouter.dart'; import '../../utils/matrix_sdk_extensions.dart/device_extension.dart'; class ChatEncryptionSettingsView extends StatelessWidget { @@ -15,11 +16,15 @@ class ChatEncryptionSettingsView extends StatelessWidget { @override Widget build(BuildContext context) { - final room = Matrix.of(context).client.getRoomById(controller.widget.id); + final room = Matrix.of(context).client.getRoomById(controller.roomId); return Scaffold( appBar: AppBar( - leading: BackButton(), + leading: IconButton( + icon: Icon(Icons.close_outlined), + onPressed: () => + VRouter.of(context).push('/rooms/${controller.roomId}'), + ), title: Text(L10n.of(context).tapOnDeviceToVerify), bottom: PreferredSize( preferredSize: Size.fromHeight(56), diff --git a/lib/pages/views/chat_list_view.dart b/lib/pages/views/chat_list_view.dart index c36794ef..5011cfce 100644 --- a/lib/pages/views/chat_list_view.dart +++ b/lib/pages/views/chat_list_view.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/chat_list.dart'; import 'package:fluffychat/widgets/connection_status_header.dart'; @@ -7,6 +6,7 @@ import 'package:flutter/cupertino.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; import '../../widgets/matrix.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -28,7 +28,9 @@ class ChatListView extends StatelessWidget { return Scaffold( appBar: AppBar( elevation: - AdaptivePageLayout.of(context).columnMode(context) ? 1 : null, + MediaQuery.of(context).size.width > AppConfig.columnWidth * 2 + ? 1 + : null, leading: selectMode == SelectMode.normal ? null : IconButton( @@ -82,8 +84,8 @@ class ChatListView extends StatelessWidget { IconButton( icon: Icon(Icons.search_outlined), tooltip: L10n.of(context).search, - onPressed: () => AdaptivePageLayout.of(context) - .pushNamed('/search'), + onPressed: () => + VRouter.of(context).push('/search'), ), PopupMenuButton( onSelected: controller.onPopupMenuSelect, @@ -223,8 +225,8 @@ class ChatListView extends StatelessWidget { ]), floatingActionButton: selectMode == SelectMode.normal ? FloatingActionButton( - onPressed: () => AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/newprivatechat'), + onPressed: () => + VRouter.of(context).push('/newprivatechat'), child: Icon(CupertinoIcons.chat_bubble), ) : null, diff --git a/lib/pages/views/chat_permissions_settings_view.dart b/lib/pages/views/chat_permissions_settings_view.dart index 90213f26..d2faa258 100644 --- a/lib/pages/views/chat_permissions_settings_view.dart +++ b/lib/pages/views/chat_permissions_settings_view.dart @@ -26,7 +26,7 @@ class ChatPermissionsSettingsView extends StatelessWidget { stream: controller.onChanged, builder: (context, _) { final room = - Matrix.of(context).client.getRoomById(controller.widget.roomId); + Matrix.of(context).client.getRoomById(controller.roomId); final powerLevelsContent = Map.from( room.getState(EventTypes.RoomPowerLevels).content); final powerLevels = Map.from(powerLevelsContent) diff --git a/lib/pages/views/chat_view.dart b/lib/pages/views/chat_view.dart index 2654d243..ed2d196c 100644 --- a/lib/pages/views/chat_view.dart +++ b/lib/pages/views/chat_view.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'dart:ui'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/pages/chat.dart'; @@ -28,6 +27,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:swipe_to_action/swipe_to_action.dart'; +import 'package:vrouter/vrouter.dart'; class ChatView extends StatelessWidget { final ChatController controller; @@ -38,7 +38,7 @@ class ChatView extends StatelessWidget { Widget build(BuildContext context) { controller.matrix = Matrix.of(context); final client = controller.matrix.client; - controller.room ??= client.getRoomById(controller.widget.id); + controller.room ??= client.getRoomById(controller.roomId); if (controller.room == null) { return Scaffold( appBar: AppBar( @@ -49,7 +49,7 @@ class ChatView extends StatelessWidget { ), ); } - controller.matrix.client.activeRoomId = controller.widget.id; + controller.matrix.client.activeRoomId = controller.roomId; if (controller.room.membership == Membership.invite) { showFutureLoadingDialog( @@ -64,11 +64,7 @@ class ChatView extends StatelessWidget { onPressed: controller.clearSelectedEvents, tooltip: L10n.of(context).close, ) - : AdaptivePageLayout.of(context).columnMode(context) - ? null - : UnreadBadgeBackButton(roomId: controller.widget.id), - titleSpacing: - AdaptivePageLayout.of(context).columnMode(context) ? null : 0, + : UnreadBadgeBackButton(roomId: controller.roomId), title: controller.selectedEvents.isEmpty ? StreamBuilder( stream: controller.room.onUpdate.stream, @@ -88,15 +84,8 @@ class ChatView extends StatelessWidget { '${controller.room.directChatMatrixID} ', ), ) - : () => (!AdaptivePageLayout.of(context) - .columnMode(context) || - AdaptivePageLayout.of(context) - .viewDataStack - .length < - 3) - ? AdaptivePageLayout.of(context).pushNamed( - '/rooms/${controller.room.id}/details') - : null, + : () => VRouter.of(context) + .push('/rooms/${controller.room.id}/details'), title: Text( controller.room.getLocalizedDisplayname( MatrixLocals(L10n.of(context))), @@ -259,13 +248,7 @@ class ChatView extends StatelessWidget { final horizontalPadding = max( 0, (MediaQuery.of(context).size.width - - FluffyThemes.columnWidth * - (AdaptivePageLayout.of(context) - .currentViewData - ?.rightView != - null - ? 4.5 - : 3.5)) / + FluffyThemes.columnWidth * (3.5)) / 2) .toDouble(); diff --git a/lib/pages/views/empty_page_view.dart b/lib/pages/views/empty_page_view.dart index c6c07e7c..46d634a9 100644 --- a/lib/pages/views/empty_page_view.dart +++ b/lib/pages/views/empty_page_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; class EmptyPage extends StatelessWidget { + const EmptyPage({Key key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/pages/views/invitation_selection_view.dart b/lib/pages/views/invitation_selection_view.dart index 47dcc87e..fcc959c8 100644 --- a/lib/pages/views/invitation_selection_view.dart +++ b/lib/pages/views/invitation_selection_view.dart @@ -15,8 +15,7 @@ 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.roomId); final groupName = room.name?.isEmpty ?? false ? L10n.of(context).group : room.name; return Scaffold( diff --git a/lib/pages/views/new_private_chat_view.dart b/lib/pages/views/new_private_chat_view.dart index ee9f9e00..fb52c140 100644 --- a/lib/pages/views/new_private_chat_view.dart +++ b/lib/pages/views/new_private_chat_view.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:fluffychat/pages/new_private_chat.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/contacts_list.dart'; @@ -7,6 +6,7 @@ import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:famedlysdk/famedlysdk.dart'; +import 'package:vrouter/vrouter.dart'; class NewPrivateChatView extends StatelessWidget { final NewPrivateChatController controller; @@ -22,8 +22,7 @@ class NewPrivateChatView extends StatelessWidget { elevation: 0, actions: [ TextButton( - onPressed: () => AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/newgroup'), + onPressed: () => VRouter.of(context).push('/newgroup'), child: Text( L10n.of(context).createNewGroup, style: TextStyle(color: Theme.of(context).accentColor), diff --git a/lib/pages/views/search_view.dart b/lib/pages/views/search_view.dart index 2bbdae6c..bbc3bf78 100644 --- a/lib/pages/views/search_view.dart +++ b/lib/pages/views/search_view.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/contacts_list.dart'; @@ -8,6 +7,7 @@ import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; +import 'package:vrouter/vrouter.dart'; import '../../utils/localized_exception_extension.dart'; import '../search.dart'; @@ -32,21 +32,21 @@ class SearchView extends StatelessWidget { genericSearchTerm: controller.genericSearchTerm, ) .catchError((error) { - if (controller.widget.alias == null) { + if (controller.alias == null) { throw error; } return PublicRoomsResponse.fromJson({ 'chunk': [], }); }).then((PublicRoomsResponse res) { - if (controller.widget.alias != null && + if (controller.alias != null && !res.chunk.any((room) => - (room.aliases?.contains(controller.widget.alias) ?? false) || - room.canonicalAlias == controller.widget.alias)) { + (room.aliases?.contains(controller.alias) ?? false) || + room.canonicalAlias == controller.alias)) { // we have to tack on the original alias res.chunk.add(PublicRoom.fromJson({ - 'aliases': [controller.widget.alias], - 'name': controller.widget.alias, + 'aliases': [controller.alias], + 'name': controller.alias, })); } return res; @@ -238,8 +238,7 @@ class SearchView extends StatelessWidget { .startDirectChat(foundProfile.userId), ); if (roomID.error == null) { - await AdaptivePageLayout.of(context) - .popAndPushNamed('/rooms/${roomID.result}'); + VRouter.of(context).push('/rooms/${roomID.result}'); } }, leading: Avatar( diff --git a/lib/pages/views/settings_multiple_emotes_view.dart b/lib/pages/views/settings_multiple_emotes_view.dart index 896e5024..18a03e5a 100644 --- a/lib/pages/views/settings_multiple_emotes_view.dart +++ b/lib/pages/views/settings_multiple_emotes_view.dart @@ -1,9 +1,9 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:fluffychat/pages/settings_multiple_emotes.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:vrouter/vrouter.dart'; class MultipleEmotesSettingsView extends StatelessWidget { final MultipleEmotesSettingsController controller; @@ -12,8 +12,7 @@ class MultipleEmotesSettingsView 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.roomId); return Scaffold( appBar: AppBar( leading: BackButton(), @@ -45,13 +44,7 @@ class MultipleEmotesSettingsView extends StatelessWidget { return ListTile( title: Text(packName), onTap: () async { - await AdaptivePageLayout.of(context).pushNamed( - '/settings/emotes', - arguments: { - 'room': room, - 'stateKey': keys[i], - }, - ); + VRouter.of(context).push('/settings/emotes'); }, ); }); diff --git a/lib/pages/views/settings_view.dart b/lib/pages/views/settings_view.dart index 8feca874..16479487 100644 --- a/lib/pages/views/settings_view.dart +++ b/lib/pages/views/settings_view.dart @@ -1,5 +1,5 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:fluffychat/widgets/sentry_switch_list_tile.dart'; import 'package:fluffychat/widgets/settings_switch_list_tile.dart'; @@ -11,6 +11,7 @@ import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:vrouter/vrouter.dart'; import '../../widgets/content_banner.dart'; import '../../widgets/matrix.dart'; @@ -31,10 +32,6 @@ class SettingsView extends StatelessWidget { headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) => [ SliverAppBar( - leading: IconButton( - icon: Icon(Icons.close_outlined), - onPressed: () => AdaptivePageLayout.of(context).popUntilIsFirst(), - ), expandedHeight: 300.0, floating: true, pinned: true, @@ -85,8 +82,7 @@ class SettingsView extends StatelessWidget { ListTile( trailing: Icon(Icons.notifications_outlined), title: Text(L10n.of(context).notifications), - onTap: () => AdaptivePageLayout.of(context) - .pushNamed('/settings/notifications'), + onTap: () => VRouter.of(context).push('/settings/notifications'), ), Divider(thickness: 1), ListTile( @@ -100,8 +96,7 @@ class SettingsView extends StatelessWidget { ), ListTile( title: Text(L10n.of(context).changeTheme), - onTap: () => - AdaptivePageLayout.of(context).pushNamed('/settings/style'), + onTap: () => VRouter.of(context).push('/settings/style'), trailing: Icon(Icons.style_outlined), ), SettingsSwitchListTile( @@ -124,8 +119,7 @@ class SettingsView extends StatelessWidget { ), ListTile( title: Text(L10n.of(context).emoteSettings), - onTap: () => - AdaptivePageLayout.of(context).pushNamed('/settings/emotes'), + onTap: () => VRouter.of(context).push('/settings/emotes'), trailing: Icon(Icons.insert_emoticon_outlined), ), Divider(thickness: 1), @@ -154,14 +148,12 @@ class SettingsView extends StatelessWidget { ListTile( trailing: Icon(Icons.devices_other_outlined), title: Text(L10n.of(context).devices), - onTap: () => - AdaptivePageLayout.of(context).pushNamed('/settings/devices'), + onTap: () => VRouter.of(context).push('/settings/devices'), ), ListTile( trailing: Icon(Icons.block_outlined), title: Text(L10n.of(context).ignoredUsers), - onTap: () => - AdaptivePageLayout.of(context).pushNamed('/settings/ignore'), + onTap: () => VRouter.of(context).push('/settings/ignorelist'), ), SentrySwitchListTile(), Divider(thickness: 1), @@ -175,8 +167,7 @@ class SettingsView extends StatelessWidget { ListTile( trailing: Icon(Icons.email_outlined), title: Text(L10n.of(context).passwordRecovery), - onTap: () => - AdaptivePageLayout.of(context).pushNamed('/settings/3pid'), + onTap: () => VRouter.of(context).push('/settings/3pid'), ), ListTile( trailing: Icon(Icons.exit_to_app_outlined), @@ -215,7 +206,6 @@ class SettingsView extends StatelessWidget { title: L10n.of(context).yourPublicKey, message: client.fingerprintKey.beautified, okLabel: L10n.of(context).ok, - useRootNavigator: false, ), trailing: Icon(Icons.vpn_key_outlined), ), @@ -236,7 +226,7 @@ class SettingsView extends StatelessWidget { fontWeight: FontWeight.bold, ), ), - onTap: () => AdaptivePageLayout.of(context).pushNamed('/logs'), + onTap: () => VRouter.of(context).push('/logs'), ), ListTile( trailing: Icon(Icons.help_outlined), diff --git a/lib/pages/views/sign_up_view.dart b/lib/pages/views/sign_up_view.dart index 5f6bb25a..f32acde7 100644 --- a/lib/pages/views/sign_up_view.dart +++ b/lib/pages/views/sign_up_view.dart @@ -1,4 +1,4 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; +import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/pages/sign_up.dart'; import 'package:fluffychat/widgets/fluffy_banner.dart'; @@ -71,29 +71,29 @@ class SignUpView extends StatelessWidget { SizedBox(height: 8), ListTile( leading: CircleAvatar( - backgroundImage: controller.avatar == null + backgroundImage: SignUpController.avatar == null ? null - : MemoryImage(controller.avatar.bytes), - backgroundColor: controller.avatar == null + : MemoryImage(SignUpController.avatar.bytes), + backgroundColor: SignUpController.avatar == null ? Theme.of(context).brightness == Brightness.dark ? Color(0xff121212) : Colors.white : Theme.of(context).secondaryHeaderColor, - child: controller.avatar == null + child: SignUpController.avatar == null ? Icon(Icons.camera_alt_outlined, color: Theme.of(context).primaryColor) : null, ), - trailing: controller.avatar == null + trailing: SignUpController.avatar == null ? null : Icon( Icons.close, color: Colors.red, ), - title: Text(controller.avatar == null + title: Text(SignUpController.avatar == null ? L10n.of(context).setAProfilePicture : L10n.of(context).discardPicture), - onTap: controller.avatar == null + onTap: SignUpController.avatar == null ? controller.setAvatarAction : controller.resetAvatarAction, ), @@ -146,8 +146,7 @@ class SignUpView extends StatelessWidget { Theme.of(context).textTheme.bodyText1.color, elevation: 2, ), - onPressed: () => AdaptivePageLayout.of(context) - .pushNamed('/login'), + onPressed: () => context.vRouter.push('/login'), child: Text(L10n.of(context).login), ), ), diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart index 7f7bd88c..167bab49 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart @@ -22,7 +22,6 @@ import 'dart:convert'; import 'dart:io'; import 'dart:ui'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fcm_shared_isolate/fcm_shared_isolate.dart'; @@ -34,6 +33,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n_en.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:vrouter/vrouter.dart'; import 'platform_infos.dart'; import '../config/app_config.dart'; import '../config/setting_keys.dart'; @@ -51,7 +51,7 @@ class BackgroundPush { FlutterLocalNotificationsPlugin(); FluffyClient client; BuildContext context; - GlobalKey apl; + GlobalKey router; String _fcmToken; LoginState _loginState; L10n l10n; @@ -95,10 +95,10 @@ class BackgroundPush { } factory BackgroundPush(FluffyClient _client, BuildContext _context, - GlobalKey _apl) { + GlobalKey router) { final instance = BackgroundPush.clientOnly(_client); instance.context = _context; - instance.apl = _apl; + instance.router = router; instance.fullInit(); return instance; } @@ -235,7 +235,7 @@ class BackgroundPush { if (details == null || !details.didNotificationLaunchApp || _wentToRoomOnStartup || - apl == null) { + router == null) { return; } _wentToRoomOnStartup = true; @@ -249,7 +249,7 @@ class BackgroundPush { } if (await store.getItemBool(SettingKeys.showNoGoogle, true)) { await loadLocale(); - apl.currentState.showSnackBar(SnackBar( + ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( PlatformInfos.isAndroid ? l10n.noGoogleServicesWarning @@ -280,10 +280,10 @@ class BackgroundPush { Future goToRoom(String roomId) async { try { Logs().v('[Push] Attempting to go to room $roomId...'); - if (apl == null) { + if (router == null) { return; } - await apl.currentState.pushNamedAndRemoveUntilIsFirst('/rooms/$roomId'); + router.currentState.push('/rooms/$roomId'); } catch (e, s) { Logs().e('[Push] Failed to open room', e, s); } diff --git a/lib/utils/fluffy_share.dart b/lib/utils/fluffy_share.dart index 59a409f9..afcda4ea 100644 --- a/lib/utils/fluffy_share.dart +++ b/lib/utils/fluffy_share.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -13,7 +12,7 @@ abstract class FluffyShare { await Clipboard.setData( ClipboardData(text: text), ); - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(L10n.of(context).copiedToClipboard))); return; } diff --git a/lib/utils/platform_infos.dart b/lib/utils/platform_infos.dart index 98874757..b818a02d 100644 --- a/lib/utils/platform_infos.dart +++ b/lib/utils/platform_infos.dart @@ -43,7 +43,6 @@ abstract class PlatformInfos { final version = await PlatformInfos.getVersion(); showAboutDialog( context: context, - useRootNavigator: false, children: [ Text('Version: $version'), OutlinedButton( diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart index 7da17221..733262ee 100644 --- a/lib/utils/url_launcher.dart +++ b/lib/utils/url_launcher.dart @@ -1,11 +1,12 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:vrouter/vrouter.dart'; class UrlLauncher { final String url; @@ -60,11 +61,10 @@ class UrlLauncher { if (room != null) { // we have the room, so....just open it if (event != null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${room.id}/$event'); + VRouter.of(context) + .push('/rooms/${room.id}', queryParameters: {'event': event}); } else { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${room.id}'); + VRouter.of(context).push('/rooms/${room.id}'); } return; } @@ -72,7 +72,6 @@ class UrlLauncher { if (await showOkCancelAlertDialog( context: context, title: 'Join room $roomIdOrAlias', - useRootNavigator: false, ) == OkCancelResult.ok) { roomId = roomIdOrAlias; @@ -89,16 +88,15 @@ class UrlLauncher { context: context, future: () => Future.delayed(const Duration(seconds: 2))); if (event != null) { - await AdaptivePageLayout.of(context).pushNamedAndRemoveUntilIsFirst( - '/rooms/${response.result}/$event'); + VRouter.of(context).push('/rooms/${response.result}/$event'); } else { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${response.result}'); + VRouter.of(context).push('/rooms/${response.result}'); } } } else { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/search/$roomIdOrAlias'); + VRouter.of(context).push('/search', queryParameters: { + if (roomIdOrAlias != null) 'query': roomIdOrAlias + }); } } else if (identityParts.primaryIdentifier.sigil == '@') { final user = User( @@ -107,8 +105,7 @@ class UrlLauncher { ); var roomId = matrix.client.getDirectChatFromUserId(user.id); if (roomId != null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/$roomId'); + VRouter.of(context).push('/rooms/$roomId'); return; } @@ -116,7 +113,6 @@ class UrlLauncher { if (await showOkCancelAlertDialog( context: context, title: 'Message user ${user.id}', - useRootNavigator: false, ) == OkCancelResult.ok) { roomId = (await showFutureLoadingDialog( @@ -126,8 +122,7 @@ class UrlLauncher { .result; if (roomId != null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/$roomId'); + VRouter.of(context).push('/rooms/$roomId'); } } } diff --git a/lib/widgets/chat_settings_popup_menu.dart b/lib/widgets/chat_settings_popup_menu.dart index 134cec10..38dfe66a 100644 --- a/lib/widgets/chat_settings_popup_menu.dart +++ b/lib/widgets/chat_settings_popup_menu.dart @@ -1,12 +1,13 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; +import 'package:vrouter/vrouter.dart'; import 'matrix.dart'; class ChatSettingsPopupMenu extends StatefulWidget { @@ -68,7 +69,6 @@ class _ChatSettingsPopupMenuState extends State { case 'leave': final confirmed = await showOkCancelAlertDialog( context: context, - useRootNavigator: false, title: L10n.of(context).areYouSure, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, @@ -77,8 +77,7 @@ class _ChatSettingsPopupMenuState extends State { final success = await showFutureLoadingDialog( context: context, future: () => widget.room.leave()); if (success.error == null) { - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveAllOthers('/'); + VRouter.of(context).push('/rooms'); } } break; @@ -95,12 +94,7 @@ class _ChatSettingsPopupMenuState extends State { widget.room.setPushRuleState(PushRuleState.notify)); break; case 'details': - if (!AdaptivePageLayout.of(context).columnMode(context) || - AdaptivePageLayout.of(context).viewDataStack.length < 3) { - await AdaptivePageLayout.of(context) - .pushNamed('/rooms/${widget.room.id}/details'); - } - + VRouter.of(context).push('/rooms/${widget.room.id}/details'); break; } }, diff --git a/lib/widgets/contacts_list.dart b/lib/widgets/contacts_list.dart index 80da865e..ee3a7ecd 100644 --- a/lib/widgets/contacts_list.dart +++ b/lib/widgets/contacts_list.dart @@ -4,9 +4,9 @@ import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; +import 'package:vrouter/vrouter.dart'; import '../utils/matrix_sdk_extensions.dart/client_presence_extension.dart'; import '../utils/matrix_sdk_extensions.dart/presence_extension.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; class ContactsList extends StatefulWidget { final TextEditingController searchController; @@ -102,9 +102,8 @@ class _ContactListTile extends StatelessWidget { fontWeight: FontWeight.bold, ) : null), - onTap: () => AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst( - '/rooms/${Matrix.of(context).client.getDirectChatFromUserId(contact.senderId)}'), + onTap: () => VRouter.of(context).push( + '/rooms/${Matrix.of(context).client.getDirectChatFromUserId(contact.senderId)}'), ); }); } diff --git a/lib/widgets/encryption_button.dart b/lib/widgets/encryption_button.dart index 4d6242d7..f683ee84 100644 --- a/lib/widgets/encryption_button.dart +++ b/lib/widgets/encryption_button.dart @@ -1,12 +1,12 @@ import 'dart:async'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; +import 'package:vrouter/vrouter.dart'; import 'matrix.dart'; class EncryptionButton extends StatefulWidget { @@ -21,14 +21,13 @@ class _EncryptionButtonState extends State { void _enableEncryptionAction() async { if (widget.room.encrypted) { - await AdaptivePageLayout.of(context) - .pushNamed('/rooms/${widget.room.id}/encryption'); + VRouter.of(context).push('/rooms/${widget.room.id}/encryption'); return; } if (widget.room.joinRules == JoinRules.public) { await showOkAlertDialog( context: context, - useRootNavigator: false, + okLabel: L10n.of(context).ok, message: L10n.of(context).noEncryptionForPublicRooms, ); @@ -36,7 +35,7 @@ class _EncryptionButtonState extends State { } if (await showOkCancelAlertDialog( context: context, - useRootNavigator: false, + title: L10n.of(context).enableEncryption, message: widget.room.client.encryptionEnabled ? L10n.of(context).enableEncryptionWarning diff --git a/lib/widgets/event_content/audio_player.dart b/lib/widgets/event_content/audio_player.dart index e5a27b0c..1788f001 100644 --- a/lib/widgets/event_content/audio_player.dart +++ b/lib/widgets/event_content/audio_player.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:audioplayers/audioplayers.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/utils/sentry_controller.dart'; @@ -95,7 +94,7 @@ class _AudioPlayerState extends State { _playAction(); } catch (e, s) { Logs().v('Could not download audio file', e, s); - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(e.toLocalizedString(context)), ), @@ -135,7 +134,7 @@ class _AudioPlayerState extends State { onPlayerStateChanged ??= audioPlayer.onPlayerStateChanged .listen((_) => setState(() => null)); onPlayerError ??= audioPlayer.onPlayerError.listen((e) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(L10n.of(context).oopsSomethingWentWrong), ), diff --git a/lib/widgets/event_content/message_content.dart b/lib/widgets/event_content/message_content.dart index a35d07a1..a2f6d129 100644 --- a/lib/widgets/event_content/message_content.dart +++ b/lib/widgets/event_content/message_content.dart @@ -1,4 +1,3 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/encryption/utils/key_verification.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/widgets/event_content/audio_player.dart'; @@ -27,7 +26,7 @@ class MessageContent extends StatelessWidget { void _verifyOrRequestKey(BuildContext context) async { if (event.content['can_request_session'] != true) { - AdaptivePageLayout.of(context).showSnackBar(SnackBar( + ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( event.type == EventTypes.Encrypted ? L10n.of(context).needPantalaimonWarning @@ -61,7 +60,7 @@ class MessageContent extends StatelessWidget { future: () => event.requestKey(), ); if (success.error == null) { - AdaptivePageLayout.of(context).showSnackBar(SnackBar( + ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(L10n.of(context).requestToReadOlderMessages))); } } diff --git a/lib/widgets/layouts/loading_view.dart b/lib/widgets/layouts/loading_view.dart index 391dc76d..89e71ee0 100644 --- a/lib/widgets/layouts/loading_view.dart +++ b/lib/widgets/layouts/loading_view.dart @@ -1,4 +1,5 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; +import 'package:famedlysdk/famedlysdk.dart'; +import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; @@ -6,8 +7,10 @@ class LoadingView extends StatelessWidget { @override Widget build(BuildContext context) { if (Matrix.of(context).loginState != null) { - WidgetsBinding.instance.addPostFrameCallback((_) => - AdaptivePageLayout.of(context).pushNamedAndRemoveAllOthers('/')); + WidgetsBinding.instance.addPostFrameCallback((_) => context.vRouter.push( + Matrix.of(context).loginState == LoginState.logged + ? '/rooms' + : '/home')); } return Scaffold(body: Center(child: CircularProgressIndicator())); } diff --git a/lib/widgets/layouts/two_column_layout.dart b/lib/widgets/layouts/two_column_layout.dart new file mode 100644 index 00000000..15802e12 --- /dev/null +++ b/lib/widgets/layouts/two_column_layout.dart @@ -0,0 +1,40 @@ +import 'package:fluffychat/config/app_config.dart'; +import 'package:flutter/material.dart'; + +class TwoColumnLayout extends StatelessWidget { + final Widget mainView; + final Widget sideView; + + const TwoColumnLayout( + {Key key, @required this.mainView, @required this.sideView}) + : super(key: key); + @override + Widget build(BuildContext context) { + if (MediaQuery.of(context).size.width <= AppConfig.columnWidth * 2) { + return mainView; + } + return Scaffold( + body: ScaffoldMessenger( + child: Row( + children: [ + Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(), + width: 360.0, + child: mainView, + ), + Container( + width: 1.0, + color: Theme.of(context).dividerColor, + ), + Expanded( + child: ClipRRect( + child: sideView, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/list_items/chat_list_item.dart b/lib/widgets/list_items/chat_list_item.dart index 91ad3ce5..ccbf4622 100644 --- a/lib/widgets/list_items/chat_list_item.dart +++ b/lib/widgets/list_items/chat_list_item.dart @@ -1,5 +1,5 @@ import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; + import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions.dart/event_extension.dart'; @@ -9,6 +9,7 @@ import 'package:fluffychat/utils/room_status_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:pedantic/pedantic.dart'; +import 'package:vrouter/vrouter.dart'; import '../../utils/date_time_extension.dart'; import '../avatar.dart'; @@ -46,7 +47,7 @@ class ChatListItem extends StatelessWidget { } if (room.membership == Membership.ban) { - AdaptivePageLayout.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(L10n.of(context).youHaveBeenBannedFromThisChat), ), @@ -96,15 +97,13 @@ class ChatListItem extends StatelessWidget { file: Matrix.of(context).shareContent['file'], room: room, ), - useRootNavigator: false, ); } else { unawaited(room.sendEvent(Matrix.of(context).shareContent)); } Matrix.of(context).shareContent = null; } - await AdaptivePageLayout.of(context) - .pushNamedAndRemoveUntilIsFirst('/rooms/${room.id}'); + context.vRouter.push('/rooms/${room.id}'); } } } @@ -126,7 +125,6 @@ class ChatListItem extends StatelessWidget { title: L10n.of(context).areYouSure, okLabel: L10n.of(context).yes, cancelLabel: L10n.of(context).no, - useRootNavigator: false, ); if (confirmed == OkCancelResult.cancel) return; await showFutureLoadingDialog( diff --git a/lib/widgets/list_items/public_room_list_item.dart b/lib/widgets/list_items/public_room_list_item.dart index c54a344c..6de588e2 100644 --- a/lib/widgets/list_items/public_room_list_item.dart +++ b/lib/widgets/list_items/public_room_list_item.dart @@ -1,8 +1,8 @@ -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:vrouter/vrouter.dart'; import '../avatar.dart'; import '../matrix.dart'; @@ -18,8 +18,7 @@ class PublicRoomListItem extends StatelessWidget { future: () => _joinRoomAndWait(context), ); if (success.error == null) { - await AdaptivePageLayout.of(context) - .pushNamed('/rooms/${success.result}'); + VRouter.of(context).pushNamed('/rooms/${success.result}'); } } diff --git a/lib/widgets/log_view.dart b/lib/widgets/log_view.dart index 8f66d2c2..bc31699d 100644 --- a/lib/widgets/log_view.dart +++ b/lib/widgets/log_view.dart @@ -13,7 +13,7 @@ class _LogViewerState extends State { Widget build(BuildContext context) { final outputEvents = Logs() .outputEvents - .where((e) => e.level.index >= logLevel.index) + .where((e) => e.level.index <= logLevel.index) .toList(); return Scaffold( backgroundColor: Colors.black, @@ -44,7 +44,12 @@ class _LogViewerState extends State { itemCount: outputEvents.length, itemBuilder: (context, i) => SingleChildScrollView( scrollDirection: Axis.horizontal, - child: Text(outputEvents[i].toDisplayString()), + child: SelectableText( + outputEvents[i].toDisplayString(), + style: TextStyle( + color: outputEvents[i].color, + ), + ), ), ), ); @@ -52,8 +57,26 @@ class _LogViewerState extends State { } extension on LogEvent { + Color get color { + switch (level) { + case Level.wtf: + return Colors.purple; + case Level.error: + return Colors.red; + case Level.warning: + return Colors.orange; + case Level.info: + return Colors.green; + case Level.debug: + return Colors.white; + case Level.verbose: + default: + return Colors.grey; + } + } + String toDisplayString() { - var str = '# $title'; + var str = '# [${level.toString().split('.').last.toUpperCase()}] $title'; if (exception != null) { str += ' - ${exception.toString()}'; } diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index e86c3eac..de61d661 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -3,7 +3,6 @@ import 'dart:io'; import 'dart:convert'; import 'package:adaptive_dialog/adaptive_dialog.dart'; -import 'package:adaptive_page_layout/adaptive_page_layout.dart'; import 'package:famedlysdk/encryption.dart'; import 'package:famedlysdk/famedlysdk.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_locals.dart'; @@ -14,7 +13,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_app_lock/flutter_app_lock.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:provider/provider.dart'; import 'package:universal_html/html.dart' as html; import 'package:http/http.dart' as http; @@ -22,7 +20,6 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:desktop_notifications/desktop_notifications.dart'; import '../utils/beautify_string_extension.dart'; -import '../utils/localized_exception_extension.dart'; import '../utils/famedlysdk_store.dart'; import '../pages/key_verification_dialog.dart'; import '../utils/platform_infos.dart'; @@ -30,13 +27,14 @@ import '../config/app_config.dart'; import '../config/setting_keys.dart'; import '../utils/matrix_sdk_extensions.dart/fluffy_client.dart'; import '../utils/background_push.dart'; +import 'package:vrouter/vrouter.dart'; class Matrix extends StatefulWidget { static const String callNamespace = 'chat.fluffy.jitsi_call'; final Widget child; - final GlobalKey apl; + final GlobalKey router; final BuildContext context; @@ -44,7 +42,7 @@ class Matrix extends StatefulWidget { Matrix({ this.child, - @required this.apl, + @required this.router, @required this.context, this.testClient, Key key, @@ -137,7 +135,6 @@ class MatrixState extends State with WidgetsBindingObserver { title: L10n.of(context).pleaseEnterYourPassword, okLabel: L10n.of(context).ok, cancelLabel: L10n.of(context).cancel, - useRootNavigator: false, textFields: [ DialogTextField( minLines: 1, @@ -190,7 +187,6 @@ class MatrixState extends State with WidgetsBindingObserver { await showOkCancelAlertDialog( message: L10n.of(context).pleaseFollowInstructionsOnWeb, context: context, - useRootNavigator: false, okLabel: L10n.of(context).next, cancelLabel: L10n.of(context).cancel, )) { @@ -287,9 +283,6 @@ class MatrixState extends State with WidgetsBindingObserver { }); } client = FluffyClient(); - LoadingDialog.defaultTitle = L10n.of(context).loadingPleaseWait; - LoadingDialog.defaultBackLabel = L10n.of(context).close; - LoadingDialog.defaultOnError = (Object e) => e.toLocalizedString(context); onRoomKeyRequestSub ??= client.onRoomKeyRequest.stream.listen((RoomKeyRequest request) async { @@ -300,7 +293,6 @@ class MatrixState extends State with WidgetsBindingObserver { final sender = room.getUserByMXIDSync(request.sender); if (await showOkCancelAlertDialog( context: context, - useRootNavigator: false, title: L10n.of(context).requestToReadOlderMessages, message: '${sender.id}\n\n${L10n.of(context).device}:\n${request.requestingDevice.deviceId}\n\n${L10n.of(context).publicKey}:\n${request.requestingDevice.ed25519Key.beautified}', @@ -324,7 +316,6 @@ class MatrixState extends State with WidgetsBindingObserver { }; if (await showOkCancelAlertDialog( context: context, - useRootNavigator: false, title: L10n.of(context).newVerificationRequest, message: L10n.of(context).askVerificationRequest(request.userId), okLabel: L10n.of(context).ok, @@ -350,7 +341,8 @@ class MatrixState extends State with WidgetsBindingObserver { onLoginStateChanged ??= client.onLoginStateChanged.stream.listen((state) { if (loginState != state) { loginState = state; - widget.apl.currentState.pushNamedAndRemoveAllOthers('/'); + widget.router.currentState + .push(loginState == LoginState.logged ? '/rooms' : '/home'); } }); @@ -380,7 +372,7 @@ class MatrixState extends State with WidgetsBindingObserver { } if (PlatformInfos.isMobile) { - _backgroundPush = BackgroundPush(client, context, widget.apl); + _backgroundPush = BackgroundPush(client, context, widget.router); } } diff --git a/pubspec.lock b/pubspec.lock index d450e808..4355df76 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -15,13 +15,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.10.0+5" - adaptive_page_layout: - dependency: "direct main" - description: - name: adaptive_page_layout - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.4" adaptive_theme: dependency: "direct main" description: @@ -627,6 +620,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.1" + move_to_background: + dependency: transitive + description: + name: move_to_background + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.2" native_imaging: dependency: "direct main" description: @@ -762,6 +762,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + path_to_regexp: + dependency: transitive + description: + name: path_to_regexp + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0" pedantic: dependency: "direct dev" description: @@ -1187,6 +1194,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.0" + url_strategy: + dependency: transitive + description: + name: url_strategy + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" uuid: dependency: transitive description: @@ -1208,6 +1222,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.2.0" + vrouter: + dependency: "direct main" + description: + name: vrouter + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2+5" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d1c53e13..a9380b06 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,6 @@ environment: dependencies: adaptive_dialog: ^0.10.0+5 - adaptive_page_layout: ^0.2.4 adaptive_theme: ^2.2.0 android_path_provider: ^0.2.1 audioplayers: ^0.18.3 @@ -70,6 +69,7 @@ dependencies: unifiedpush: ^1.0.2 universal_html: ^2.0.8 url_launcher: ^6.0.3 + vrouter: ^1.1.2+5 dev_dependencies: dapackages: ^1.6.0 diff --git a/test/sign_up_password_test.dart b/test/sign_up_password_test.dart index 03473c70..dd455935 100644 --- a/test/sign_up_password_test.dart +++ b/test/sign_up_password_test.dart @@ -6,10 +6,7 @@ void main() { testWidgets('Test if the widget can be created', (WidgetTester tester) async { await tester.pumpWidget( FluffyChatApp( - testWidget: SignUpPassword( - 'test_user', - displayname: 'Test User', - ), + testWidget: SignUpPassword(), ), ); });