diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fa44d10..5b88b3e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed - (**Category**) Prevent creating categories without a name +- (**WebUI Update**) Do not require a forced page refresh when an update has been detected in case the app just got opened ### Fixed - (**General**) Fix tooltips sometimes causing a layout shift diff --git a/src/features/app-updates/components/WebUIUpdateChecker.tsx b/src/features/app-updates/components/WebUIUpdateChecker.tsx index 31f0650b..07f7bf15 100644 --- a/src/features/app-updates/components/WebUIUpdateChecker.tsx +++ b/src/features/app-updates/components/WebUIUpdateChecker.tsx @@ -14,23 +14,27 @@ import DialogContent from '@mui/material/DialogContent'; import DialogContentText from '@mui/material/DialogContentText'; import DialogActions from '@mui/material/DialogActions'; import Button from '@mui/material/Button'; +import { d } from 'koration'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { UpdateState, WebUiChannel, WebUiUpdateStatus } from '@/lib/graphql/generated/graphql.ts'; -import { useLocalStorage } from '@/base/hooks/useStorage.tsx'; +import { useLocalStorage, useSessionStorage } from '@/base/hooks/useStorage.tsx'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { makeToast } from '@/base/utils/Toast.ts'; import { ABOUT_WEBUI, WEBUI_UPDATE_CHECK } from '@/lib/graphql/fragments/InfoFragments.ts'; import { VersionUpdateInfoDialog } from '@/features/app-updates/components/VersionUpdateInfoDialog.tsx'; import { useUpdateChecker } from '@/features/app-updates/hooks/useUpdateChecker.tsx'; import { useMetadataServerSettings } from '@/features/settings/services/ServerSettingsMetadata.ts'; -import { getErrorMessage } from '@/lib/HelperFunctions.ts'; +import { getErrorMessage, noOp } from '@/lib/HelperFunctions.ts'; const disabledUpdateCheck = () => Promise.resolve(); +const FORCED_REFRESH_THRESHOLD = d(30).seconds.inWholeMilliseconds; + export const WebUIUpdateChecker = () => { const { t } = useTranslation(); const [webUIVersion, setWebUIVersion] = useLocalStorage('webUIVersion'); + const [initialLoadTimestamp, setInitialLoadTimestamp] = useSessionStorage('webUIInitialLoadTimestamp'); const [open, setOpen] = useState(false); const { @@ -70,6 +74,15 @@ export const WebUIUpdateChecker = () => { const newVersion = aboutWebUI?.tag; const isSameAsCurrent = !newVersion || !webUIVersion || webUIVersion === newVersion; + // Store initial load timestamp (once per session) + if (!initialLoadTimestamp) { + setInitialLoadTimestamp(Date.now()); + } + + // Calculate if forced refresh threshold has been met + const timeSinceLoad = Date.now() - (initialLoadTimestamp ?? Date.now()); + const shouldForceRefresh = timeSinceLoad >= FORCED_REFRESH_THRESHOLD; + const saveInitialVersion = !webUIVersion && !!newVersion; if (saveInitialVersion) { setWebUIVersion(newVersion); @@ -160,7 +173,7 @@ export const WebUIUpdateChecker = () => { } return ( - + setOpen(false) : noOp}> {t('settings.about.webui.label.updated')} @@ -179,11 +192,14 @@ export const WebUIUpdateChecker = () => { onClick={() => { setWebUIVersion(newVersion); setOpen(false); - window.location.reload(); + + if (shouldForceRefresh) { + window.location.reload(); + } }} variant="contained" > - {t('global.button.refresh')} + {t(shouldForceRefresh ? 'global.button.refresh' : 'global.button.ok')}