diff --git a/assets/l10n/intl_cs.arb b/assets/l10n/intl_cs.arb index ef5f9be4..3671b8ed 100644 --- a/assets/l10n/intl_cs.arb +++ b/assets/l10n/intl_cs.arb @@ -1352,7 +1352,7 @@ "senderName": {} } }, - "startYourFirstChat": "Zahajte svůj první chat! 🙂\n- Klepněte na „+“\n- Zadejte uživatelské jméno přítele\n- Bavte se chatováním", + "startYourFirstChat": "Zahajte svůj první chat! 🙂\n- Klepněte na tlačítko zprávy\n- Zadejte uživatelské jméno přítele\n- Bavte se chatováním", "@startYourFirstChat": { "type": "text", "placeholders": {} @@ -2341,5 +2341,15 @@ "@invalidEmail": { "type": "text", "placeholders": {} + }, + "useSSO": "Použijte jednotné přihlášení", + "@useSSO": { + "type": "text", + "placeholders": {} + }, + "or": "Nebo", + "@or": { + "type": "text", + "placeholders": {} } } diff --git a/assets/l10n/intl_et.arb b/assets/l10n/intl_et.arb index 8b28b400..69194e69 100644 --- a/assets/l10n/intl_et.arb +++ b/assets/l10n/intl_et.arb @@ -1367,7 +1367,7 @@ "senderName": {} } }, - "startYourFirstChat": "Alusta oma esimest vestlust kohe nüüd 🙂\n- Klõpsi „+“ ikooni\n- Sisesta teise osapoole kasutajanimi\n- Ja lase vestlusel kulgeda", + "startYourFirstChat": "Alusta oma esimest vestlust kohe nüüd 🙂\n- klõpsi vestlusnuppu\n- sisesta teise osapoole kasutajanimi\n- ja lase vestlusel kulgeda", "@startYourFirstChat": { "type": "text", "placeholders": {} @@ -2341,5 +2341,15 @@ "@invalidEmail": { "type": "text", "placeholders": {} + }, + "or": "või", + "@or": { + "type": "text", + "placeholders": {} + }, + "useSSO": "Kasuta ühekordset sisselogimist", + "@useSSO": { + "type": "text", + "placeholders": {} } } diff --git a/assets/l10n/intl_tr.arb b/assets/l10n/intl_tr.arb index c0c56d11..cbd66f8d 100644 --- a/assets/l10n/intl_tr.arb +++ b/assets/l10n/intl_tr.arb @@ -1271,7 +1271,7 @@ "type": "text", "placeholders": {} }, - "startYourFirstChat": "Hemen ilk sohbetinize başlayın! 🙂\n- \"+\" simgesine dokunun\n- Bir arkadaşın kullanıcı adını girin\n- Eğlenceli bir şekilde sohbet edin", + "startYourFirstChat": "Hemen ilk sohbetinize başlayın! 🙂\n- Mesaj düğmesine dokunun\n- Bir arkadaşın kullanıcı adını girin\n- Eğlenceli bir şekilde sohbet edin", "@startYourFirstChat": { "type": "text", "placeholders": {} @@ -2341,5 +2341,15 @@ "@invalidEmail": { "type": "text", "placeholders": {} + }, + "useSSO": "Tekli oturum açma kullan", + "@useSSO": { + "type": "text", + "placeholders": {} + }, + "or": "Veya", + "@or": { + "type": "text", + "placeholders": {} } } diff --git a/lib/main.dart b/lib/main.dart index bdd7d94c..8c9c4646 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -65,6 +65,7 @@ class FluffyChatApp extends StatefulWidget { } class _FluffyChatAppState extends State { + final GlobalKey _matrix = GlobalKey(); GlobalKey _router; int columns; String _initialUrl = '/'; @@ -74,48 +75,49 @@ class _FluffyChatAppState extends State { light: FluffyThemes.light, dark: FluffyThemes.dark, initial: AdaptiveThemeMode.system, - 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(); - }); + builder: (theme, darkTheme) => 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; - }, - ); - }, - ), + }); + } + 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 Matrix( + key: _matrix, + context: context, + router: _router, + testClient: widget.testClient, + child: child, + ); + }, + ); + }, ), ); } diff --git a/lib/pages/chat_list.dart b/lib/pages/chat_list.dart index 75baff73..628b55c3 100644 --- a/lib/pages/chat_list.dart +++ b/lib/pages/chat_list.dart @@ -245,7 +245,10 @@ class ChatListController extends State { } @override - Widget build(BuildContext context) => ChatListView(this); + Widget build(BuildContext context) { + Matrix.of(context).navigatorContext = context; + return ChatListView(this); + } } enum ChatListPopupMenuItemActions { diff --git a/lib/pages/homeserver_picker.dart b/lib/pages/homeserver_picker.dart index 1a5b3cd7..fac56ff2 100644 --- a/lib/pages/homeserver_picker.dart +++ b/lib/pages/homeserver_picker.dart @@ -65,5 +65,8 @@ class HomeserverPickerController extends State { } @override - Widget build(BuildContext context) => HomeserverPickerView(this); + Widget build(BuildContext context) { + Matrix.of(context).navigatorContext = context; + return HomeserverPickerView(this); + } } diff --git a/lib/pages/sign_up.dart b/lib/pages/sign_up.dart index c998c653..9e721876 100644 --- a/lib/pages/sign_up.dart +++ b/lib/pages/sign_up.dart @@ -153,7 +153,7 @@ class SignUpController extends State { setState(() => loading = false); VRouter.of(context).push( - '/signup/password/${Uri.encodeComponent(preferredUsername)}/${Uri.encodeComponent(usernameController.text)}', + '/signup/password/${Uri.encodeComponent(preferredUsername)}', queryParameters: {'displayname': usernameController.text}, ); } diff --git a/lib/pages/views/chat_permissions_settings_view.dart b/lib/pages/views/chat_permissions_settings_view.dart index d2faa258..8a8953a0 100644 --- a/lib/pages/views/chat_permissions_settings_view.dart +++ b/lib/pages/views/chat_permissions_settings_view.dart @@ -6,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 ChatPermissionsSettingsView extends StatelessWidget { final ChatPermissionsSettingsController controller; @@ -17,7 +18,11 @@ class ChatPermissionsSettingsView extends StatelessWidget { Widget build(BuildContext context) { 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).editChatPermissions), ), body: MaxWidthBody( diff --git a/lib/pages/views/invitation_selection_view.dart b/lib/pages/views/invitation_selection_view.dart index fcc959c8..c03a551b 100644 --- a/lib/pages/views/invitation_selection_view.dart +++ b/lib/pages/views/invitation_selection_view.dart @@ -7,6 +7,7 @@ import 'package:fluffychat/widgets/layouts/max_width_body.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 InvitationSelectionView extends StatelessWidget { final InvitationSelectionController controller; @@ -20,7 +21,11 @@ class InvitationSelectionView extends StatelessWidget { room.name?.isEmpty ?? false ? L10n.of(context).group : room.name; return Scaffold( appBar: AppBar( - leading: BackButton(), + leading: IconButton( + icon: Icon(Icons.close_outlined), + onPressed: () => + VRouter.of(context).push('/rooms/${controller.roomId}'), + ), titleSpacing: 0, title: DefaultAppBarSearchField( autofocus: true, diff --git a/lib/widgets/layouts/one_page_card.dart b/lib/widgets/layouts/one_page_card.dart index e8607817..abc33a69 100644 --- a/lib/widgets/layouts/one_page_card.dart +++ b/lib/widgets/layouts/one_page_card.dart @@ -14,32 +14,35 @@ class OnePageCard extends StatelessWidget { return MediaQuery.of(context).size.width <= breakpoint || MediaQuery.of(context).size.height <= breakpoint ? child - : Container( - decoration: BoxDecoration( - color: Theme.of(context).backgroundColor, - gradient: LinearGradient( - begin: Alignment.topRight, - end: Alignment.bottomLeft, - stops: [ - 0.1, - 0.4, - 0.6, - 0.9, - ], - colors: [ - Theme.of(context).secondaryHeaderColor.withAlpha(alpha), - Theme.of(context).primaryColor.withAlpha(alpha), - Theme.of(context).accentColor.withAlpha(alpha), - Theme.of(context).backgroundColor.withAlpha(alpha), - ], + : Material( + color: Theme.of(context).backgroundColor, + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topRight, + end: Alignment.bottomLeft, + stops: [ + 0.1, + 0.4, + 0.6, + 0.9, + ], + colors: [ + Theme.of(context).secondaryHeaderColor.withAlpha(alpha), + Theme.of(context).primaryColor.withAlpha(alpha), + Theme.of(context).accentColor.withAlpha(alpha), + Theme.of(context).backgroundColor.withAlpha(alpha), + ], + ), ), + padding: EdgeInsets.symmetric( + horizontal: + max((MediaQuery.of(context).size.width - 600) / 2, 12), + vertical: + max((MediaQuery.of(context).size.height - 800) / 2, 12), + ), + child: SafeArea(child: Card(child: child)), ), - padding: EdgeInsets.symmetric( - horizontal: - max((MediaQuery.of(context).size.width - 600) / 2, 12), - vertical: max((MediaQuery.of(context).size.height - 800) / 2, 12), - ), - child: SafeArea(child: Card(child: child)), ); } } diff --git a/lib/widgets/matrix.dart b/lib/widgets/matrix.dart index de61d661..1567ac84 100644 --- a/lib/widgets/matrix.dart +++ b/lib/widgets/matrix.dart @@ -18,8 +18,6 @@ import 'package:universal_html/html.dart' as html; import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; import 'package:desktop_notifications/desktop_notifications.dart'; - -import '../utils/beautify_string_extension.dart'; import '../utils/famedlysdk_store.dart'; import '../pages/key_verification_dialog.dart'; import '../utils/platform_infos.dart'; @@ -59,8 +57,7 @@ class Matrix extends StatefulWidget { class MatrixState extends State with WidgetsBindingObserver { FluffyClient client; Store store = Store(); - @override - BuildContext get context => widget.context; + BuildContext navigatorContext; BackgroundPush _backgroundPush; @@ -131,10 +128,10 @@ class MatrixState extends State with WidgetsBindingObserver { case AuthenticationTypes.password: final input = cachedPassword ?? (await showTextInputDialog( - context: context, - title: L10n.of(context).pleaseEnterYourPassword, - okLabel: L10n.of(context).ok, - cancelLabel: L10n.of(context).cancel, + context: navigatorContext, + title: L10n.of(widget.context).pleaseEnterYourPassword, + okLabel: L10n.of(widget.context).ok, + cancelLabel: L10n.of(widget.context).cancel, textFields: [ DialogTextField( minLines: 1, @@ -185,10 +182,10 @@ class MatrixState extends State with WidgetsBindingObserver { ); if (OkCancelResult.ok == await showOkCancelAlertDialog( - message: L10n.of(context).pleaseFollowInstructionsOnWeb, - context: context, - okLabel: L10n.of(context).next, - cancelLabel: L10n.of(context).cancel, + message: L10n.of(widget.context).pleaseFollowInstructionsOnWeb, + context: navigatorContext, + okLabel: L10n.of(widget.context).next, + cancelLabel: L10n.of(widget.context).cancel, )) { return uiaRequest.completeStage( AuthenticationData(session: uiaRequest.session), @@ -211,9 +208,10 @@ class MatrixState extends State with WidgetsBindingObserver { final room = client.getRoomById(roomId); if (room.notificationCount == 0) return; final event = Event.fromJson(eventUpdate.content, room); - final title = room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))); + final title = + room.getLocalizedDisplayname(MatrixLocals(L10n.of(widget.context))); final body = event.getLocalizedBody( - MatrixLocals(L10n.of(context)), + MatrixLocals(L10n.of(widget.context)), withSenderNamePrefix: !room.isDirectChat || room.lastEvent.senderId == client.userID, ); @@ -276,33 +274,13 @@ class MatrixState extends State with WidgetsBindingObserver { WidgetsBinding.instance.addPostFrameCallback((_) { FlutterSecureStorage().read(key: SettingKeys.appLockKey).then((lock) { if (lock?.isNotEmpty ?? false) { - AppLock.of(context).enable(); - AppLock.of(context).showLockScreen(); + AppLock.of(widget.context).enable(); + AppLock.of(widget.context).showLockScreen(); } }); }); } client = FluffyClient(); - - onRoomKeyRequestSub ??= - client.onRoomKeyRequest.stream.listen((RoomKeyRequest request) async { - final room = request.room; - if (request.sender != room.client.userID) { - return; // ignore share requests by others - } - final sender = room.getUserByMXIDSync(request.sender); - if (await showOkCancelAlertDialog( - context: context, - 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}', - okLabel: L10n.of(context).verify, - cancelLabel: L10n.of(context).deny, - ) == - OkCancelResult.ok) { - await request.forwardKey(); - } - }); onKeyVerificationRequestSub ??= client.onKeyVerificationRequest.stream .listen((KeyVerification request) async { var hidPopup = false; @@ -310,22 +288,23 @@ class MatrixState extends State with WidgetsBindingObserver { if (!hidPopup && {KeyVerificationState.done, KeyVerificationState.error} .contains(request.state)) { - Navigator.of(context, rootNavigator: true).pop('dialog'); + Navigator.of(navigatorContext).pop('dialog'); } hidPopup = true; }; if (await showOkCancelAlertDialog( - context: context, - title: L10n.of(context).newVerificationRequest, - message: L10n.of(context).askVerificationRequest(request.userId), - okLabel: L10n.of(context).ok, - cancelLabel: L10n.of(context).cancel, + context: navigatorContext, + title: L10n.of(widget.context).newVerificationRequest, + message: + L10n.of(widget.context).askVerificationRequest(request.userId), + okLabel: L10n.of(widget.context).ok, + cancelLabel: L10n.of(widget.context).cancel, ) == OkCancelResult.ok) { request.onUpdate = null; hidPopup = true; await request.acceptVerification(); - await KeyVerificationDialog(request: request).show(context); + await KeyVerificationDialog(request: request).show(navigatorContext); } else { request.onUpdate = null; hidPopup = true; @@ -372,7 +351,7 @@ class MatrixState extends State with WidgetsBindingObserver { } if (PlatformInfos.isMobile) { - _backgroundPush = BackgroundPush(client, context, widget.router); + _backgroundPush = BackgroundPush(client, navigatorContext, widget.router); } }