feat(desktop): update failures say what happened and what to do
CI / Secret scan (gitleaks) (push) Successful in 15s
CI / Build & Quality Checks (push) Canceled after 53s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Docker image build & smoke test (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
CI / Secret scan (gitleaks) (push) Successful in 15s
CI / Build & Quality Checks (push) Canceled after 53s
CI / Trigger Desktop Build (push) Canceled after 0s
CI / Docker image build & smoke test (push) Canceled after 0s
CI / Playwright smoke (e2e) (push) Canceled after 0s
A friend's update failed ten times in a row ("Update check failed: error
sending request for url (…nsis.zip)") before the 11th went through, and
he didn't know what to do. The label was also wrong: the check had
worked; the download failed.
- Progress: "Downloading update… 28% (14.3 MB of 49.9 MB)", "The update
server didn't respond. Trying again in 3 s (attempt 2 of 4)…", from the
native `lotus-update-progress` events (cinny-desktop retries itself).
- Failures name the step (check / download / install, from the native
error prefix) in plain language, with Try again and a Download
installer button (Windows: the setup .exe; else the release page), and
the raw error under "Details".
- Installing from the update toast now shows a "Downloading update"
toast, and on failure a sticky "Update didn't install" toast that
retries on click and points at Settings → General → App Updates.
Before, the toast vanished and the failure was only visible in Settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
23649f1255
commit
568f218fe9
@@ -1,6 +1,7 @@
|
||||
import { useAtomValue, useSetAtom } from 'jotai';
|
||||
import React, { ReactNode, useCallback, useEffect, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Icons } from 'folds';
|
||||
import {
|
||||
ClientEvent,
|
||||
ClientEventHandlerMap,
|
||||
@@ -62,10 +63,11 @@ import {
|
||||
import { STATUS_EXPIRY_KEY, STATUS_MSG_KEY } from '../../features/settings/account/Profile';
|
||||
import { setPresenceWithRetry } from '../../utils/presenceWrite';
|
||||
import { useDeepLinkNavigate } from '../../hooks/useDeepLinkNavigate';
|
||||
import { toastQueueAtom } from '../../state/toast';
|
||||
import { dismissToastAtom, toastQueueAtom } from '../../state/toast';
|
||||
import { useReminders } from '../../hooks/useReminders';
|
||||
import { getRoomRetentionMs, isExpired } from '../../utils/retention';
|
||||
import { useTauriUpdater } from '../../hooks/useTauriUpdater';
|
||||
import { useTauriUpdateProgress, useTauriUpdater } from '../../hooks/useTauriUpdater';
|
||||
import { isNetworkUpdateError } from '../../utils/updateErrors';
|
||||
import { invokeTauri, isTauri as isTauriApp } from '../../hooks/useTauri';
|
||||
import { TauriDesktopFeatures } from '../../components/TauriDesktopFeatures';
|
||||
import { KeyboardShortcutsDialog, useKeyboardShortcutsTrigger } from '../../features/shortcuts';
|
||||
@@ -887,11 +889,50 @@ function RetentionSweeper() {
|
||||
const TAURI_UPDATE_CHECK_INTERVAL = 12 * 60 * 60_000; // 12 hours
|
||||
const TAURI_UPDATE_LAST_CHECK_KEY = 'lotus.tauriUpdateLastCheck';
|
||||
|
||||
const UPDATE_PROGRESS_TOAST = 'tauri-update-progress';
|
||||
const UPDATE_FAILED_TOAST = 'tauri-update-failed';
|
||||
|
||||
function TauriUpdateFeature() {
|
||||
const { isTauri, status, check, install } = useTauriUpdater();
|
||||
useTauriUpdateProgress();
|
||||
const setToast = useSetAtom(toastQueueAtom);
|
||||
const dismissToast = useSetAtom(dismissToastAtom);
|
||||
const firedRef = useRef<string | null>(null);
|
||||
|
||||
// Installing from the toast used to fail invisibly: the toast was gone and
|
||||
// the only trace was an error line in Settings. Say what is happening, and
|
||||
// on failure leave a toast that retries and points at the manual installer.
|
||||
const installFromToast = useCallback(async () => {
|
||||
dismissToast(UPDATE_FAILED_TOAST);
|
||||
setToast({
|
||||
id: UPDATE_PROGRESS_TOAST,
|
||||
iconSrc: Icons.Download,
|
||||
displayName: 'Downloading update',
|
||||
body: 'Lotus Chat will restart by itself when it’s done. You can keep chatting.',
|
||||
roomName: 'System',
|
||||
roomId: '',
|
||||
onClick: () => undefined,
|
||||
});
|
||||
const failure = await install();
|
||||
dismissToast(UPDATE_PROGRESS_TOAST);
|
||||
if (!failure) return;
|
||||
// Short on purpose; the full explanation and a Download installer button
|
||||
// are in Settings → General → App Updates.
|
||||
const busy = failure.phase !== 'install' && isNetworkUpdateError(failure.message);
|
||||
setToast({
|
||||
id: UPDATE_FAILED_TOAST,
|
||||
iconSrc: Icons.Warning,
|
||||
displayName: 'Update didn’t install',
|
||||
body: `${busy ? 'The update server seems busy. ' : ''}Click to try again, or get the installer in Settings → General → App Updates.`,
|
||||
roomName: 'System',
|
||||
roomId: '',
|
||||
sticky: true,
|
||||
onClick: () => {
|
||||
installFromToast();
|
||||
},
|
||||
});
|
||||
}, [install, setToast, dismissToast]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTauri) return;
|
||||
|
||||
@@ -917,10 +958,12 @@ function TauriUpdateFeature() {
|
||||
body: `Lotus Chat ${status.version} is ready. Click to install and restart.`,
|
||||
roomName: 'System',
|
||||
roomId: '',
|
||||
onClick: install,
|
||||
onClick: () => {
|
||||
installFromToast();
|
||||
},
|
||||
sticky: true,
|
||||
});
|
||||
}, [status, setToast, install]);
|
||||
}, [status, setToast, installFromToast]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user