From 33208aa30cb9344fb3d88478713d7b21be14e7af Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:23:21 -0500 Subject: [PATCH] 1814 add future loading dialog to prevent user interaction during signup login loading (#1866) * chore: updates for running on android for flutter 3.29.0 * feat: show future loading dialog on signup and login * chore: enable build on iOS for flutter 3.29.0 --- ios/Podfile | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 1 + lib/pages/chat_list/chat_list.dart | 31 +- .../chat_list/client_chooser_button.dart | 2 +- lib/pages/login/login.dart | 224 +++++------- .../new_private_chat/qr_scanner_modal.dart | 8 +- lib/pages/settings/settings.dart | 2 +- lib/pangea/login/pages/pangea_login_view.dart | 8 - lib/pangea/login/pages/signup.dart | 139 +++----- lib/pangea/login/pages/signup_view.dart | 4 - .../login/pages/signup_with_email_view.dart | 1 - lib/pangea/login/widgets/p_sso_button.dart | 40 +-- lib/pangea/user/utils/p_login.dart | 85 +++++ .../user/utils/{logout.dart => p_logout.dart} | 3 - lib/utils/background_push.dart | 10 +- .../ios_badge_client_extension.dart | 20 -- lib/utils/push_helper.dart | 7 +- lib/utils/voip/callkeep_manager.dart | 325 ------------------ lib/utils/voip/user_media_manager.dart | 24 +- lib/utils/voip_plugin.dart | 55 +-- lib/widgets/future_loading_dialog.dart | 56 ++- linux/flutter/generated_plugin_registrant.cc | 8 + linux/flutter/generated_plugins.cmake | 2 + macos/Flutter/GeneratedPluginRegistrant.swift | 8 +- pubspec.lock | 291 ++++++++-------- pubspec.yaml | 31 +- .../flutter/generated_plugin_registrant.cc | 6 + windows/flutter/generated_plugins.cmake | 2 + 28 files changed, 505 insertions(+), 890 deletions(-) create mode 100644 lib/pangea/user/utils/p_login.dart rename lib/pangea/user/utils/{logout.dart => p_logout.dart} (91%) delete mode 100644 lib/utils/matrix_sdk_extensions/ios_badge_client_extension.dart delete mode 100644 lib/utils/voip/callkeep_manager.dart diff --git a/ios/Podfile b/ios/Podfile index ffafc1fa9..e1f306535 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -51,7 +51,7 @@ post_install do |installer| config.build_settings['ENABLE_BITCODE'] = 'NO' # see https://github.com/flutter-webrtc/flutter-webrtc/issues/1054 - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = 'arm64 i386' config.build_settings["CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"] = 'YES' diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 5e31d3d34..c53e2b314 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -48,6 +48,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/lib/pages/chat_list/chat_list.dart b/lib/pages/chat_list/chat_list.dart index 2a2bdbe8b..a22ac0d04 100644 --- a/lib/pages/chat_list/chat_list.dart +++ b/lib/pages/chat_list/chat_list.dart @@ -4,14 +4,14 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:app_links/app_links.dart'; import 'package:cross_file/cross_file.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_shortcuts/flutter_shortcuts.dart'; +import 'package:flutter_shortcuts_new/flutter_shortcuts_new.dart'; import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart' as sdk; import 'package:matrix/matrix.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; -import 'package:uni_links/uni_links.dart'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/themes.dart'; @@ -38,13 +38,12 @@ import 'package:fluffychat/widgets/share_scaffold_dialog.dart'; import '../../../utils/account_bundles.dart'; import '../../config/setting_keys.dart'; import '../../utils/url_launcher.dart'; -import '../../utils/voip/callkeep_manager.dart'; -import '../../widgets/fluffy_chat_app.dart'; import '../../widgets/matrix.dart'; import 'package:fluffychat/utils/tor_stub.dart' if (dart.library.html) 'package:tor_detector_web/tor_detector_web.dart'; + enum PopupMenuAction { settings, invite, @@ -184,23 +183,20 @@ class ChatListController extends State case ActiveFilter.messages: return (room) => !room.isSpace && - room.isDirectChat - // #Pangea + room.isDirectChat // #Pangea && !room.isAnalyticsRoom; // Pangea# case ActiveFilter.groups: return (room) => !room.isSpace && - !room.isDirectChat - // #Pangea + !room.isDirectChat // #Pangea && !room.isAnalyticsRoom; // Pangea# case ActiveFilter.unread: return (room) => - room.isUnreadOrInvited - // #Pangea + room.isUnreadOrInvited // #Pangea && !room.isAnalyticsRoom; // Pangea# @@ -405,11 +401,11 @@ class ChatListController extends State ); } - void _processIncomingUris(String? text) async { - if (text == null) return; + void _processIncomingUris(Uri? uri) async { + if (uri == null) return; context.go('/rooms'); WidgetsBinding.instance.addPostFrameCallback((_) { - UrlLauncher(context, text).openMatrixToUrl(); + UrlLauncher(context, uri.toString()).openMatrixToUrl(); }); } @@ -427,11 +423,8 @@ class ChatListController extends State .then(_processIncomingSharedMedia); // For receiving shared Uris - _intentUriStreamSubscription = linkStream.listen(_processIncomingUris); - if (FluffyChatApp.gotInitialLink == false) { - FluffyChatApp.gotInitialLink = true; - getInitialLink().then(_processIncomingUris); - } + _intentUriStreamSubscription = + AppLinks().uriLinkStream.listen(_processIncomingUris); if (PlatformInfos.isAndroid) { final shortcuts = FlutterShortcuts(); @@ -459,7 +452,6 @@ class ChatListController extends State scrollController.addListener(_onScroll); _waitForFirstSync(); _hackyWebRTCFixForWeb(); - CallKeepManager().initialize(); WidgetsBinding.instance.addPostFrameCallback((_) async { if (mounted) { searchServer = @@ -851,7 +843,6 @@ class ChatListController extends State return; case ChatContextAction.leave: final confirmed = await showOkCancelAlertDialog( - useRootNavigator: false, context: context, title: L10n.of(context).areYouSure, // #Pangea diff --git a/lib/pages/chat_list/client_chooser_button.dart b/lib/pages/chat_list/client_chooser_button.dart index 8deaa4c65..f056c1069 100644 --- a/lib/pages/chat_list/client_chooser_button.dart +++ b/lib/pages/chat_list/client_chooser_button.dart @@ -6,7 +6,7 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart'; import 'package:fluffychat/pangea/spaces/utils/space_code.dart'; -import 'package:fluffychat/pangea/user/utils/logout.dart'; +import 'package:fluffychat/pangea/user/utils/p_logout.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/matrix.dart'; diff --git a/lib/pages/login/login.dart b/lib/pages/login/login.dart index a0200bbef..71187ae89 100644 --- a/lib/pages/login/login.dart +++ b/lib/pages/login/login.dart @@ -3,20 +3,17 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/common/constants/local.key.dart'; import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart'; -import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart'; import 'package:fluffychat/pangea/login/pages/pangea_login_view.dart'; import 'package:fluffychat/pangea/login/widgets/p_sso_button.dart'; +import 'package:fluffychat/pangea/user/utils/p_login.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_ok_cancel_alert_dialog.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_text_input_dialog.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; -import '../../utils/platform_infos.dart'; class Login extends StatefulWidget { const Login({super.key}); @@ -28,30 +25,26 @@ class Login extends StatefulWidget { class LoginController extends State { final TextEditingController usernameController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); - String? usernameText; - String? passwordText; - String? usernameError; String? passwordError; + bool loading = false; + bool showPassword = false; + void toggleShowPassword() => + setState(() => showPassword = !loading && !showPassword); + + // #Pangea bool loadingSignIn = false; bool loadingAppleSSO = false; bool loadingGoogleSSO = false; - String? appleSSOError; - String? googleSSOError; - bool showPassword = false; - - // #Pangea final PangeaController pangeaController = MatrixState.pangeaController; final GlobalKey formKey = GlobalKey(); bool get enabledSignIn => !loadingSignIn && - usernameText != null && - usernameText!.isNotEmpty && - passwordText != null && - passwordText!.isNotEmpty; + usernameController.text.isNotEmpty && + passwordController.text.isNotEmpty; @override void initState() { @@ -70,15 +63,8 @@ class LoginController extends State { }); }); - usernameController.addListener(() { - _setStateOnTextChange(usernameText, usernameController.text); - usernameText = usernameController.text; - }); - - passwordController.addListener(() { - _setStateOnTextChange(passwordText, passwordController.text); - passwordText = passwordController.text; - }); + usernameController.addListener(() => setState(() {})); + passwordController.addListener(() => setState(() {})); } @override @@ -91,15 +77,10 @@ class LoginController extends State { super.dispose(); } - void setSSOError(String? error, SSOProvider provider) { - if (provider == SSOProvider.apple) { - appleSSOError = error; - googleSSOError = null; - } else if (provider == SSOProvider.google) { - googleSSOError = error; - appleSSOError = null; + void setLoadingSignIn(bool loading) { + if (mounted) { + setState(() => loadingSignIn = loading); } - if (mounted) setState(() {}); } void setLoadingSSO(bool loading, SSOProvider provider) { @@ -113,121 +94,67 @@ class LoginController extends State { if (mounted) setState(() {}); } - void _setStateOnTextChange(String? oldText, String newText) { - if ((oldText == null || oldText.isEmpty) && (newText.isNotEmpty)) { - setState(() {}); - } - if ((oldText != null && oldText.isNotEmpty) && (newText.isEmpty)) { - setState(() {}); - } - } + void login() async => pLoginAction(controller: this, context: context); + // void login() async { + // final matrix = Matrix.of(context); + // if (usernameController.text.isEmpty) { + // setState(() => usernameError = L10n.of(context).pleaseEnterYourUsername); + // } else { + // setState(() => usernameError = null); + // } + // if (passwordController.text.isEmpty) { + // setState(() => passwordError = L10n.of(context).pleaseEnterYourPassword); + // } else { + // setState(() => passwordError = null); + // } + + // if (usernameController.text.isEmpty || passwordController.text.isEmpty) { + // return; + // } + + // setState(() => loading = true); + + // _coolDown?.cancel(); + + // try { + // final username = usernameController.text; + // AuthenticationIdentifier identifier; + // if (username.isEmail) { + // identifier = AuthenticationThirdPartyIdentifier( + // medium: 'email', + // address: username, + // ); + // } else if (username.isPhoneNumber) { + // identifier = AuthenticationThirdPartyIdentifier( + // medium: 'msisdn', + // address: username, + // ); + // } else { + // identifier = AuthenticationUserIdentifier(user: username); + // } + // await matrix.getLoginClient().login( + // LoginType.mLoginPassword, + // identifier: identifier, + // // To stay compatible with older server versions + // // ignore: deprecated_member_use + // user: identifier.type == AuthenticationIdentifierTypes.userId + // ? username + // : null, + // password: passwordController.text, + // initialDeviceDisplayName: PlatformInfos.clientName, + // ); + // } on MatrixException catch (exception) { + // setState(() => passwordError = exception.errorMessage); + // return setState(() => loading = false); + // } catch (exception) { + // setState(() => passwordError = exception.toString()); + // return setState(() => loading = false); + // } + + // if (mounted) setState(() => loading = false); + // } // Pangea# - void toggleShowPassword() => - setState(() => showPassword = !loadingSignIn && !showPassword); - - void login() async { - // #Pangea - final valid = formKey.currentState!.validate(); - if (!valid) return; - // Pangea# - - final matrix = Matrix.of(context); - if (usernameController.text.isEmpty) { - setState(() => usernameError = L10n.of(context).pleaseEnterYourUsername); - } else { - setState(() => usernameError = null); - } - if (passwordController.text.isEmpty) { - setState(() => passwordError = L10n.of(context).pleaseEnterYourPassword); - } else { - setState(() => passwordError = null); - } - - if (usernameController.text.isEmpty || passwordController.text.isEmpty) { - return; - } - - setState(() => loadingSignIn = true); - - _coolDown?.cancel(); - - try { - // #Pangea - String username = usernameController.text.trim(); - if (RegExp(r'^@(\w+):').hasMatch(username)) { - username = - RegExp(r'^@(\w+):').allMatches(username).elementAt(0).group(1)!; - } - // Pangea# - AuthenticationIdentifier identifier; - if (username.isEmail) { - identifier = AuthenticationThirdPartyIdentifier( - medium: 'email', - address: username, - ); - } else if (username.isPhoneNumber) { - identifier = AuthenticationThirdPartyIdentifier( - medium: 'msisdn', - address: username, - ); - } else { - identifier = AuthenticationUserIdentifier(user: username); - } - // #Pangea - // await matrix.getLoginClient().login( - final loginRes = await matrix.getLoginClient().login( - // Pangea# - LoginType.mLoginPassword, - identifier: identifier, - // To stay compatible with older server versions - // ignore: deprecated_member_use - user: identifier.type == AuthenticationIdentifierTypes.userId - ? username - : null, - // #Pangea - // password: passwordController.text, - password: passwordController.text.trim(), - // Pangea# - initialDeviceDisplayName: PlatformInfos.clientName, - // #Pangea - onInitStateChanged: (state) { - if (state == InitState.settingUpEncryption) { - context.go("/rooms"); - } - }, - // Pangea# - ); - MatrixState.pangeaController.pStoreService - .save(PLocalKey.loginType, 'password'); - // #Pangea - GoogleAnalytics.login("pangea", loginRes.userId); - // Pangea# - } on MatrixException catch (exception) { - // #Pangea - // setState(() => passwordError = exception.errorMessage); - setState(() { - passwordError = exception.errorMessage; - usernameError = exception.errorMessage; - }); - // Pangea# - return setState(() => loadingSignIn = false); - } catch (exception) { - // #Pangea - // setState(() => passwordError = exception.toString()); - setState(() { - passwordError = exception.toString(); - usernameError = exception.toString(); - }); - // Pangea# - return setState(() => loadingSignIn = false); - } - - // #Pangea - // if (mounted) setState(() => loading = false); - // Pangea# - } - Timer? _coolDown; void checkWellKnownWithCoolDown(String userId) async { @@ -381,7 +308,10 @@ class LoginController extends State { // Pangea# } -extension on String { +// #Pangea +// extension on String { +extension LoginExtension on String { +// Pangea# static final RegExp _phoneRegex = RegExp(r'^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*$'); static final RegExp _emailRegex = RegExp(r'(.+)@(.+)\.(.+)'); diff --git a/lib/pages/new_private_chat/qr_scanner_modal.dart b/lib/pages/new_private_chat/qr_scanner_modal.dart index f0c571ddd..915ffa726 100644 --- a/lib/pages/new_private_chat/qr_scanner_modal.dart +++ b/lib/pages/new_private_chat/qr_scanner_modal.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:qr_code_scanner/qr_code_scanner.dart'; +import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart'; class QrScannerModal extends StatefulWidget { final void Function(String) onScan; @@ -72,10 +72,4 @@ class QrScannerModalState extends State { if (data != null) widget.onScan(data); }); } - - @override - void dispose() { - controller?.dispose(); - super.dispose(); - } } diff --git a/lib/pages/settings/settings.dart b/lib/pages/settings/settings.dart index 393bbbb85..d3676ddc5 100644 --- a/lib/pages/settings/settings.dart +++ b/lib/pages/settings/settings.dart @@ -5,7 +5,7 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:image_picker/image_picker.dart'; import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/user/utils/logout.dart'; +import 'package:fluffychat/pangea/user/utils/p_logout.dart'; import 'package:fluffychat/utils/file_selector.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/adaptive_dialogs/show_modal_action_popup.dart'; diff --git a/lib/pangea/login/pages/pangea_login_view.dart b/lib/pangea/login/pages/pangea_login_view.dart index 5829fc43e..a25c73111 100644 --- a/lib/pangea/login/pages/pangea_login_view.dart +++ b/lib/pangea/login/pages/pangea_login_view.dart @@ -29,9 +29,6 @@ class PangeaLoginView extends StatelessWidget { return null; }, controller: controller.usernameController, - errorText: controller.usernameError, - showErrorText: controller.usernameError != null && - controller.passwordError == null, ), FullWidthTextField( hintText: L10n.of(context).password, @@ -47,7 +44,6 @@ class PangeaLoginView extends StatelessWidget { return null; }, controller: controller.passwordController, - errorText: controller.passwordError, ), FullWidthButton( title: L10n.of(context).signIn, @@ -93,17 +89,13 @@ class PangeaLoginView extends StatelessWidget { provider: SSOProvider.google, title: L10n.of(context).signInWithGoogle, loading: controller.loadingGoogleSSO, - error: controller.googleSSOError, setLoading: controller.setLoadingSSO, - setError: controller.setSSOError, ), PangeaSsoButton( provider: SSOProvider.apple, title: L10n.of(context).signInWithApple, loading: controller.loadingAppleSSO, - error: controller.appleSSOError, setLoading: controller.setLoadingSSO, - setError: controller.setSSOError, ), ], ), diff --git a/lib/pangea/login/pages/signup.dart b/lib/pangea/login/pages/signup.dart index 67e24340e..420d3fe99 100644 --- a/lib/pangea/login/pages/signup.dart +++ b/lib/pangea/login/pages/signup.dart @@ -3,13 +3,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix_api_lite/model/matrix_exception.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart'; import 'package:fluffychat/pangea/login/pages/signup_view.dart'; import 'package:fluffychat/pangea/login/pages/signup_with_email_view.dart'; import 'package:fluffychat/pangea/login/widgets/p_sso_button.dart'; -import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; class SignupPage extends StatefulWidget { @@ -32,12 +31,9 @@ class SignupPageController extends State { String? passwordText; String? emailText; - String? error; bool loadingSignup = false; bool loadingAppleSSO = false; bool loadingGoogleSSO = false; - String? appleSSOError; - String? googleSSOError; bool showPassword = false; bool noEmailWarningConfirmed = false; @@ -69,21 +65,9 @@ class SignupPageController extends State { passwordController.dispose(); emailController.dispose(); loadingSignup = false; - error = null; super.dispose(); } - void setSSOError(String? error, SSOProvider provider) { - if (provider == SSOProvider.apple) { - appleSSOError = error; - googleSSOError = null; - } else if (provider == SSOProvider.google) { - googleSSOError = error; - appleSSOError = null; - } - if (mounted) setState(() {}); - } - void setLoadingSSO(bool loading, SSOProvider provider) { if (provider == SSOProvider.apple) { loadingAppleSSO = loading; @@ -149,13 +133,8 @@ class SignupPageController extends State { } String? emailTextFieldValidator(String? value) { - // #Pangea if (value == null || value.isEmpty) { - // if (value!.isEmpty && !noEmailWarningConfirmed) { - // noEmailWarningConfirmed = true; - // return L10n.of(context).noEmailWarning; return L10n.of(context).pleaseEnterEmail; - // Pangea# } if (value.isNotEmpty && !value.contains('@')) { return L10n.of(context).pleaseEnterValidEmail; @@ -172,83 +151,63 @@ class SignupPageController extends State { } void signup([_]) async { - setState(() { - error = null; - }); + setState(() => signupError = null); final valid = formKey.currentState!.validate(); if (!isTnCChecked) { - setState(() { - signupError = L10n.of(context).pleaseAgreeToTOS; - }); - } - if (!valid || !isTnCChecked) { - return; + setState(() => signupError = L10n.of(context).pleaseAgreeToTOS); } + if (!valid || !isTnCChecked) return; + setState(() => loadingSignup = true); - setState(() { - loadingSignup = true; - }); + await showFutureLoadingDialog( + context: context, + future: _signupFuture, + onError: (e, s) { + setState(() { + loadingSignup = false; + loadingAppleSSO = false; + loadingGoogleSSO = false; + }); + return e is MatrixException + ? e.errorMessage + : L10n.of(context).oopsSomethingWentWrong; + }, + ); + } - try { - final client = Matrix.of(context).getLoginClient(); - final email = emailController.text; - if (email.isNotEmpty) { - Matrix.of(context).currentClientSecret = - DateTime.now().millisecondsSinceEpoch.toString(); - Matrix.of(context).currentThreepidCreds = - await client.requestTokenToRegisterEmail( - Matrix.of(context).currentClientSecret, - email, - 0, - ); - } - - final displayname = usernameController.text; - final localPart = displayname.toLowerCase().replaceAll(' ', '_'); - - final registerRes = await client.uiaRequestBackground( - (auth) => client.register( - username: localPart, - password: passwordController.text, - initialDeviceDisplayName: PlatformInfos.clientName, - auth: auth, - ), + Future _signupFuture() async { + final client = Matrix.of(context).getLoginClient(); + final email = emailController.text; + if (email.isNotEmpty) { + Matrix.of(context).currentClientSecret = + DateTime.now().millisecondsSinceEpoch.toString(); + Matrix.of(context).currentThreepidCreds = + await client.requestTokenToRegisterEmail( + Matrix.of(context).currentClientSecret, + email, + 0, ); + } - GoogleAnalytics.login("pangea", registerRes.userId); + final displayname = usernameController.text; + final localPart = displayname.toLowerCase().replaceAll(' ', '_'); - if (displayname != localPart && client.userID != null) { - await client.setDisplayName( - client.userID!, - displayname, - ); - } - } on MatrixException catch (e, s) { - if (e.error != MatrixError.M_THREEPID_IN_USE) { - ErrorHandler.logError( - e: e, - s: s, - data: {}, - ); - } - error = e.errorMessage; - } catch (e, s) { - const cancelledString = "Exception: Request has been canceled"; - if (e.toString() != cancelledString) { - ErrorHandler.logError( - e: e, - s: s, - data: {}, - ); - } + final registerRes = await client.uiaRequestBackground( + (auth) => client.register( + username: localPart, + password: passwordController.text, + initialDeviceDisplayName: PlatformInfos.clientName, + auth: auth, + ), + ); - if (mounted) { - error = (e).toLocalizedString(context); - } - } finally { - if (mounted) { - setState(() => loadingSignup = false); - } + GoogleAnalytics.login("pangea", registerRes.userId); + + if (displayname != localPart && client.userID != null) { + await client.setDisplayName( + client.userID!, + displayname, + ); } } diff --git a/lib/pangea/login/pages/signup_view.dart b/lib/pangea/login/pages/signup_view.dart index 95a409047..a3c4c1339 100644 --- a/lib/pangea/login/pages/signup_view.dart +++ b/lib/pangea/login/pages/signup_view.dart @@ -30,18 +30,14 @@ class SignupPageView extends StatelessWidget { PangeaSsoButton( provider: SSOProvider.google, title: L10n.of(context).signUpWithGoogle, - setError: controller.setSSOError, setLoading: controller.setLoadingSSO, loading: controller.loadingGoogleSSO, - error: controller.googleSSOError, ), PangeaSsoButton( provider: SSOProvider.apple, title: L10n.of(context).signUpWithApple, - setError: controller.setSSOError, setLoading: controller.setLoadingSSO, loading: controller.loadingAppleSSO, - error: controller.appleSSOError, ), ], ); diff --git a/lib/pangea/login/pages/signup_with_email_view.dart b/lib/pangea/login/pages/signup_with_email_view.dart index 3f64d7a15..2c92d7181 100644 --- a/lib/pangea/login/pages/signup_with_email_view.dart +++ b/lib/pangea/login/pages/signup_with_email_view.dart @@ -58,7 +58,6 @@ class SignupWithEmailView extends StatelessWidget { forceColor: Theme.of(context).colorScheme.onPrimary, ), onPressed: controller.enableSignUp ? controller.signup : null, - error: controller.error, loading: controller.loadingSignup, enabled: controller.enableSignUp, ), diff --git a/lib/pangea/login/widgets/p_sso_button.dart b/lib/pangea/login/widgets/p_sso_button.dart index a8a5e8db4..42f02385b 100644 --- a/lib/pangea/login/widgets/p_sso_button.dart +++ b/lib/pangea/login/widgets/p_sso_button.dart @@ -5,9 +5,9 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:matrix/matrix_api_lite/model/matrix_exception.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/login/utils/sso_login_action.dart'; import 'package:fluffychat/pangea/login/widgets/full_width_button.dart'; +import 'package:fluffychat/widgets/future_loading_dialog.dart'; import 'package:fluffychat/widgets/matrix.dart'; enum SSOProvider { google, apple } @@ -46,53 +46,43 @@ class PangeaSsoButton extends StatelessWidget { final SSOProvider provider; final Function(bool, SSOProvider) setLoading; - final Function(String?, SSOProvider) setError; - final bool loading; - final String? error; const PangeaSsoButton({ required this.title, required this.provider, required this.setLoading, - required this.setError, this.loading = false, - this.error, super.key, }); Future _runSSOLogin(BuildContext context) async { - try { - setLoading(true, provider); - setError(null, provider); - await pangeaSSOLoginAction( + setLoading(true, provider); + await showFutureLoadingDialog( + context: context, + future: () async => pangeaSSOLoginAction( IdentityProvider( id: provider.id, name: provider.name, ), Matrix.of(context).getLoginClient(), context, - ); - } catch (err, s) { - ErrorHandler.logError( - e: err, - s: s, - data: {}, - ); - final error = err is MatrixException - ? err.errorMessage - : L10n.of(context).oopsSomethingWentWrong; - setError(error, provider); - } finally { - setLoading(false, provider); - } + ), + onError: (e, s) { + setLoading(false, provider); + return e is MatrixException + ? e.errorMessage + : L10n.of(context).oopsSomethingWentWrong; + }, + onDismiss: () => setLoading(false, provider), + ); + setLoading(false, provider); } @override Widget build(BuildContext context) { return FullWidthButton( depressed: loading, - error: error, loading: loading, title: title, icon: SvgPicture.asset( diff --git a/lib/pangea/user/utils/p_login.dart b/lib/pangea/user/utils/p_login.dart new file mode 100644 index 000000000..e41a9e8f5 --- /dev/null +++ b/lib/pangea/user/utils/p_login.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; + +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; + +import 'package:fluffychat/pages/login/login.dart'; +import 'package:fluffychat/pangea/common/constants/local.key.dart'; +import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart'; +import 'package:fluffychat/pangea/login/widgets/p_sso_button.dart'; +import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/widgets/future_loading_dialog.dart'; +import 'package:fluffychat/widgets/matrix.dart'; + +void pLoginAction({ + required LoginController controller, + required BuildContext context, +}) async { + final valid = controller.formKey.currentState!.validate(); + if (!valid) return; + + await showFutureLoadingDialog( + context: context, + future: () => _loginFuture( + controller: controller, + context: context, + ), + onError: (e, s) { + controller.setLoadingSignIn(false); + controller.setLoadingSSO(false, SSOProvider.apple); + controller.setLoadingSSO(false, SSOProvider.google); + return e is MatrixException + ? e.errorMessage + : L10n.of(context).oopsSomethingWentWrong; + }, + ); +} + +Future _loginFuture({ + required LoginController controller, + required BuildContext context, +}) async { + final matrix = Matrix.of(context); + controller.setLoadingSignIn(true); + + String username = controller.usernameController.text.trim(); + if (RegExp(r'^@(\w+):').hasMatch(username)) { + username = RegExp(r'^@(\w+):').allMatches(username).elementAt(0).group(1)!; + } + + AuthenticationIdentifier identifier; + if (username.isEmail) { + identifier = AuthenticationThirdPartyIdentifier( + medium: 'email', + address: username, + ); + } else if (username.isPhoneNumber) { + identifier = AuthenticationThirdPartyIdentifier( + medium: 'msisdn', + address: username, + ); + } else { + identifier = AuthenticationUserIdentifier(user: username); + } + + final loginRes = await matrix.getLoginClient().login( + LoginType.mLoginPassword, + identifier: identifier, + // To stay compatible with older server versions + // ignore: deprecated_member_use + user: identifier.type == AuthenticationIdentifierTypes.userId + ? username + : null, + password: controller.passwordController.text.trim(), + initialDeviceDisplayName: PlatformInfos.clientName, + onInitStateChanged: (state) { + if (state == InitState.settingUpEncryption) { + context.go("/rooms"); + } + }, + ); + MatrixState.pangeaController.pStoreService + .save(PLocalKey.loginType, 'password'); + GoogleAnalytics.login("pangea", loginRes.userId); +} diff --git a/lib/pangea/user/utils/logout.dart b/lib/pangea/user/utils/p_logout.dart similarity index 91% rename from lib/pangea/user/utils/logout.dart rename to lib/pangea/user/utils/p_logout.dart index 10902fdc8..a7ad74840 100644 --- a/lib/pangea/user/utils/logout.dart +++ b/lib/pangea/user/utils/p_logout.dart @@ -11,10 +11,7 @@ void pLogoutAction(BuildContext context, {bool? isDestructiveAction}) async { useRootNavigator: false, context: context, title: L10n.of(context).areYouSureYouWantToLogout, - // #Pangea - // message: L10n.of(context).noBackupWarning, message: L10n.of(context).dontForgetPassword, - // Pangea# okLabel: L10n.of(context).logout, cancelLabel: L10n.of(context).cancel, ) == diff --git a/lib/utils/background_push.dart b/lib/utils/background_push.dart index e8297b68a..d4c684387 100644 --- a/lib/utils/background_push.dart +++ b/lib/utils/background_push.dart @@ -27,9 +27,9 @@ import 'package:flutter/material.dart'; import 'package:fcm_shared_isolate/fcm_shared_isolate.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter_app_badger/flutter_app_badger.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:flutter_new_badger/flutter_new_badger.dart'; import 'package:http/http.dart' as http; import 'package:matrix/matrix.dart'; import 'package:unifiedpush/unifiedpush.dart'; @@ -203,9 +203,9 @@ class BackgroundPush { .where((room) => room.isUnreadOrInvited && room.id != roomId) .length; if (unreadCount == 0) { - FlutterAppBadger.removeBadge(); + FlutterNewBadger.removeBadge(); } else { - FlutterAppBadger.updateBadgeCount(unreadCount); + FlutterNewBadger.setBadge(unreadCount); } return; } @@ -222,7 +222,8 @@ class BackgroundPush { // Pangea# if (PlatformInfos.isIOS) { await firebase?.requestPermission(); - } else if (PlatformInfos.isAndroid) { + } + if (PlatformInfos.isAndroid) { _flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() @@ -237,7 +238,6 @@ class BackgroundPush { ); } // Pangea# - final clientName = PlatformInfos.clientName; oldTokens ??= {}; final pushers = await (client.getPushers().catchError((e) { diff --git a/lib/utils/matrix_sdk_extensions/ios_badge_client_extension.dart b/lib/utils/matrix_sdk_extensions/ios_badge_client_extension.dart deleted file mode 100644 index bea7713d0..000000000 --- a/lib/utils/matrix_sdk_extensions/ios_badge_client_extension.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter_app_badger/flutter_app_badger.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/utils/platform_infos.dart'; - -extension IosBadgeClientExtension on Client { - void updateIosBadge() { - if (PlatformInfos.isIOS) { - // Workaround for iOS not clearing notifications with fcm_shared_isolate - if (!rooms.any( - (r) => r.membership == Membership.invite || (r.notificationCount > 0), - )) { - // ignore: unawaited_futures - FlutterLocalNotificationsPlugin().cancelAll(); - FlutterAppBadger.removeBadge(); - } - } - } -} diff --git a/lib/utils/push_helper.dart b/lib/utils/push_helper.dart index 2da1ebbf4..33e69b925 100644 --- a/lib/utils/push_helper.dart +++ b/lib/utils/push_helper.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:flutter_shortcuts/flutter_shortcuts.dart'; +import 'package:flutter_shortcuts_new/flutter_shortcuts_new.dart'; import 'package:matrix/matrix.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -16,7 +16,6 @@ import 'package:fluffychat/utils/client_download_content_extension.dart'; import 'package:fluffychat/utils/client_manager.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/platform_infos.dart'; -import 'package:fluffychat/utils/voip/callkeep_manager.dart'; Future pushHelper( PushNotification notification, { @@ -121,9 +120,7 @@ Future _tryPushHelper( client.backgroundSync = true; } - if (event.type == EventTypes.CallInvite) { - CallKeepManager().initialize(); - } else if (event.type == EventTypes.CallHangup) { + if (event.type == EventTypes.CallHangup) { client.backgroundSync = false; } diff --git a/lib/utils/voip/callkeep_manager.dart b/lib/utils/voip/callkeep_manager.dart deleted file mode 100644 index a66252414..000000000 --- a/lib/utils/voip/callkeep_manager.dart +++ /dev/null @@ -1,325 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; - -import 'package:callkeep/callkeep.dart'; -import 'package:flutter_foreground_task/flutter_foreground_task.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:matrix/matrix.dart'; -import 'package:permission_handler/permission_handler.dart'; - -class CallKeeper { - CallKeeper(this.callKeepManager, this.call) { - call.onCallStateChanged.stream.listen(_handleCallState); - } - - CallKeepManager callKeepManager; - bool? held = false; - bool? muted = false; - bool connected = false; - CallSession call; - - // update native caller to show what remote user has done. - void _handleCallState(CallState state) { - Logs().i('CallKeepManager::handleCallState: ${state.toString()}'); - switch (state) { - case CallState.kConnecting: - Logs().v('callkeep connecting'); - break; - case CallState.kConnected: - Logs().v('callkeep connected'); - if (!connected) { - callKeepManager.answer(call.callId); - } else { - callKeepManager.setMutedCall(call.callId, false); - callKeepManager.setOnHold(call.callId, false); - } - break; - case CallState.kEnded: - callKeepManager.hangup(call.callId); - break; - - case CallState.kFledgling: - case CallState.kInviteSent: - case CallState.kWaitLocalMedia: - case CallState.kCreateOffer: - case CallState.kCreateAnswer: - case CallState.kRinging: - case CallState.kEnding: - break; - } - } -} - -Map calls = {}; - -class CallKeepManager { - factory CallKeepManager() { - return _instance; - } - - CallKeepManager._internal() { - _callKeep = FlutterCallkeep(); - } - - static final CallKeepManager _instance = CallKeepManager._internal(); - - late FlutterCallkeep _callKeep; - - String get appName => 'FluffyChat'; - - Future get hasPhoneAccountEnabled async => - await _callKeep.hasPhoneAccount(); - - Map get alertOptions => { - 'alertTitle': 'Permissions required', - 'alertDescription': - 'Allow $appName to register as a calling account? This will allow calls to be handled by the native android dialer.', - 'cancelButton': 'Cancel', - 'okButton': 'ok', - // Required to get audio in background when using Android 11 - 'foregroundService': { - 'channelId': 'com.fluffy.fluffychat', - 'channelName': 'Foreground service for my app', - 'notificationTitle': '$appName is running on background', - 'notificationIcon': 'mipmap/ic_notification_launcher', - }, - 'additionalPermissions': [''], - }; - bool setupDone = false; - - Future showCallkitIncoming(CallSession call) async { - if (!setupDone) { - await _callKeep.setup( - null, - { - 'ios': { - 'appName': appName, - }, - 'android': alertOptions, - }, - backgroundMode: true, - ); - } - setupDone = true; - await displayIncomingCall(call); - call.onCallStateChanged.stream.listen((state) { - if (state == CallState.kEnded) { - _callKeep.endAllCalls(); - } - }); - call.onCallEventChanged.stream.listen( - (event) { - if (event == CallStateChange.kLocalHoldUnhold) { - Logs().i( - 'Call hold event: local ${call.localHold}, remote ${call.remoteOnHold}', - ); - } - }, - ); - } - - void removeCall(String? callUUID) { - calls.remove(callUUID); - } - - void addCall(String? callUUID, CallKeeper callKeeper) { - if (calls.containsKey(callUUID)) return; - calls[callUUID] = callKeeper; - } - - void setCallHeld(String? callUUID, bool? held) { - calls[callUUID]!.held = held; - } - - void setCallMuted(String? callUUID, bool? muted) { - calls[callUUID]!.muted = muted; - } - - void didDisplayIncomingCall(CallKeepDidDisplayIncomingCall event) { - final callUUID = event.callUUID; - final number = event.handle; - Logs().v('[displayIncomingCall] $callUUID number: $number'); - // addCall(callUUID, CallKeeper(this null)); - } - - void onPushKitToken(CallKeepPushKitToken event) { - Logs().v('[onPushKitToken] token => ${event.token}'); - } - - Future initialize() async { - _callKeep.on(CallKeepPerformAnswerCallAction(), answerCall); - _callKeep.on(CallKeepDidPerformDTMFAction(), didPerformDTMFAction); - - _callKeep.on(CallKeepDidToggleHoldAction(), didToggleHoldCallAction); - _callKeep.on( - CallKeepDidPerformSetMutedCallAction(), - didPerformSetMutedCallAction, - ); - _callKeep.on(CallKeepPerformEndCallAction(), endCall); - _callKeep.on(CallKeepPushKitToken(), onPushKitToken); - _callKeep.on(CallKeepDidDisplayIncomingCall(), didDisplayIncomingCall); - Logs().i('[VOIP] Initialized'); - } - - Future hangup(String callUUID) async { - await _callKeep.endCall(callUUID); - removeCall(callUUID); - } - - Future reject(String callUUID) async { - await _callKeep.rejectCall(callUUID); - } - - Future answer(String? callUUID) async { - final keeper = calls[callUUID]!; - if (!keeper.connected) { - await _callKeep.answerIncomingCall(callUUID!); - keeper.connected = true; - } - } - - Future setOnHold(String callUUID, bool held) async { - await _callKeep.setOnHold(callUUID, held); - setCallHeld(callUUID, held); - } - - Future setMutedCall(String callUUID, bool muted) async { - await _callKeep.setMutedCall(callUUID, muted); - setCallMuted(callUUID, muted); - } - - Future updateDisplay(String callUUID) async { - // Workaround because Android doesn't display well displayName, se we have to switch ... - if (isIOS) { - await _callKeep.updateDisplay( - callUUID, - displayName: 'New Name', - handle: callUUID, - ); - } else { - await _callKeep.updateDisplay( - callUUID, - displayName: callUUID, - handle: 'New Name', - ); - } - } - - Future displayIncomingCall(CallSession call) async { - final callKeeper = CallKeeper(this, call); - addCall(call.callId, callKeeper); - await _callKeep.displayIncomingCall( - call.callId, - '${call.room.getLocalizedDisplayname()} (FluffyChat)', - localizedCallerName: - '${call.room.getLocalizedDisplayname()} (FluffyChat)', - handleType: 'number', - hasVideo: call.type == CallType.kVideo, - ); - return callKeeper; - } - - Future checkoutPhoneAccountSetting(BuildContext context) async { - showDialog( - context: context, - barrierDismissible: true, - useRootNavigator: false, - builder: (_) => AlertDialog( - title: Text(L10n.of(context).callingPermissions), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - ListTile( - onTap: () => openCallingAccountsPage(context), - title: Text(L10n.of(context).callingAccount), - subtitle: Text(L10n.of(context).callingAccountDetails), - trailing: const Icon(Icons.phone), - ), - const Divider(), - ListTile( - onTap: () => FlutterForegroundTask.openSystemAlertWindowSettings( - forceOpen: true, - ), - title: Text(L10n.of(context).appearOnTop), - subtitle: Text(L10n.of(context).appearOnTopDetails), - trailing: const Icon(Icons.file_upload_rounded), - ), - const Divider(), - ListTile( - onTap: () => openAppSettings(), - title: Text(L10n.of(context).otherCallingPermissions), - trailing: const Icon(Icons.mic), - ), - ], - ), - ), - ); - } - - void openCallingAccountsPage(BuildContext context) async { - await _callKeep.setup(context, { - 'ios': { - 'appName': appName, - }, - 'android': alertOptions, - }); - final hasPhoneAccount = await _callKeep.hasPhoneAccount(); - Logs().e(hasPhoneAccount.toString()); - if (!hasPhoneAccount) { - await _callKeep.hasDefaultPhoneAccount(context, alertOptions); - } else { - await _callKeep.openPhoneAccounts(); - } - } - - /// CallActions. - Future answerCall(CallKeepPerformAnswerCallAction event) async { - final callUUID = event.callUUID; - final keeper = calls[event.callUUID]!; - if (!keeper.connected) { - Logs().e('answered'); - // Answer Call - keeper.call.answer(); - keeper.connected = true; - } - Timer(const Duration(seconds: 1), () { - _callKeep.setCurrentCallActive(callUUID!); - }); - } - - Future endCall(CallKeepPerformEndCallAction event) async { - final keeper = calls[event.callUUID]; - keeper?.call.hangup(reason: CallErrorCode.userHangup); - removeCall(event.callUUID); - } - - Future didPerformDTMFAction(CallKeepDidPerformDTMFAction event) async { - final keeper = calls[event.callUUID]!; - keeper.call.sendDTMF(event.digits!); - } - - Future didPerformSetMutedCallAction( - CallKeepDidPerformSetMutedCallAction event, - ) async { - final keeper = calls[event.callUUID]; - if (event.muted!) { - keeper!.call.setMicrophoneMuted(true); - } else { - keeper!.call.setMicrophoneMuted(false); - } - setCallMuted(event.callUUID, event.muted); - } - - Future didToggleHoldCallAction( - CallKeepDidToggleHoldAction event, - ) async { - final keeper = calls[event.callUUID]; - if (event.hold!) { - keeper!.call.setRemoteOnHold(true); - } else { - keeper!.call.setRemoteOnHold(false); - } - setCallHeld(event.callUUID, event.hold); - } -} diff --git a/lib/utils/voip/user_media_manager.dart b/lib/utils/voip/user_media_manager.dart index 03ecd6030..e1677f894 100644 --- a/lib/utils/voip/user_media_manager.dart +++ b/lib/utils/voip/user_media_manager.dart @@ -1,10 +1,5 @@ -import 'package:flutter/foundation.dart'; - -import 'package:flutter_ringtone_player/flutter_ringtone_player.dart'; import 'package:just_audio/just_audio.dart'; -import 'package:fluffychat/utils/platform_infos.dart'; - class UserMediaManager { factory UserMediaManager() { return _instance; @@ -16,25 +11,16 @@ class UserMediaManager { AudioPlayer? _assetsAudioPlayer; - final FlutterRingtonePlayer _flutterRingtonePlayer = FlutterRingtonePlayer(); - Future startRingingTone() async { - if (PlatformInfos.isMobile) { - await _flutterRingtonePlayer.playRingtone(volume: 80); - } else if ((kIsWeb || PlatformInfos.isMacOS) && - _assetsAudioPlayer != null) { - const path = 'assets/sounds/phone.ogg'; - final player = _assetsAudioPlayer = AudioPlayer(); - player.setAsset(path); - player.play(); - } + const path = 'assets/sounds/phone.ogg'; + final player = _assetsAudioPlayer = AudioPlayer(); + player.setAsset(path); + player.play(); + return; } Future stopRingingTone() async { - if (PlatformInfos.isMobile) { - await _flutterRingtonePlayer.stop(); - } await _assetsAudioPlayer?.stop(); _assetsAudioPlayer = null; return; diff --git a/lib/utils/voip_plugin.dart b/lib/utils/voip_plugin.dart index 6d0c06dcd..c5120d604 100644 --- a/lib/utils/voip_plugin.dart +++ b/lib/utils/voip_plugin.dart @@ -11,7 +11,6 @@ import 'package:webrtc_interface/webrtc_interface.dart' hide Navigator; import 'package:fluffychat/pages/chat_list/chat_list.dart'; import 'package:fluffychat/pages/dialer/dialer.dart'; import 'package:fluffychat/utils/platform_infos.dart'; -import '../../utils/voip/callkeep_manager.dart'; import '../../utils/voip/user_media_manager.dart'; import '../widgets/matrix.dart'; @@ -89,8 +88,7 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate { ]) => webrtc_impl.createPeerConnection(configuration, constraints); - Future get hasCallingAccount async => - kIsWeb ? false : await CallKeepManager().hasPhoneAccountEnabled; + Future get hasCallingAccount async => false; @override Future playRingtone() async { @@ -113,46 +111,21 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate { @override Future handleNewCall(CallSession call) async { if (PlatformInfos.isAndroid) { - // probably works on ios too - final hasCallingAccount = await CallKeepManager().hasPhoneAccountEnabled; - if (call.direction == CallDirection.kIncoming && - hasCallingAccount && - call.type == CallType.kVoice) { - ///Popup native telecom manager call UI for incoming call. - final callKeeper = CallKeeper(CallKeepManager(), call); - CallKeepManager().addCall(call.callId, callKeeper); - await CallKeepManager().showCallkitIncoming(call); - return; - } else { - try { - final wasForeground = await FlutterForegroundTask.isAppOnForeground; + try { + final wasForeground = await FlutterForegroundTask.isAppOnForeground; - await matrix.store.setString( - 'wasForeground', - wasForeground == true ? 'true' : 'false', - ); - FlutterForegroundTask.setOnLockScreenVisibility(true); - FlutterForegroundTask.wakeUpScreen(); - FlutterForegroundTask.launchApp(); - } catch (e) { - Logs().e('VOIP foreground failed $e'); - } - // use fallback flutter call pages for outgoing and video calls. - addCallingOverlay(call.callId, call); - try { - if (!hasCallingAccount) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - 'No calling accounts found (used for native calls UI)', - ), - ), - ); - } - } catch (e) { - Logs().e('failed to show snackbar'); - } + await matrix.store.setString( + 'wasForeground', + wasForeground == true ? 'true' : 'false', + ); + FlutterForegroundTask.setOnLockScreenVisibility(true); + FlutterForegroundTask.wakeUpScreen(); + FlutterForegroundTask.launchApp(); + } catch (e) { + Logs().e('VOIP foreground failed $e'); } + // use fallback flutter call pages for outgoing and video calls. + addCallingOverlay(call.callId, call); } else { addCallingOverlay(call.callId, call); } diff --git a/lib/widgets/future_loading_dialog.dart b/lib/widgets/future_loading_dialog.dart index bbc7247b2..dd2219475 100644 --- a/lib/widgets/future_loading_dialog.dart +++ b/lib/widgets/future_loading_dialog.dart @@ -20,6 +20,10 @@ Future> showFutureLoadingDialog({ bool barrierDismissible = false, bool delay = true, ExceptionContext? exceptionContext, + // #Pangea + String Function(Object, StackTrace?)? onError, + VoidCallback? onDismiss, + // Pangea# }) async { final futureExec = future(); final resultFuture = ResultFuture(futureExec); @@ -48,6 +52,10 @@ Future> showFutureLoadingDialog({ title: title, backLabel: backLabel, exceptionContext: exceptionContext, + // #Pangea + onError: onError, + onDismiss: onDismiss, + // Pangea# ), ); return result ?? @@ -70,6 +78,10 @@ class LoadingDialog extends StatefulWidget { final String? backLabel; final Future future; final ExceptionContext? exceptionContext; + // #Pangea + final String Function(Object, StackTrace?)? onError; + final VoidCallback? onDismiss; + // Pangea# const LoadingDialog({ super.key, @@ -77,6 +89,10 @@ class LoadingDialog extends StatefulWidget { this.title, this.backLabel, this.exceptionContext, + // #Pangea + this.onError, + this.onDismiss, + // Pangea# }); @override LoadingDialogState createState() => LoadingDialogState(); @@ -90,11 +106,26 @@ class LoadingDialogState extends State { void initState() { super.initState(); widget.future.then( - (result) => Navigator.of(context).pop>(Result.value(result)), - onError: (e, s) => setState(() { - exception = e; - stackTrace = s; - }), + // #Pangea + // (result) => Navigator.of(context).pop>(Result.value(result)), + // onError: (e, s) => setState(() { + // exception = e; + // stackTrace = s; + // }), + (result) { + if (mounted) { + Navigator.of(context).pop>(Result.value(result)); + } + }, + onError: (e, s) { + if (mounted) { + setState(() { + exception = widget.onError?.call(e, s) ?? e; + stackTrace = s; + }); + } + }, + // Pangea# ); } @@ -134,7 +165,20 @@ class LoadingDialogState extends State { ), ), actions: exception == null - ? null + // #Pangea + // ? null + ? widget.onDismiss != null + ? [ + AdaptiveDialogAction( + onPressed: () { + widget.onDismiss!(); + Navigator.of(context).pop(); + }, + child: Text(L10n.of(context).cancel), + ), + ] + : null + // Pangea# : [ AdaptiveDialogAction( onPressed: () => Navigator.of(context).pop>( diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 8a1e26c05..63e1af5cd 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,11 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include #include #include #include #include #include +#include #include #include #include @@ -24,6 +26,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin"); audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar); + g_autoptr(FlPluginRegistrar) desktop_webview_window_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopWebviewWindowPlugin"); + desktop_webview_window_plugin_register_with_registrar(desktop_webview_window_registrar); g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); @@ -39,6 +44,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_webrtc_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterWebRTCPlugin"); flutter_web_r_t_c_plugin_register_with_registrar(flutter_webrtc_registrar); + g_autoptr(FlPluginRegistrar) gtk_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin"); + gtk_plugin_register_with_registrar(gtk_registrar); g_autoptr(FlPluginRegistrar) handy_window_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin"); handy_window_plugin_register_with_registrar(handy_window_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 7c2b2bd52..3273dcc88 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,11 +4,13 @@ list(APPEND FLUTTER_PLUGIN_LIST audioplayers_linux + desktop_webview_window dynamic_color emoji_picker_flutter file_selector_linux flutter_secure_storage_linux flutter_webrtc + gtk handy_window pasteboard record_linux diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 0487a6c5b..b51c9c563 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,10 @@ import FlutterMacOS import Foundation +import app_links import audio_session import audioplayers_darwin +import desktop_webview_window import device_info_plus import dynamic_color import emoji_picker_flutter @@ -14,8 +16,8 @@ import file_selector_macos import firebase_analytics import firebase_core import firebase_messaging -import flutter_app_badger import flutter_local_notifications +import flutter_new_badger import flutter_secure_storage_macos import flutter_tts import flutter_web_auth_2 @@ -42,8 +44,10 @@ import wakelock_plus import window_to_front func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin")) AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) + DesktopWebviewWindowPlugin.register(with: registry.registrar(forPlugin: "DesktopWebviewWindowPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) EmojiPickerFlutterPlugin.register(with: registry.registrar(forPlugin: "EmojiPickerFlutterPlugin")) @@ -51,8 +55,8 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) - FlutterAppBadgerPlugin.register(with: registry.registrar(forPlugin: "FlutterAppBadgerPlugin")) FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) + FlutterNewBadgerPlugin.register(with: registry.registrar(forPlugin: "FlutterNewBadgerPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FlutterTtsPlugin.register(with: registry.registrar(forPlugin: "FlutterTtsPlugin")) FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin")) diff --git a/pubspec.lock b/pubspec.lock index 61dbd9e22..6422835fb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,6 +49,38 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.2" + app_links: + dependency: "direct main" + description: + name: app_links + sha256: "85ed8fc1d25a76475914fff28cc994653bd900bc2c26e4b57a49e097febb54ba" + url: "https://pub.dev" + source: hosted + version: "6.4.0" + app_links_linux: + dependency: transitive + description: + name: app_links_linux + sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + app_links_platform_interface: + dependency: transitive + description: + name: app_links_platform_interface + sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + app_links_web: + dependency: transitive + description: + name: app_links_web + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 + url: "https://pub.dev" + source: hosted + version: "1.0.4" archive: dependency: "direct main" description: @@ -69,10 +101,10 @@ packages: dependency: "direct main" description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" audio_session: dependency: transitive description: @@ -173,10 +205,10 @@ packages: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" build_config: dependency: transitive description: @@ -185,14 +217,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - callkeep: - dependency: "direct main" - description: - name: callkeep - sha256: "9e86e9632a603a61f7045c179ea5ca0ee4da0a49fc5f80c2fe09fb422b96d3c6" - url: "https://pub.dev" - source: hosted - version: "0.3.3" canonical_json: dependency: transitive description: @@ -205,10 +229,10 @@ packages: dependency: "direct main" description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" charcode: dependency: transitive description: @@ -245,18 +269,18 @@ packages: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: "direct main" description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" colorize: dependency: transitive description: @@ -349,10 +373,10 @@ packages: dependency: transitive description: name: dart_webrtc - sha256: e65506edb452148220efab53d8d2f8bb9d827bd8bcd53cf3a3e6df70b27f3d86 + sha256: "03df5b41b23bc185ebcf4b0ffc92d002e295bf56287fb5f9d2c321ddaf7760cc" url: "https://pub.dev" source: hosted - version: "1.4.10" + version: "1.5.1" dbus: dependency: transitive description: @@ -377,6 +401,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.3" + desktop_webview_window: + dependency: transitive + description: + name: desktop_webview_window + sha256: "57cf20d81689d5cbb1adfd0017e96b669398a669d927906073b0e42fc64111c0" + url: "https://pub.dev" + source: hosted + version: "0.2.3" device_info_plus: dependency: "direct main" description: @@ -461,10 +493,10 @@ packages: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" fcm_shared_isolate: dependency: "direct main" description: @@ -484,10 +516,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" file_picker: dependency: "direct main" description: @@ -653,14 +685,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_app_badger: - dependency: "direct main" - description: - name: flutter_app_badger - sha256: "64d4a279bab862ed28850431b9b446b9820aaae0bf363322d51077419f930fa8" - url: "https://pub.dev" - source: hosted - version: "1.5.0" flutter_cache_manager: dependency: "direct main" description: @@ -807,14 +831,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" + flutter_new_badger: + dependency: "direct main" + description: + name: flutter_new_badger + sha256: d3742ace8009663db1ac6ba0377b092f479c35deb33e05514ba05cc0b0a5aaaa + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter_olm: dependency: "direct main" description: name: flutter_olm - sha256: "69aaac45d854e74d17d04dac8a0ca3f548266d271a0f0fa7600e006e81432417" + sha256: "5e6211af8cba1abf7d1f92e543f6d573dfe6017fe4742e0d04ba84beab47f940" url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "2.0.0" flutter_openssl_crypto: dependency: "direct main" description: @@ -831,14 +863,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.20" - flutter_ringtone_player: - dependency: "direct main" - description: - name: flutter_ringtone_player - sha256: d0277a04e629a6582d776f5dcc2a879a733f7326ba073b872a9ccfbff9d9b51f - url: "https://pub.dev" - source: hosted - version: "4.0.0+3" flutter_secure_storage: dependency: "direct main" description: @@ -887,15 +911,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" - flutter_shortcuts: + flutter_shortcuts_new: dependency: "direct main" description: - path: "." - ref: HEAD - resolved-ref: "930c51d56c87a7f8cefdf8c1db52c194baddc37d" - url: "https://github.com/krille-chan/flutter_shortcuts.git" - source: git - version: "1.4.0" + name: flutter_shortcuts_new + sha256: "16ee1c8a9bc9586b5117ebb774a8ff6b396f856743e97251eb483c4dc5769d7f" + url: "https://pub.dev" + source: hosted + version: "2.0.0" flutter_svg: dependency: "direct main" description: @@ -929,18 +952,18 @@ packages: dependency: "direct main" description: name: flutter_web_auth_2 - sha256: "4d3d2fd3d26bf1a26b3beafd4b4b899c0ffe10dc99af25abc58ffe24e991133c" + sha256: "3c14babeaa066c371f3a743f204dd0d348b7d42ffa6fae7a9847a521aff33696" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "4.1.0" flutter_web_auth_2_platform_interface: dependency: transitive description: name: flutter_web_auth_2_platform_interface - sha256: e8669e262005a8354389ba2971f0fc1c36188481234ff50d013aaf993f30f739 + sha256: c63a472c8070998e4e422f6b34a17070e60782ac442107c70000dd1bed645f4d url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.1.0" flutter_web_plugins: dependency: transitive description: flutter @@ -950,10 +973,10 @@ packages: dependency: "direct main" description: name: flutter_webrtc - sha256: f6800cc2af79018c12e955ddf8ad007891fdfbb8199b0ce3dccd0977ed2add9c + sha256: "9c4ca34ced1d1b780baf3776557f9edd0af18ce030969346f752e8df455faaab" url: "https://pub.dev" source: hosted - version: "0.11.7" + version: "0.12.10" freezed_annotation: dependency: transitive description: @@ -1079,6 +1102,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + gtk: + dependency: transitive + description: + name: gtk + sha256: e8ce9ca4b1df106e4d72dad201d345ea1a036cc12c360f1a7d5a758f78ffa42c + url: "https://pub.dev" + source: hosted + version: "2.1.0" handy_window: dependency: "direct main" description: @@ -1235,34 +1266,34 @@ packages: dependency: "direct main" description: name: in_app_purchase - sha256: def70fbaa2a274f4d835677459f6f7afc5469de912438f86076e51cbd4cbd5b4 + sha256: "11a40f148eeb4f681a0572003e2b33432e110c90c1bbb4f9ef83b81ec0c4f737" url: "https://pub.dev" source: hosted - version: "3.1.13" + version: "3.2.1" in_app_purchase_android: dependency: transitive description: name: in_app_purchase_android - sha256: "28164faac635a6cc357c96f47813e675eec7622a8f41e829b501573dbbce2cce" + sha256: "45ae4fe253f85b4fcc58b421fe137f6e48aca16bf8a618cd760cb0542e7f854e" url: "https://pub.dev" source: hosted - version: "0.3.0+17" + version: "0.4.0" in_app_purchase_platform_interface: dependency: transitive description: name: in_app_purchase_platform_interface - sha256: "412efce2b9238c5ace4f057acad43f793ed06880e366d26ae322e796cadb051a" + sha256: "1d353d38251da5b9fea6635c0ebfc6bb17a2d28d0e86ea5e083bf64244f1fb4c" url: "https://pub.dev" source: hosted - version: "1.3.7" + version: "1.4.0" in_app_purchase_storekit: dependency: transitive description: name: in_app_purchase_storekit - sha256: c4b17a7f2ca8ddc7fd7996a8c32a3af6beddf91d651997c8675a5f23c103c9bc + sha256: "276831961023055b55a2156c1fc043f50f6215ff49fb0f5f2273da6eeb510ecf" url: "https://pub.dev" source: hosted - version: "0.3.8+1" + version: "0.3.21" injector: dependency: transitive description: @@ -1360,18 +1391,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -1440,10 +1471,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -1473,10 +1504,10 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" mgrs_dart: dependency: transitive description: @@ -1505,10 +1536,10 @@ packages: dependency: "direct main" description: name: native_imaging - sha256: "182ccd8e0815a8a2158500ef66c828c030f6b9e05783e41e22f33bbcfd46a3d5" + sha256: "93573afdcab070011d78a40fc1f69b61967f1f8485d2b81a7a2ee585a85f4c04" url: "https://pub.dev" source: hosted - version: "0.1.1" + version: "0.2.0" nested: dependency: transitive description: @@ -1593,10 +1624,10 @@ packages: dependency: "direct main" description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_parsing: dependency: transitive description: @@ -1665,26 +1696,26 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6" + sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" url: "https://pub.dev" source: hosted - version: "11.2.0" + version: "11.4.0" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: a5ebaa420cee8fd880ef10dedd42c6b3f493e7dbe27d7e0a7e1798669373082a + sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc url: "https://pub.dev" source: hosted - version: "12.0.4" + version: "12.1.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "6ca25ee52518a8a26e80aaefe3c71caf6e2dfd809c1b20900d0882df6faed36e" + sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98 url: "https://pub.dev" source: hosted - version: "9.3.1" + version: "9.4.6" permission_handler_html: dependency: transitive description: @@ -1697,10 +1728,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: "5c43148f2bfb6d14c5a8162c0a712afe891f2d847f35fcff29c406b37da43c3c" + sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "4.3.0" permission_handler_windows: dependency: transitive description: @@ -1721,10 +1752,10 @@ packages: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" platform_detect: dependency: transitive description: @@ -1801,10 +1832,10 @@ packages: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" proj4dart: dependency: transitive description: @@ -1857,10 +1888,10 @@ packages: dependency: "direct main" description: name: purchases_flutter - sha256: "4ff3a62a685cd964590d2c8126be62c3ede3657a5421adf558fd95f01699643a" + sha256: "88099e7b2a9f140d565d6ded919b9b3b2a0187b59542e46abee1b16b319c2025" url: "https://pub.dev" source: hosted - version: "6.29.0" + version: "8.5.1" qr: dependency: transitive description: @@ -1869,14 +1900,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" - qr_code_scanner: + qr_code_scanner_plus: dependency: "direct main" description: - name: qr_code_scanner - sha256: f23b68d893505a424f0bd2e324ebea71ed88465d572d26bb8d2e78a4749591fd + name: qr_code_scanner_plus + sha256: "39696b50d277097ee4d90d4292de36f38c66213a4f5216a06b2bdd2b63117859" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "2.0.10+1" qr_image: dependency: "direct main" description: @@ -2182,10 +2213,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" sprintf: dependency: transitive description: @@ -2238,26 +2269,26 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" string_validator: dependency: transitive description: @@ -2310,34 +2341,34 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test: dependency: transitive description: name: test - sha256: "713a8789d62f3233c46b4a90b174737b2c04cb6ae4500f2aa8b1be8f03f5e67f" + sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e" url: "https://pub.dev" source: hosted - version: "1.25.8" + version: "1.25.15" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.4" test_core: dependency: transitive description: name: test_core - sha256: "12391302411737c176b0b5d6491f466b0dd56d4763e347b6714efbaa74d7953d" + sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa" url: "https://pub.dev" source: hosted - version: "0.6.5" + version: "0.6.8" text_to_speech: dependency: "direct main" description: @@ -2410,30 +2441,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - uni_links: - dependency: "direct main" - description: - name: uni_links - sha256: "051098acfc9e26a9fde03b487bef5d3d228ca8f67693480c6f33fd4fbb8e2b6e" - url: "https://pub.dev" - source: hosted - version: "0.5.1" - uni_links_platform_interface: - dependency: transitive - description: - name: uni_links_platform_interface - sha256: "929cf1a71b59e3b7c2d8a2605a9cf7e0b125b13bc858e55083d88c62722d4507" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - uni_links_web: - dependency: transitive - description: - name: uni_links_web - sha256: "7539db908e25f67de2438e33cc1020b30ab94e66720b5677ba6763b25f6394df" - url: "https://pub.dev" - source: hosted - version: "0.1.0" unicode: dependency: transitive description: @@ -2606,18 +2613,18 @@ packages: dependency: "direct main" description: name: video_compress - sha256: "5b42d89f3970c956bad7a86c29682b0892c11a4ddf95ae6e29897ee28788e377" + sha256: "31bc5cdb9a02ba666456e5e1907393c28e6e0e972980d7d8d619a7beda0d4f20" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" video_player: dependency: "direct main" description: name: video_player - sha256: e30df0d226c4ef82e2c150ebf6834b3522cf3f654d8e2f9419d376cdc071425d + sha256: "4a8c3492d734f7c39c2588a3206707a05ee80cef52e8c7f3b2078d430c84bc17" url: "https://pub.dev" source: hosted - version: "2.9.1" + version: "2.9.2" video_player_android: dependency: transitive description: @@ -2654,10 +2661,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.3.1" wakelock_plus: dependency: "direct main" description: @@ -2718,10 +2725,10 @@ packages: dependency: "direct main" description: name: webrtc_interface - sha256: abec3ab7956bd5ac539cf34a42fa0c82ea26675847c0966bb85160400eea9388 + sha256: "10fc6dc0ac16f909f5e434c18902415211d759313c87261f1e4ec5b4f6a04c26" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" win32: dependency: "direct overridden" description: @@ -2779,5 +2786,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.7.0-0 <4.0.0" flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index fbe619add..b95993dbb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,11 +13,11 @@ environment: dependencies: animations: ^2.0.11 - archive: ^3.6.1 + app_links: ^6.3.3 + archive: ^3.4.10 async: ^2.11.0 badges: ^3.1.2 blurhash_dart: ^1.2.1 - callkeep: ^0.3.2 characters: ^1.2.0 chewie: ^1.8.1 collection: ^1.18.0 @@ -37,7 +37,6 @@ dependencies: file_selector: ^1.0.3 flutter: sdk: flutter - flutter_app_badger: ^1.5.0 flutter_cache_manager: ^3.4.1 flutter_foreground_task: ^6.1.3 flutter_highlighter: ^0.1.1 @@ -46,15 +45,14 @@ dependencies: flutter_localizations: sdk: flutter flutter_map: ^6.1.0 - flutter_olm: 1.3.2 # Keep in sync with scripts/prepare-web.sh ! 1.4.0 does currently not build on Android + flutter_new_badger: ^1.1.1 + flutter_olm: 2.0.0 flutter_openssl_crypto: ^0.3.0 - flutter_ringtone_player: ^4.0.0+2 flutter_secure_storage: ^9.2.3 - flutter_shortcuts: - git: https://github.com/krille-chan/flutter_shortcuts.git + flutter_shortcuts_new: ^2.0.0 flutter_typeahead: ^5.2.0 - flutter_web_auth_2: ^3.1.1 # Version 4 blocked by https://github.com/MixinNetwork/flutter-plugins/issues/379 - flutter_webrtc: ^0.11.7 + flutter_web_auth_2: ^4.1.0 + flutter_webrtc: ^0.12.9 geolocator: ^13.0.1 go_router: ^14.3.0 handy_window: ^0.4.0 @@ -76,17 +74,17 @@ dependencies: # matrix: ^0.37.0 # Pangea# mime: ^1.0.6 - native_imaging: ^0.1.1 + native_imaging: ^0.2.0 opus_caf_converter_dart: ^1.0.1 package_info_plus: ^8.1.1 pasteboard: ^0.2.0 path: ^1.9.0 path_provider: ^2.1.2 - permission_handler: ^11.0.1 + permission_handler: ^11.4.0 pretty_qr_code: ^3.2.1 provider: ^6.0.2 punycode: ^1.0.0 - qr_code_scanner: ^1.0.1 + qr_code_scanner_plus: ^2.0.10+1 qr_image: ^1.0.0 receive_sharing_intent: ^1.8.1 record: ^5.1.2 @@ -98,13 +96,12 @@ dependencies: sqlcipher_flutter_libs: ^0.6.1 swipe_to_action: ^0.3.0 tor_detector_web: ^1.1.0 - uni_links: ^0.5.1 unifiedpush: ^5.0.1 unifiedpush_ui: ^0.1.0 universal_html: ^2.2.4 url_launcher: ^6.2.5 - video_compress: ^3.1.3 - video_player: ^2.8.5 + video_compress: ^3.1.4 + video_player: ^2.9.2 wakelock_plus: ^1.2.2 webrtc_interface: ^1.0.13 # #Pangea @@ -123,12 +120,12 @@ dependencies: path: pangea_packages/fcm_shared_isolate flutter_svg: ^2.0.10+1 get_storage: ^2.1.1 - in_app_purchase: ^3.1.13 + in_app_purchase: ^3.2.1 jwt_decode: ^0.3.1 language_tool: ^2.2.0 material_symbols_icons: ^4.2741.0 open_file: ^3.3.2 - purchases_flutter: ^6.26.0 + purchases_flutter: ^8.5.1 sentry_flutter: ^8.2.0 shimmer: ^3.0.0 rive: 0.11.11 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index bd80c81e1..60a2f4afe 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,7 +6,9 @@ #include "generated_plugin_registrant.h" +#include #include +#include #include #include #include @@ -26,8 +28,12 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { + AppLinksPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("AppLinksPluginCApi")); AudioplayersWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("AudioplayersWindowsPlugin")); + DesktopWebviewWindowPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("DesktopWebviewWindowPlugin")); DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); EmojiPickerFlutterPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 095209a76..5f639e806 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,7 +3,9 @@ # list(APPEND FLUTTER_PLUGIN_LIST + app_links audioplayers_windows + desktop_webview_window dynamic_color emoji_picker_flutter file_selector_windows