🐛 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:
Innei
2026-01-25 00:48:48 +08:00
committed by GitHub
parent c901093eda
commit c0ffd8fab3
20 changed files with 62 additions and 13 deletions

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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 lancienne 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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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 클라우드",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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",

View File

@@ -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 雲端",

View File

@@ -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>
) : (

View File

@@ -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',