mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix(settings): show latest update feedback
This commit is contained in:
+31
@@ -92,6 +92,7 @@ describe('InterfaceSettings', () => {
|
||||
useFeedViewSettingsStore.getState().setEnableInfiniteScroll(false);
|
||||
useAppUpdateStore.setState({
|
||||
availableUpdate: null,
|
||||
appUpdateCheckStatus: 'idle',
|
||||
isApplyingUpdate: false,
|
||||
isCheckingForUpdate: false,
|
||||
applyAppUpdate: testState.applyAppUpdateMock,
|
||||
@@ -106,6 +107,8 @@ describe('InterfaceSettings', () => {
|
||||
|
||||
afterEach(() => {
|
||||
act(() => root.unmount());
|
||||
useAppUpdateStore.getState().clearAppUpdateCheckStatus();
|
||||
vi.useRealTimers();
|
||||
container.remove();
|
||||
setItemSpy.mockRestore();
|
||||
vi.unstubAllGlobals();
|
||||
@@ -230,6 +233,7 @@ describe('InterfaceSettings', () => {
|
||||
});
|
||||
|
||||
it('checks for app updates when the check button is pressed', async () => {
|
||||
testState.refreshAvailableUpdateMock.mockResolvedValueOnce(null);
|
||||
render(createElement(InterfaceSettings));
|
||||
await settleLazyImports();
|
||||
|
||||
@@ -245,6 +249,33 @@ describe('InterfaceSettings', () => {
|
||||
expect(testState.applyAppUpdateMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows then clears the latest-version status when no app update is available', async () => {
|
||||
vi.useFakeTimers();
|
||||
testState.refreshAvailableUpdateMock.mockResolvedValueOnce(null);
|
||||
render(createElement(InterfaceSettings));
|
||||
await settleLazyImports();
|
||||
|
||||
const button = findButtonByText('Check');
|
||||
expect(button).toBeTruthy();
|
||||
|
||||
await act(async () => {
|
||||
button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(container.textContent).toContain('app_is_up_to_date');
|
||||
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(3999);
|
||||
});
|
||||
expect(container.textContent).toContain('app_is_up_to_date');
|
||||
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(1);
|
||||
});
|
||||
expect(container.textContent).not.toContain('app_is_up_to_date');
|
||||
});
|
||||
|
||||
it('applies the available app update when the button is pressed', async () => {
|
||||
useAppUpdateStore.setState({
|
||||
availableUpdate: {
|
||||
|
||||
@@ -8,8 +8,10 @@ const UpdateButton = () => {
|
||||
const availableUpdate = useAppUpdateStore((state) => state.availableUpdate);
|
||||
const isApplyingUpdate = useAppUpdateStore((state) => state.isApplyingUpdate);
|
||||
const isCheckingForUpdate = useAppUpdateStore((state) => state.isCheckingForUpdate);
|
||||
const appUpdateCheckStatus = useAppUpdateStore((state) => state.appUpdateCheckStatus);
|
||||
const applyAppUpdate = useAppUpdateStore((state) => state.applyAppUpdate);
|
||||
const refreshAvailableUpdate = useAppUpdateStore((state) => state.refreshAvailableUpdate);
|
||||
const showAppUpdateUpToDateStatus = useAppUpdateStore((state) => state.showAppUpdateUpToDateStatus);
|
||||
|
||||
const handleUpdateAction = async () => {
|
||||
try {
|
||||
@@ -18,13 +20,17 @@ const UpdateButton = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
await refreshAvailableUpdate();
|
||||
const update = await refreshAvailableUpdate();
|
||||
if (!update) {
|
||||
showAppUpdateUpToDateStatus();
|
||||
}
|
||||
} catch (error) {
|
||||
alert(String(error));
|
||||
}
|
||||
};
|
||||
const buttonLabel = availableUpdate ? t('download') : t('check');
|
||||
const isBusy = isApplyingUpdate || isCheckingForUpdate;
|
||||
const shouldShowUpToDateStatus = !isCheckingForUpdate && !availableUpdate && appUpdateCheckStatus === 'upToDate';
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -36,6 +42,11 @@ const UpdateButton = () => {
|
||||
{t('checking_for_updates')}
|
||||
</span>
|
||||
)}
|
||||
{shouldShowUpToDateStatus && (
|
||||
<span className={styles.updateStatus} aria-live='polite'>
|
||||
{t('app_is_up_to_date')}
|
||||
</span>
|
||||
)}
|
||||
{!isCheckingForUpdate && availableUpdate && (
|
||||
<span className={styles.updateStatus} aria-live='polite'>
|
||||
{t('new_version_found')}:
|
||||
|
||||
@@ -1,19 +1,50 @@
|
||||
import { create } from 'zustand';
|
||||
import { applyAvailableAppUpdate, resolveAvailableAppUpdate, type AvailableAppUpdate } from '../lib/app-update';
|
||||
|
||||
type AppUpdateCheckStatus = 'idle' | 'upToDate';
|
||||
|
||||
interface AppUpdateState {
|
||||
availableUpdate: AvailableAppUpdate | null;
|
||||
appUpdateCheckStatus: AppUpdateCheckStatus;
|
||||
isApplyingUpdate: boolean;
|
||||
isCheckingForUpdate: boolean;
|
||||
clearAppUpdateCheckStatus: () => void;
|
||||
showAppUpdateUpToDateStatus: () => void;
|
||||
refreshAvailableUpdate: () => Promise<AvailableAppUpdate | null>;
|
||||
applyAppUpdate: () => Promise<void>;
|
||||
}
|
||||
|
||||
const UP_TO_DATE_STATUS_TIMEOUT_MS = 4000;
|
||||
|
||||
let appUpdateCheckStatusTimeout: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
const clearAppUpdateCheckStatusTimeout = () => {
|
||||
if (appUpdateCheckStatusTimeout !== null) {
|
||||
clearTimeout(appUpdateCheckStatusTimeout);
|
||||
appUpdateCheckStatusTimeout = null;
|
||||
}
|
||||
};
|
||||
|
||||
const scheduleAppUpdateCheckStatusClear = (clearStatus: () => void) => {
|
||||
clearAppUpdateCheckStatusTimeout();
|
||||
appUpdateCheckStatusTimeout = setTimeout(clearStatus, UP_TO_DATE_STATUS_TIMEOUT_MS);
|
||||
};
|
||||
|
||||
const useAppUpdateStore = create<AppUpdateState>((set, get) => ({
|
||||
availableUpdate: null,
|
||||
appUpdateCheckStatus: 'idle',
|
||||
isApplyingUpdate: false,
|
||||
isCheckingForUpdate: false,
|
||||
clearAppUpdateCheckStatus: () => {
|
||||
clearAppUpdateCheckStatusTimeout();
|
||||
set({ appUpdateCheckStatus: 'idle' });
|
||||
},
|
||||
showAppUpdateUpToDateStatus: () => {
|
||||
set({ appUpdateCheckStatus: 'upToDate' });
|
||||
scheduleAppUpdateCheckStatusClear(get().clearAppUpdateCheckStatus);
|
||||
},
|
||||
refreshAvailableUpdate: async () => {
|
||||
get().clearAppUpdateCheckStatus();
|
||||
set({ isCheckingForUpdate: true });
|
||||
try {
|
||||
const availableUpdate = await resolveAvailableAppUpdate();
|
||||
|
||||
Reference in New Issue
Block a user