mirror of
https://github.com/immich-app/immich.git
synced 2025-12-12 15:50:43 -08:00
feat: show update version info (#23698)
* feat: show update version info * Apply suggestions from code review Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> --------- Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
This commit is contained in:
@@ -1414,6 +1414,7 @@
|
|||||||
"new_pin_code": "New PIN code",
|
"new_pin_code": "New PIN code",
|
||||||
"new_pin_code_subtitle": "This is your first time accessing the locked folder. Create a PIN code to securely access this page",
|
"new_pin_code_subtitle": "This is your first time accessing the locked folder. Create a PIN code to securely access this page",
|
||||||
"new_timeline": "New Timeline",
|
"new_timeline": "New Timeline",
|
||||||
|
"new_update": "New update",
|
||||||
"new_user_created": "New user created",
|
"new_user_created": "New user created",
|
||||||
"new_version_available": "NEW VERSION AVAILABLE",
|
"new_version_available": "NEW VERSION AVAILABLE",
|
||||||
"newest_first": "Newest first",
|
"newest_first": "Newest first",
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ServerAboutModal from '$lib/modals/ServerAboutModal.svelte';
|
import ServerAboutModal from '$lib/modals/ServerAboutModal.svelte';
|
||||||
|
import { user } from '$lib/stores/user.store';
|
||||||
import { userInteraction } from '$lib/stores/user.svelte';
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
import { websocketStore } from '$lib/stores/websocket';
|
import { websocketStore } from '$lib/stores/websocket';
|
||||||
|
import { semverToName } from '$lib/utils';
|
||||||
import { requestServerInfo } from '$lib/utils/auth';
|
import { requestServerInfo } from '$lib/utils/auth';
|
||||||
import {
|
import {
|
||||||
getAboutInfo,
|
getAboutInfo,
|
||||||
@@ -9,12 +11,12 @@
|
|||||||
type ServerAboutResponseDto,
|
type ServerAboutResponseDto,
|
||||||
type ServerVersionHistoryResponseDto,
|
type ServerVersionHistoryResponseDto,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { Icon, modalManager } from '@immich/ui';
|
import { Icon, modalManager, Text } from '@immich/ui';
|
||||||
import { mdiAlert } from '@mdi/js';
|
import { mdiAlert, mdiNewBox } from '@mdi/js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
const { serverVersion, connected } = websocketStore;
|
const { serverVersion, connected, release } = websocketStore;
|
||||||
|
|
||||||
let info: ServerAboutResponseDto | undefined = $state();
|
let info: ServerAboutResponseDto | undefined = $state();
|
||||||
let versions: ServerVersionHistoryResponseDto[] = $state([]);
|
let versions: ServerVersionHistoryResponseDto[] = $state([]);
|
||||||
@@ -34,6 +36,21 @@
|
|||||||
let version = $derived(
|
let version = $derived(
|
||||||
$serverVersion ? `v${$serverVersion.major}.${$serverVersion.minor}.${$serverVersion.patch}` : null,
|
$serverVersion ? `v${$serverVersion.major}.${$serverVersion.minor}.${$serverVersion.patch}` : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const releaseInfo = $derived.by(() => {
|
||||||
|
if ($release == undefined || $release?.isAvailable || !$user.isAdmin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const availableVersion = semverToName($release.releaseVersion);
|
||||||
|
const serverVersion = semverToName($release.serverVersion);
|
||||||
|
|
||||||
|
if (serverVersion === availableVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { availableVersion, releaseUrl: `https://github.com/immich-app/immich/releases/tag/${availableVersion}` };
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -56,7 +73,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onclick={() => info && modalManager.show(ServerAboutModal, { versions, info })}
|
onclick={() => info && modalManager.show(ServerAboutModal, { versions, info })}
|
||||||
class="dark:text-immich-gray flex gap-1"
|
class="dark:text-immich-gray flex gap-1 place-items-center place-content-center"
|
||||||
>
|
>
|
||||||
{#if isMain}
|
{#if isMain}
|
||||||
<Icon icon={mdiAlert} size="1.5em" color="#ffcc4d" /> {info?.sourceRef}
|
<Icon icon={mdiAlert} size="1.5em" color="#ffcc4d" /> {info?.sourceRef}
|
||||||
@@ -69,3 +86,26 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{#if releaseInfo}
|
||||||
|
<a
|
||||||
|
href={releaseInfo.releaseUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="mt-3 p-2.5 ms-4 rounded-lg text-sm min-w-52 border border-gray-200/50 dark:border-gray-700/50 bg-white/50 dark:bg-gray-800/50 hover:border-immich-primary/40 dark:hover:border-immich-dark-primary/40 hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/5 transition-all duration-200 group block"
|
||||||
|
>
|
||||||
|
<div class="flex items-center justify-between gap-2">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Icon icon={mdiNewBox} size="16" class="text-immich-primary dark:text-immich-dark-primary opacity-80" />
|
||||||
|
<Text size="tiny" class="font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
{releaseInfo.availableVersion}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="text-[11px] text-gray-500 dark:text-gray-400 group-hover:text-immich-primary dark:group-hover:text-immich-dark-primary transition-colors opacity-70 group-hover:opacity-100"
|
||||||
|
>
|
||||||
|
{$t('new_update')}!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
|
|||||||
@@ -400,3 +400,5 @@ export const getReleaseType = (
|
|||||||
|
|
||||||
return 'none';
|
return 'none';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const semverToName = ({ major, minor, patch }: ServerVersionResponseDto) => `v${major}.${minor}.${patch}`;
|
||||||
|
|||||||
@@ -17,9 +17,8 @@
|
|||||||
websocketStore,
|
websocketStore,
|
||||||
type ReleaseEvent,
|
type ReleaseEvent,
|
||||||
} from '$lib/stores/websocket';
|
} from '$lib/stores/websocket';
|
||||||
import { copyToClipboard, getReleaseType } from '$lib/utils';
|
import { copyToClipboard, getReleaseType, semverToName } from '$lib/utils';
|
||||||
import { isAssetViewerRoute } from '$lib/utils/navigation';
|
import { isAssetViewerRoute } from '$lib/utils/navigation';
|
||||||
import type { ServerVersionResponseDto } from '@immich/sdk';
|
|
||||||
import { modalManager, setTranslations } from '@immich/ui';
|
import { modalManager, setTranslations } from '@immich/ui';
|
||||||
import { onMount, type Snippet } from 'svelte';
|
import { onMount, type Snippet } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
@@ -78,7 +77,6 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const semverToName = ({ major, minor, patch }: ServerVersionResponseDto) => `v${major}.${minor}.${patch}`;
|
|
||||||
const { release } = websocketStore;
|
const { release } = websocketStore;
|
||||||
|
|
||||||
const handleRelease = async (release?: ReleaseEvent) => {
|
const handleRelease = async (release?: ReleaseEvent) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user