forked from baron/baron-sso
fix userfront mobile approval close flow
This commit is contained in:
@@ -100,6 +100,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
_redirectUrl = widget.redirectUrl;
|
||||
_passwordFocusNode.addListener(_handlePasswordFocusChange);
|
||||
HardwareKeyboard.instance.addHandler(_handleHardwareKeyEvent);
|
||||
_verificationOnly = _isVerificationOnlyUri(Uri.base);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final uri = Uri.base;
|
||||
@@ -127,8 +128,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
final hasVerificationToken =
|
||||
widget.verificationToken != null || hasTokenParam;
|
||||
final hasLoginCode = loginIdParam != null && codeParam != null;
|
||||
_verificationOnly =
|
||||
hasVerificationToken || hasLoginCode || hasShortCodePath;
|
||||
final notice = uri.queryParameters['notice'];
|
||||
|
||||
if (hasShortCodePath) {
|
||||
@@ -174,6 +173,15 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
});
|
||||
}
|
||||
|
||||
bool _isVerificationOnlyUri(Uri uri) {
|
||||
final loginIdParam = uri.queryParameters['loginId'];
|
||||
final codeParam = uri.queryParameters['code'];
|
||||
return widget.verificationToken != null ||
|
||||
uri.queryParameters.containsKey('t') ||
|
||||
(loginIdParam != null && codeParam != null) ||
|
||||
extractLoginShortCode(uri) != null;
|
||||
}
|
||||
|
||||
void _handlePasswordFocusChange() {
|
||||
if (!mounted) {
|
||||
return;
|
||||
@@ -765,6 +773,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
_onVerificationAction?.call();
|
||||
}
|
||||
|
||||
void _closeVerificationWindowIfPossible() {
|
||||
if (webWindow.hasOpener()) {
|
||||
webWindow.close();
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildVerificationResultView() {
|
||||
return Center(
|
||||
child: Padding(
|
||||
@@ -802,7 +816,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
return;
|
||||
}
|
||||
if (_verificationOnly) {
|
||||
webWindow.close();
|
||||
_closeVerificationWindowIfPossible();
|
||||
return;
|
||||
}
|
||||
final hasLocalSession =
|
||||
@@ -827,6 +841,55 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVerificationPendingView() {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 48,
|
||||
height: 48,
|
||||
child: CircularProgressIndicator(strokeWidth: 4),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
tr('ui.userfront.login.verification.title_pending'),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
tr('msg.userfront.login.verification.pending_remote'),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: Colors.black54),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVerificationOnlyScaffold() {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: Text(_verificationPageTitle),
|
||||
leading: _verificationApproved && _onVerificationAction != null
|
||||
? IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: _runVerificationExitAction,
|
||||
)
|
||||
: null,
|
||||
actions: const [ThemeToggleButton(compact: true)],
|
||||
),
|
||||
body: _verificationApproved
|
||||
? _buildVerificationResultView()
|
||||
: _buildVerificationPendingView(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _verifyToken(String token) async {
|
||||
debugPrint("[Auth] Starting verification for token: $token");
|
||||
final approvedMessage = tr('msg.userfront.login.verification.approved');
|
||||
@@ -858,7 +921,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -894,7 +957,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -951,7 +1014,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -972,7 +1035,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -985,7 +1048,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
remoteApprovedMessage,
|
||||
title: tr('ui.userfront.login.verification.title_remote'),
|
||||
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -1005,7 +1068,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -1053,7 +1116,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -1074,7 +1137,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -1087,7 +1150,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
remoteApprovedMessage,
|
||||
title: tr('ui.userfront.login.verification.title_remote'),
|
||||
actionLabel: tr('ui.userfront.login.verification.action_label_close'),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -1105,7 +1168,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
actionLabel: tr(
|
||||
'ui.userfront.login.verification.action_label_close',
|
||||
),
|
||||
onAction: () => webWindow.close(),
|
||||
onAction: _closeVerificationWindowIfPossible,
|
||||
);
|
||||
}
|
||||
return;
|
||||
@@ -1609,21 +1672,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
),
|
||||
);
|
||||
|
||||
if (_verificationOnly && _verificationApproved) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: Text(_verificationPageTitle),
|
||||
leading: _onVerificationAction == null
|
||||
? null
|
||||
: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: _runVerificationExitAction,
|
||||
),
|
||||
actions: const [ThemeToggleButton(compact: true)],
|
||||
),
|
||||
body: _buildVerificationResultView(),
|
||||
);
|
||||
if (_verificationOnly) {
|
||||
return _buildVerificationOnlyScaffold();
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
|
||||
Reference in New Issue
Block a user