refactor: Improve sso login UX on web

pull/1577/head
krille-chan 9 months ago
parent e4b8d45715
commit 7cbc518951
No known key found for this signature in database

@ -2822,5 +2822,13 @@
"addLink": "Add link", "addLink": "Add link",
"unableToJoinChat": "Unable to join chat. Maybe the other party has already closed the conversation.", "unableToJoinChat": "Unable to join chat. Maybe the other party has already closed the conversation.",
"previous": "Previous", "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."
} }

@ -33,7 +33,6 @@ class HomeserverPicker extends StatefulWidget {
class HomeserverPickerController extends State<HomeserverPicker> { class HomeserverPickerController extends State<HomeserverPicker> {
bool isLoading = false; bool isLoading = false;
bool isLoggingIn = false;
final TextEditingController homeserverController = TextEditingController( final TextEditingController homeserverController = TextEditingController(
text: AppConfig.defaultHomeserver, text: AppConfig.defaultHomeserver,
@ -61,58 +60,29 @@ class HomeserverPickerController extends State<HomeserverPicker> {
isTorBrowser = isTor; 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 /// 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 /// 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 /// well-known information and forwards to the login page depending on the
/// login type. /// login type.
Future<void> checkHomeserverAction([_]) async { Future<void> checkHomeserverAction({bool legacyPasswordLogin = false}) async {
final homeserverInput = final homeserverInput =
homeserverController.text.trim().toLowerCase().replaceAll(' ', '-'); homeserverController.text.trim().toLowerCase().replaceAll(' ', '-');
if (homeserverInput.isEmpty || !homeserverInput.contains('.')) { if (homeserverInput.isEmpty) {
setState(() { setState(() {
error = loginFlows = null; error = loginFlows = null;
isLoading = false; isLoading = false;
Matrix.of(context).getLoginClient().homeserver = null; Matrix.of(context).getLoginClient().homeserver = null;
_lastCheckedUrl = null;
}); });
return; return;
} }
if (_lastCheckedUrl == homeserverInput) return;
_lastCheckedUrl = homeserverInput;
setState(() { setState(() {
error = loginFlows = null; error = loginFlows = null;
isLoading = true; isLoading = true;
}); });
final l10n = L10n.of(context);
try { try {
var homeserver = Uri.parse(homeserverInput); var homeserver = Uri.parse(homeserverInput);
if (homeserver.scheme.isEmpty) { if (homeserver.scheme.isEmpty) {
@ -121,6 +91,21 @@ class HomeserverPickerController extends State<HomeserverPicker> {
final client = Matrix.of(context).getLoginClient(); final client = Matrix.of(context).getLoginClient();
final (_, _, loginFlows) = await client.checkHomeserver(homeserver); final (_, _, loginFlows) = await client.checkHomeserver(homeserver);
this.loginFlows = loginFlows; 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) { } catch (e) {
setState( setState(
() => error = (e).toLocalizedString( () => error = (e).toLocalizedString(
@ -176,7 +161,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
setState(() { setState(() {
error = null; error = null;
isLoading = isLoggingIn = true; isLoading = true;
}); });
try { try {
await Matrix.of(context).getLoginClient().login( await Matrix.of(context).getLoginClient().login(
@ -191,27 +176,16 @@ class HomeserverPickerController extends State<HomeserverPicker> {
} finally { } finally {
if (mounted) { if (mounted) {
setState(() { 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 @override
void initState() { void initState() {
_checkTorBrowser(); _checkTorBrowser();
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback(checkHomeserverAction);
} }
@override @override
@ -223,7 +197,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
if (file == null) return; if (file == null) return;
setState(() { setState(() {
error = null; error = null;
isLoading = isLoggingIn = true; isLoading = true;
}); });
try { try {
final client = Matrix.of(context).getLoginClient(); final client = Matrix.of(context).getLoginClient();
@ -236,7 +210,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
} finally { } finally {
if (mounted) { if (mounted) {
setState(() { setState(() {
isLoading = isLoggingIn = false; isLoading = false;
}); });
} }
} }
@ -245,7 +219,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
void onMoreAction(MoreLoginActions action) { void onMoreAction(MoreLoginActions action) {
switch (action) { switch (action) {
case MoreLoginActions.passwordLogin: case MoreLoginActions.passwordLogin:
login(); checkHomeserverAction(legacyPasswordLogin: true);
case MoreLoginActions.privacy: case MoreLoginActions.privacy:
launchUrlString(AppConfig.privacyUrl); launchUrlString(AppConfig.privacyUrl);
case MoreLoginActions.about: case MoreLoginActions.about:

@ -142,30 +142,13 @@ class HomeserverPickerView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
TextField( TextField(
onChanged: onSubmitted: (_) =>
controller.tryCheckHomeserverActionWithCooldown, controller.checkHomeserverAction(),
onSubmitted: controller.onSubmitted,
onTap:
controller.tryCheckHomeserverActionWithCooldown,
controller: controller.homeserverController, controller: controller.homeserverController,
autocorrect: false, autocorrect: false,
keyboardType: TextInputType.url, keyboardType: TextInputType.url,
decoration: InputDecoration( decoration: InputDecoration(
prefixIcon: controller.isLoading prefixIcon: const Icon(Icons.search_outlined),
? 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),
filled: false, filled: false,
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(
@ -219,25 +202,21 @@ class HomeserverPickerView extends StatelessWidget {
backgroundColor: theme.colorScheme.primary, backgroundColor: theme.colorScheme.primary,
foregroundColor: theme.colorScheme.onPrimary, foregroundColor: theme.colorScheme.onPrimary,
), ),
onPressed: onPressed: controller.isLoading
controller.isLoggingIn || controller.isLoading ? null
? null : controller.checkHomeserverAction,
: controller.supportsSso child: controller.isLoading
? controller.ssoLoginAction ? const LinearProgressIndicator()
: controller.supportsPasswordLogin : Text(L10n.of(context).continueText),
? controller.login
: null,
child: Text(L10n.of(context).continueText),
), ),
TextButton( TextButton(
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: theme.colorScheme.secondary, foregroundColor: theme.colorScheme.secondary,
textStyle: theme.textTheme.labelMedium, textStyle: theme.textTheme.labelMedium,
), ),
onPressed: onPressed: controller.isLoading
controller.isLoggingIn || controller.isLoading ? null
? null : controller.restoreBackup,
: controller.restoreBackup,
child: Text(L10n.of(context).hydrate), child: Text(L10n.of(context).hydrate),
), ),
], ],

Loading…
Cancel
Save