diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index d50e8f3fe..9744d666b 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2822,5 +2822,13 @@ "addLink": "Add link", "unableToJoinChat": "Unable to join chat. Maybe the other party has already closed the conversation.", "previous": "Previous", - "otherPartyNotLoggedIn": "The other party is currently not logged in and therefore cannot receive messages!" + "otherPartyNotLoggedIn": "The other party is currently not logged in and therefore cannot receive messages!", + "appWantsToUseForLogin": "Use '{server}' to log in", + "@appWantsToUseForLogin": { + "type": "text", + "placeholders": { + "server": {} + } + }, + "appWantsToUseForLoginDescription": "You hereby allow the app and website to share information about you." } diff --git a/lib/pages/homeserver_picker/homeserver_picker.dart b/lib/pages/homeserver_picker/homeserver_picker.dart index e379937ca..d8c584a98 100644 --- a/lib/pages/homeserver_picker/homeserver_picker.dart +++ b/lib/pages/homeserver_picker/homeserver_picker.dart @@ -33,7 +33,6 @@ class HomeserverPicker extends StatefulWidget { class HomeserverPickerController extends State { bool isLoading = false; - bool isLoggingIn = false; final TextEditingController homeserverController = TextEditingController( text: AppConfig.defaultHomeserver, @@ -61,58 +60,29 @@ class HomeserverPickerController extends State { isTorBrowser = isTor; } - String? _lastCheckedUrl; - - Timer? _checkHomeserverCooldown; - - tryCheckHomeserverActionWithCooldown([_]) { - _checkHomeserverCooldown?.cancel(); - _checkHomeserverCooldown = Timer( - const Duration(milliseconds: 500), - checkHomeserverAction, - ); - } - - void tryCheckHomeserverActionWithoutCooldown([_]) { - _checkHomeserverCooldown?.cancel(); - _lastCheckedUrl = null; - checkHomeserverAction(); - } - - void onSubmitted([_]) { - if (isLoading || _checkHomeserverCooldown?.isActive == true) { - return tryCheckHomeserverActionWithoutCooldown(); - } - if (supportsSso) return ssoLoginAction(); - if (supportsPasswordLogin) return login(); - return tryCheckHomeserverActionWithoutCooldown(); - } - /// Starts an analysis of the given homeserver. It uses the current domain and /// makes sure that it is prefixed with https. Then it searches for the /// well-known information and forwards to the login page depending on the /// login type. - Future checkHomeserverAction([_]) async { + Future checkHomeserverAction({bool legacyPasswordLogin = false}) async { final homeserverInput = homeserverController.text.trim().toLowerCase().replaceAll(' ', '-'); - if (homeserverInput.isEmpty || !homeserverInput.contains('.')) { + if (homeserverInput.isEmpty) { setState(() { error = loginFlows = null; isLoading = false; Matrix.of(context).getLoginClient().homeserver = null; - _lastCheckedUrl = null; }); return; } - if (_lastCheckedUrl == homeserverInput) return; - - _lastCheckedUrl = homeserverInput; setState(() { error = loginFlows = null; isLoading = true; }); + final l10n = L10n.of(context); + try { var homeserver = Uri.parse(homeserverInput); if (homeserver.scheme.isEmpty) { @@ -121,6 +91,21 @@ class HomeserverPickerController extends State { final client = Matrix.of(context).getLoginClient(); final (_, _, loginFlows) = await client.checkHomeserver(homeserver); this.loginFlows = loginFlows; + if (supportsSso && !legacyPasswordLogin) { + if (!PlatformInfos.isMobile) { + final consent = await showOkCancelAlertDialog( + context: context, + title: l10n.appWantsToUseForLogin(homeserverInput), + message: l10n.appWantsToUseForLoginDescription, + okLabel: l10n.continueText, + ); + if (consent != OkCancelResult.ok) return; + } + return ssoLoginAction(); + } + context.push( + '${GoRouter.of(context).routeInformationProvider.value.uri.path}/login', + ); } catch (e) { setState( () => error = (e).toLocalizedString( @@ -176,7 +161,7 @@ class HomeserverPickerController extends State { setState(() { error = null; - isLoading = isLoggingIn = true; + isLoading = true; }); try { await Matrix.of(context).getLoginClient().login( @@ -191,27 +176,16 @@ class HomeserverPickerController extends State { } finally { if (mounted) { setState(() { - isLoading = isLoggingIn = false; + isLoading = false; }); } } } - void login() async { - if (!supportsPasswordLogin) { - homeserverController.text = AppConfig.defaultHomeserver; - await checkHomeserverAction(); - } - context.push( - '${GoRouter.of(context).routeInformationProvider.value.uri.path}/login', - ); - } - @override void initState() { _checkTorBrowser(); super.initState(); - WidgetsBinding.instance.addPostFrameCallback(checkHomeserverAction); } @override @@ -223,7 +197,7 @@ class HomeserverPickerController extends State { if (file == null) return; setState(() { error = null; - isLoading = isLoggingIn = true; + isLoading = true; }); try { final client = Matrix.of(context).getLoginClient(); @@ -236,7 +210,7 @@ class HomeserverPickerController extends State { } finally { if (mounted) { setState(() { - isLoading = isLoggingIn = false; + isLoading = false; }); } } @@ -245,7 +219,7 @@ class HomeserverPickerController extends State { void onMoreAction(MoreLoginActions action) { switch (action) { case MoreLoginActions.passwordLogin: - login(); + checkHomeserverAction(legacyPasswordLogin: true); case MoreLoginActions.privacy: launchUrlString(AppConfig.privacyUrl); case MoreLoginActions.about: diff --git a/lib/pages/homeserver_picker/homeserver_picker_view.dart b/lib/pages/homeserver_picker/homeserver_picker_view.dart index 1d022f68e..040a60a34 100644 --- a/lib/pages/homeserver_picker/homeserver_picker_view.dart +++ b/lib/pages/homeserver_picker/homeserver_picker_view.dart @@ -142,30 +142,13 @@ class HomeserverPickerView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextField( - onChanged: - controller.tryCheckHomeserverActionWithCooldown, - onSubmitted: controller.onSubmitted, - onTap: - controller.tryCheckHomeserverActionWithCooldown, + onSubmitted: (_) => + controller.checkHomeserverAction(), controller: controller.homeserverController, autocorrect: false, keyboardType: TextInputType.url, decoration: InputDecoration( - prefixIcon: controller.isLoading - ? Container( - width: 16, - height: 16, - alignment: Alignment.center, - child: const SizedBox( - width: 16, - height: 16, - child: - CircularProgressIndicator.adaptive( - strokeWidth: 2, - ), - ), - ) - : const Icon(Icons.search_outlined), + prefixIcon: const Icon(Icons.search_outlined), filled: false, border: OutlineInputBorder( borderRadius: BorderRadius.circular( @@ -219,25 +202,21 @@ class HomeserverPickerView extends StatelessWidget { backgroundColor: theme.colorScheme.primary, foregroundColor: theme.colorScheme.onPrimary, ), - onPressed: - controller.isLoggingIn || controller.isLoading - ? null - : controller.supportsSso - ? controller.ssoLoginAction - : controller.supportsPasswordLogin - ? controller.login - : null, - child: Text(L10n.of(context).continueText), + onPressed: controller.isLoading + ? null + : controller.checkHomeserverAction, + child: controller.isLoading + ? const LinearProgressIndicator() + : Text(L10n.of(context).continueText), ), TextButton( style: TextButton.styleFrom( foregroundColor: theme.colorScheme.secondary, textStyle: theme.textTheme.labelMedium, ), - onPressed: - controller.isLoggingIn || controller.isLoading - ? null - : controller.restoreBackup, + onPressed: controller.isLoading + ? null + : controller.restoreBackup, child: Text(L10n.of(context).hydrate), ), ],