forked from baron/baron-sso
Merge branch 'dev' into feat/org-chart-rebac
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart' hide tr;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -17,28 +19,54 @@ class LocaleGate extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LocaleGateState extends State<LocaleGate> {
|
||||
bool _syncScheduled = false;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_applyLocale();
|
||||
_scheduleLocaleSync();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(LocaleGate oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.localeCode != widget.localeCode) {
|
||||
_applyLocale();
|
||||
_scheduleLocaleSync();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _applyLocale() async {
|
||||
final normalized = normalizeLocaleCode(widget.localeCode);
|
||||
LocaleStorage.write(normalized);
|
||||
webWindow.setTitle(tr('ui.userfront.app_title'));
|
||||
if (context.locale.languageCode == normalized) {
|
||||
void _scheduleLocaleSync() {
|
||||
if (_syncScheduled) {
|
||||
return;
|
||||
}
|
||||
_syncScheduled = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_syncScheduled = false;
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
unawaited(_applyLocale());
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _applyLocale() async {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
final normalized = normalizeLocaleCode(widget.localeCode);
|
||||
LocaleStorage.write(normalized);
|
||||
final localization = EasyLocalization.of(context);
|
||||
if (localization == null) {
|
||||
return;
|
||||
}
|
||||
if (localization.currentLocale?.languageCode == normalized) {
|
||||
webWindow.setTitle(tr('ui.userfront.app_title'));
|
||||
return;
|
||||
}
|
||||
await localization.setLocale(Locale(normalized));
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
await context.setLocale(Locale(normalized));
|
||||
webWindow.setTitle(tr('ui.userfront.app_title'));
|
||||
}
|
||||
|
||||
|
||||
@@ -183,10 +183,11 @@ class LocaleStorageEngine implements LocaleStorageBackend {
|
||||
|
||||
final legacy = _readByKey(LocaleStoragePolicy.legacyKey);
|
||||
if (LocaleStoragePolicy.shouldMigrateLegacy(
|
||||
current: current,
|
||||
legacy: legacy,
|
||||
)) {
|
||||
_writeByKey(LocaleStoragePolicy.currentKey, legacy!);
|
||||
current: current,
|
||||
legacy: legacy,
|
||||
) &&
|
||||
legacy != null) {
|
||||
_writeByKey(LocaleStoragePolicy.currentKey, legacy);
|
||||
_removeEverywhere(LocaleStoragePolicy.legacyKey);
|
||||
return legacy;
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@ String resolvePreferredLocaleCode() {
|
||||
}
|
||||
}
|
||||
final deviceLocale = PlatformDispatcher.instance.locale;
|
||||
final languageTag =
|
||||
deviceLocale.countryCode == null || deviceLocale.countryCode!.isEmpty
|
||||
final countryCode = deviceLocale.countryCode;
|
||||
final languageTag = countryCode == null || countryCode.isEmpty
|
||||
? deviceLocale.languageCode
|
||||
: '${deviceLocale.languageCode}-${deviceLocale.countryCode}';
|
||||
: '${deviceLocale.languageCode}-$countryCode';
|
||||
return normalizeLocaleCode(languageTag);
|
||||
}
|
||||
|
||||
@@ -101,3 +101,17 @@ String buildSigninRedirectPath(String localeCode, Uri uri) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String buildLocalizedHomePath(Uri uri, {String? preferredLocaleCode}) {
|
||||
final resolvedLocale =
|
||||
extractLocaleFromPath(uri) ??
|
||||
normalizeLocaleCode(preferredLocaleCode ?? resolvePreferredLocaleCode());
|
||||
return '/$resolvedLocale/dashboard';
|
||||
}
|
||||
|
||||
String buildLocalizedSigninPath(Uri uri, {String? preferredLocaleCode}) {
|
||||
final resolvedLocale =
|
||||
extractLocaleFromPath(uri) ??
|
||||
normalizeLocaleCode(preferredLocaleCode ?? resolvePreferredLocaleCode());
|
||||
return '/$resolvedLocale/signin';
|
||||
}
|
||||
|
||||
26
userfront/lib/core/services/null_check_recovery.dart
Normal file
26
userfront/lib/core/services/null_check_recovery.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import '../i18n/locale_utils.dart';
|
||||
|
||||
String? computeNullCheckRecoveryTarget({
|
||||
required Object exception,
|
||||
required Uri uri,
|
||||
required String preferredLocaleCode,
|
||||
}) {
|
||||
final message = exception.toString();
|
||||
if (!message.contains('Null check operator used on a null value')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final localeCode =
|
||||
extractLocaleFromPath(uri) ?? normalizeLocaleCode(preferredLocaleCode);
|
||||
final path = uri.path;
|
||||
final localeRootPath = '/$localeCode';
|
||||
if (path != '/' && path != localeRootPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final target = '/$localeCode/signin';
|
||||
if (path == target) {
|
||||
return null;
|
||||
}
|
||||
return target;
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import 'package:web/web.dart' as web;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'dart:js_interop';
|
||||
import 'auth_token_store.dart';
|
||||
import '../i18n/locale_utils.dart';
|
||||
|
||||
void implSendLoginSuccess(String token) {
|
||||
var effectiveToken = token;
|
||||
@@ -87,8 +88,9 @@ void implSendLoginSuccess(String token) {
|
||||
}
|
||||
|
||||
// No opener and no redirect: fall back to local navigation
|
||||
debugPrint('No opener found. Redirecting to /.');
|
||||
web.window.location.href = '/';
|
||||
final fallbackTarget = buildLocalizedHomePath(Uri.base);
|
||||
debugPrint('No opener found. Redirecting to $fallbackTarget.');
|
||||
web.window.location.href = fallbackTarget;
|
||||
}
|
||||
|
||||
bool implIsPopup() {
|
||||
|
||||
@@ -13,7 +13,13 @@ class LanguageSelector extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final current = context.locale.languageCode;
|
||||
final localization = EasyLocalization.of(context);
|
||||
final resolvedCurrent = normalizeLocaleCode(
|
||||
localization?.currentLocale?.languageCode,
|
||||
);
|
||||
final current = (resolvedCurrent == 'ko' || resolvedCurrent == 'en')
|
||||
? resolvedCurrent
|
||||
: 'en';
|
||||
final items = [
|
||||
DropdownMenuItem(value: 'ko', child: Text(tr('ui.common.language_ko'))),
|
||||
DropdownMenuItem(
|
||||
@@ -34,9 +40,16 @@ class LanguageSelector extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
LocaleStorage.write(value);
|
||||
await context.setLocale(Locale(value));
|
||||
if (localization != null) {
|
||||
await localization.setLocale(Locale(value));
|
||||
}
|
||||
if (!context.mounted) return;
|
||||
final uri = GoRouterState.of(context).uri;
|
||||
Uri uri;
|
||||
try {
|
||||
uri = GoRouterState.of(context).uri;
|
||||
} catch (_) {
|
||||
uri = Uri.base;
|
||||
}
|
||||
final target = buildLocalizedPath(value, uri);
|
||||
context.go(target);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user