mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
🐛 fix(desktop-onboarding): improve auth countdown and error UI (#11788)
* 🐛 fix(desktop-onboarding): improve auth countdown and error UI - Add local countdown state for smooth 1-second updates (was 3s) - Add gap between error alert and retry button - Add i18n support for "Authorization timed out" error message Fixes LOBE-4267, LOBE-4268 * 🌐 chore(i18n): add timeout error translations for all locales
This commit is contained in:
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "تسجيل الدخول",
|
||||
"screen5.description": "سجّل الدخول لمزامنة الوكلاء والمجموعات والإعدادات والسياق عبر جميع الأجهزة.",
|
||||
"screen5.errors.desktopOnlyOidc": "تفويض OIDC متاح فقط في تطبيق سطح المكتب.",
|
||||
"screen5.errors.timedOut": "انتهت مهلة التفويض، يرجى المحاولة مرة أخرى",
|
||||
"screen5.legacyLocalDb.link": "ترحيل قاعدة البيانات المحلية القديمة",
|
||||
"screen5.methods.cloud.description": "سجّل الدخول باستخدام حساب LobeHub Cloud الخاص بك لمزامنة كل شيء بسلاسة",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Вход",
|
||||
"screen5.description": "Влез, за да синхронизираш Агенти, Групи, настройки и Контекст на всички устройства.",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC удостоверяване е налично само в десктоп версията на приложението.",
|
||||
"screen5.errors.timedOut": "Времето за оторизация изтече, моля опитайте отново",
|
||||
"screen5.legacyLocalDb.link": "Мигрирай остаряла локална база данни",
|
||||
"screen5.methods.cloud.description": "Влез с твоя LobeHub Cloud акаунт за безпроблемна синхронизация",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Anmeldung",
|
||||
"screen5.description": "Melden Sie sich an, um Agenten, Gruppen, Einstellungen und Kontexte auf allen Geräten zu synchronisieren.",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC-Autorisierung ist nur in der Desktop-App verfügbar.",
|
||||
"screen5.errors.timedOut": "Autorisierung abgelaufen, bitte erneut versuchen",
|
||||
"screen5.legacyLocalDb.link": "Alte lokale Datenbank migrieren",
|
||||
"screen5.methods.cloud.description": "Melden Sie sich mit Ihrem LobeHub Cloud-Konto an, um alles nahtlos zu synchronisieren",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Sign in",
|
||||
"screen5.description": "Sign in to sync Agents, Groups, settings, and Context across all devices.",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC authorization is only available in the desktop app runtime.",
|
||||
"screen5.errors.timedOut": "Authorization timed out, please try again",
|
||||
"screen5.legacyLocalDb.link": "Migrate legacy local database",
|
||||
"screen5.methods.cloud.description": "Sign in with your LobeHub Cloud account to sync everything seamlessly",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Iniciar sesión",
|
||||
"screen5.description": "Inicia sesión para sincronizar Agentes, Grupos, configuración y Contexto en todos tus dispositivos.",
|
||||
"screen5.errors.desktopOnlyOidc": "La autorización OIDC solo está disponible en la aplicación de escritorio.",
|
||||
"screen5.errors.timedOut": "La autorización expiró, por favor intente de nuevo",
|
||||
"screen5.legacyLocalDb.link": "Migrar base de datos local heredada",
|
||||
"screen5.methods.cloud.description": "Inicia sesión con tu cuenta de LobeHub Cloud para sincronizar todo sin problemas",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "ورود",
|
||||
"screen5.description": "برای همگامسازی عوامل، گروهها، تنظیمات و زمینهها در تمام دستگاهها وارد شوید.",
|
||||
"screen5.errors.desktopOnlyOidc": "احراز هویت OIDC فقط در نسخه دسکتاپ در دسترس است.",
|
||||
"screen5.errors.timedOut": "زمان احراز هویت به پایان رسید، لطفاً دوباره تلاش کنید",
|
||||
"screen5.legacyLocalDb.link": "انتقال پایگاه داده محلی قدیمی",
|
||||
"screen5.methods.cloud.description": "با حساب LobeHub Cloud خود وارد شوید تا همه چیز بهصورت یکپارچه همگامسازی شود",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Connexion",
|
||||
"screen5.description": "Connectez-vous pour synchroniser Agents, Groupes, paramètres et Contexte sur tous vos appareils.",
|
||||
"screen5.errors.desktopOnlyOidc": "L'autorisation OIDC est uniquement disponible dans l'application de bureau.",
|
||||
"screen5.errors.timedOut": "L'autorisation a expiré, veuillez réessayer",
|
||||
"screen5.legacyLocalDb.link": "Migrer l’ancienne base de données locale",
|
||||
"screen5.methods.cloud.description": "Connectez-vous avec votre compte LobeHub Cloud pour tout synchroniser facilement",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Accesso",
|
||||
"screen5.description": "Accedi per sincronizzare Agenti, Gruppi, impostazioni e Contesto su tutti i dispositivi.",
|
||||
"screen5.errors.desktopOnlyOidc": "L'autorizzazione OIDC è disponibile solo nell'app desktop.",
|
||||
"screen5.errors.timedOut": "Autorizzazione scaduta, riprova",
|
||||
"screen5.legacyLocalDb.link": "Migra il database locale legacy",
|
||||
"screen5.methods.cloud.description": "Accedi con il tuo account LobeHub Cloud per sincronizzare tutto senza problemi",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "サインイン",
|
||||
"screen5.description": "すべてのデバイスでエージェント、グループ、設定、コンテキストを同期するにはサインインしてください。",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC 認証はデスクトップアプリでのみ利用可能です。",
|
||||
"screen5.errors.timedOut": "認証がタイムアウトしました。もう一度お試しください",
|
||||
"screen5.legacyLocalDb.link": "旧ローカルデータベースを移行する",
|
||||
"screen5.methods.cloud.description": "LobeHub Cloud アカウントでサインインして、すべてをシームレスに同期",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "로그인",
|
||||
"screen5.description": "에이전트, 그룹, 설정, 컨텍스트를 모든 기기에서 동기화하려면 로그인하세요.",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC 인증은 데스크톱 앱에서만 사용할 수 있습니다.",
|
||||
"screen5.errors.timedOut": "인증 시간이 초과되었습니다. 다시 시도해 주세요",
|
||||
"screen5.legacyLocalDb.link": "이전 로컬 데이터베이스 마이그레이션",
|
||||
"screen5.methods.cloud.description": "LobeHub 클라우드 계정으로 로그인하여 모든 것을 원활하게 동기화하세요",
|
||||
"screen5.methods.cloud.name": "LobeHub 클라우드",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Aanmelden",
|
||||
"screen5.description": "Meld je aan om Agenten, Groepen, instellingen en Context te synchroniseren op al je apparaten.",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC-autorisatie is alleen beschikbaar in de desktop-app.",
|
||||
"screen5.errors.timedOut": "Autorisatie verlopen, probeer het opnieuw",
|
||||
"screen5.legacyLocalDb.link": "Migreer verouderde lokale database",
|
||||
"screen5.methods.cloud.description": "Meld je aan met je LobeHub Cloud-account om alles naadloos te synchroniseren",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Logowanie",
|
||||
"screen5.description": "Zaloguj się, aby synchronizować Agentów, Grupy, ustawienia i Kontekst na wszystkich urządzeniach.",
|
||||
"screen5.errors.desktopOnlyOidc": "Autoryzacja OIDC jest dostępna tylko w wersji desktopowej aplikacji.",
|
||||
"screen5.errors.timedOut": "Autoryzacja wygasła, spróbuj ponownie",
|
||||
"screen5.legacyLocalDb.link": "Migruj starszą lokalną bazę danych",
|
||||
"screen5.methods.cloud.description": "Zaloguj się na konto LobeHub Cloud, aby bezproblemowo synchronizować wszystko",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Entrar",
|
||||
"screen5.description": "Entre para sincronizar Agentes, Grupos, configurações e Contexto em todos os dispositivos.",
|
||||
"screen5.errors.desktopOnlyOidc": "A autorização OIDC está disponível apenas no aplicativo desktop.",
|
||||
"screen5.errors.timedOut": "A autorização expirou, por favor tente novamente",
|
||||
"screen5.legacyLocalDb.link": "Migrar banco de dados local legado",
|
||||
"screen5.methods.cloud.description": "Entre com sua conta LobeHub Cloud para sincronizar tudo de forma integrada",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Вход",
|
||||
"screen5.description": "Войдите, чтобы синхронизировать Агентов, Группы, настройки и Контекст на всех устройствах.",
|
||||
"screen5.errors.desktopOnlyOidc": "Авторизация OIDC доступна только в настольной версии приложения.",
|
||||
"screen5.errors.timedOut": "Время авторизации истекло, пожалуйста, попробуйте снова",
|
||||
"screen5.legacyLocalDb.link": "Перенести устаревшую локальную базу данных",
|
||||
"screen5.methods.cloud.description": "Войдите с помощью аккаунта LobeHub Cloud для бесшовной синхронизации",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Giriş Yap",
|
||||
"screen5.description": "Ajanlar, Gruplar, ayarlar ve Bağlam'ı tüm cihazlar arasında senkronize etmek için giriş yapın.",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC yetkilendirmesi yalnızca masaüstü uygulamasında kullanılabilir.",
|
||||
"screen5.errors.timedOut": "Yetkilendirme zaman aşımına uğradı, lütfen tekrar deneyin",
|
||||
"screen5.legacyLocalDb.link": "Eski yerel veritabanını taşı",
|
||||
"screen5.methods.cloud.description": "Her şeyi sorunsuz bir şekilde senkronize etmek için LobeHub Cloud hesabınızla giriş yapın",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "Đăng nhập",
|
||||
"screen5.description": "Đăng nhập để đồng bộ Tác nhân, Nhóm, cài đặt và Ngữ cảnh trên tất cả thiết bị.",
|
||||
"screen5.errors.desktopOnlyOidc": "Xác thực OIDC chỉ khả dụng trong ứng dụng desktop.",
|
||||
"screen5.errors.timedOut": "Xác thực đã hết hạn, vui lòng thử lại",
|
||||
"screen5.legacyLocalDb.link": "Di chuyển cơ sở dữ liệu cục bộ cũ",
|
||||
"screen5.methods.cloud.description": "Đăng nhập bằng tài khoản LobeHub Cloud để đồng bộ mọi thứ một cách liền mạch",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "登录",
|
||||
"screen5.description": "登录以在所有设备间同步代理、群组、设置和上下文。",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC 授权仅在桌面端运行时可用。",
|
||||
"screen5.errors.timedOut": "授权超时,请重试",
|
||||
"screen5.legacyLocalDb.link": "迁移旧版本地数据库",
|
||||
"screen5.methods.cloud.description": "使用您的 LobeHub 云账户登录,实现无缝同步",
|
||||
"screen5.methods.cloud.name": "LobeHub Cloud",
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"screen5.badge": "登入",
|
||||
"screen5.description": "登入以同步代理人、群組、設定與上下文至所有裝置。",
|
||||
"screen5.errors.desktopOnlyOidc": "OIDC 授權僅支援桌面應用程式執行環境。",
|
||||
"screen5.errors.timedOut": "授權逾時,請重試",
|
||||
"screen5.legacyLocalDb.link": "遷移舊版本地資料庫",
|
||||
"screen5.methods.cloud.description": "使用你的 LobeHub 雲端帳號登入,無縫同步所有內容",
|
||||
"screen5.methods.cloud.name": "LobeHub 雲端",
|
||||
|
||||
@@ -71,6 +71,7 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
const [isSigningOut, setIsSigningOut] = useState(false);
|
||||
const [showEndpoint, setShowEndpoint] = useState(false);
|
||||
const [hasLegacyLocalDb, setHasLegacyLocalDb] = useState(false);
|
||||
const [localRemainingSeconds, setLocalRemainingSeconds] = useState<number | null>(null);
|
||||
|
||||
const [
|
||||
dataSyncConfig,
|
||||
@@ -222,6 +223,33 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Sync local countdown from authProgress
|
||||
useEffect(() => {
|
||||
if (authProgress) {
|
||||
const seconds = Math.max(
|
||||
0,
|
||||
Math.ceil((authProgress.maxPollTime - authProgress.elapsed) / 1000),
|
||||
);
|
||||
setLocalRemainingSeconds(seconds);
|
||||
} else {
|
||||
setLocalRemainingSeconds(null);
|
||||
}
|
||||
}, [authProgress]);
|
||||
|
||||
// Decrement local countdown every second for smooth UI updates
|
||||
useEffect(() => {
|
||||
if (localRemainingSeconds === null || localRemainingSeconds <= 0) return;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setLocalRemainingSeconds((prev) => {
|
||||
if (prev === null || prev <= 0) return prev;
|
||||
return prev - 1;
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [localRemainingSeconds]);
|
||||
|
||||
const handleCancelAuth = async () => {
|
||||
setRemoteError(null);
|
||||
clearRemoteServerSyncError();
|
||||
@@ -264,10 +292,14 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
}
|
||||
|
||||
if (cloudLoginStatus === 'error') {
|
||||
const errorMessage = remoteError?.toLowerCase().includes('timed out')
|
||||
? t('screen5.errors.timedOut')
|
||||
: remoteError || t('authResult.failed.desc');
|
||||
|
||||
return (
|
||||
<Flexbox style={{ width: '100%' }}>
|
||||
<Flexbox gap={16} style={{ width: '100%' }}>
|
||||
<Alert
|
||||
description={remoteError || t('authResult.failed.desc')}
|
||||
description={errorMessage}
|
||||
title={t('authResult.failed.title')}
|
||||
type={'secondary'}
|
||||
/>
|
||||
@@ -288,9 +320,6 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
const phaseText = t(authorizationPhaseI18nKeyMap[authProgress?.phase ?? 'browser_opened'], {
|
||||
defaultValue: t('screen5.actions.signingIn'),
|
||||
});
|
||||
const remainingSeconds = authProgress
|
||||
? Math.max(0, Math.ceil((authProgress.maxPollTime - authProgress.elapsed) / 1000))
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Flexbox gap={8} style={{ width: '100%' }}>
|
||||
@@ -301,10 +330,10 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
{phaseText}
|
||||
</Text>
|
||||
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
||||
{remainingSeconds !== null ? (
|
||||
{localRemainingSeconds !== null ? (
|
||||
<Text style={{ color: cssVar.colorTextDescription }} type={'secondary'}>
|
||||
{t('screen5.auth.remaining', {
|
||||
time: remainingSeconds,
|
||||
time: localRemainingSeconds,
|
||||
})}
|
||||
</Text>
|
||||
) : (
|
||||
@@ -365,10 +394,14 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
}
|
||||
|
||||
if (selfhostLoginStatus === 'error') {
|
||||
const errorMessage = remoteError?.toLowerCase().includes('timed out')
|
||||
? t('screen5.errors.timedOut')
|
||||
: remoteError || t('authResult.failed.desc');
|
||||
|
||||
return (
|
||||
<Flexbox gap={16} style={{ width: '100%' }}>
|
||||
<Alert
|
||||
description={remoteError || t('authResult.failed.desc')}
|
||||
description={errorMessage}
|
||||
title={t('authResult.failed.title')}
|
||||
type={'secondary'}
|
||||
/>
|
||||
@@ -383,9 +416,6 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
const phaseText = t(authorizationPhaseI18nKeyMap[authProgress?.phase ?? 'browser_opened'], {
|
||||
defaultValue: t('screen5.actions.connecting'),
|
||||
});
|
||||
const remainingSeconds = authProgress
|
||||
? Math.max(0, Math.ceil((authProgress.maxPollTime - authProgress.elapsed) / 1000))
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Flexbox gap={8} style={{ width: '100%' }}>
|
||||
@@ -403,10 +433,10 @@ const LoginStep = memo<LoginStepProps>(({ onBack, onNext }) => {
|
||||
{phaseText}
|
||||
</Text>
|
||||
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
||||
{remainingSeconds !== null ? (
|
||||
{localRemainingSeconds !== null ? (
|
||||
<Text style={{ color: cssVar.colorTextDescription }} type={'secondary'}>
|
||||
{t('screen5.auth.remaining', {
|
||||
time: remainingSeconds,
|
||||
time: localRemainingSeconds,
|
||||
})}
|
||||
</Text>
|
||||
) : (
|
||||
|
||||
@@ -90,6 +90,7 @@ export default {
|
||||
'Sign in to sync Agents, Groups, settings, and Context across all devices.',
|
||||
'screen5.errors.desktopOnlyOidc':
|
||||
'OIDC authorization is only available in the desktop app runtime.',
|
||||
'screen5.errors.timedOut': 'Authorization timed out, please try again',
|
||||
'screen5.legacyLocalDb.link': 'Migrate legacy local database',
|
||||
'screen5.methods.cloud.description':
|
||||
'Sign in with your LobeHub Cloud account to sync everything seamlessly',
|
||||
|
||||
Reference in New Issue
Block a user