mirror of
https://github.com/immich-app/immich.git
synced 2025-05-30 19:54:52 -04:00
fix: reduce the number of API requests when changing route (#14666)
* fix: reduce the number of API requests when changing route * fix: reset `userInteraction` after sign out
This commit is contained in:
parent
6b0f9ec46c
commit
8945a5d862
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||||
import { featureFlags } from '$lib/stores/server-config.store';
|
import { featureFlags } from '$lib/stores/server-config.store';
|
||||||
import { serverInfo } from '$lib/stores/server-info.store';
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
import { ByteUnit, convertToBytes } from '$lib/utils/byte-units';
|
import { ByteUnit, convertToBytes } from '$lib/utils/byte-units';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { createUserAdmin } from '@immich/sdk';
|
import { createUserAdmin } from '@immich/sdk';
|
||||||
@ -34,7 +34,9 @@
|
|||||||
let isCreatingUser = $state(false);
|
let isCreatingUser = $state(false);
|
||||||
|
|
||||||
let quotaSizeInBytes = $derived(quotaSize ? convertToBytes(quotaSize, ByteUnit.GiB) : null);
|
let quotaSizeInBytes = $derived(quotaSize ? convertToBytes(quotaSize, ByteUnit.GiB) : null);
|
||||||
let quotaSizeWarning = $derived(quotaSizeInBytes && quotaSizeInBytes > $serverInfo.diskSizeRaw);
|
let quotaSizeWarning = $derived(
|
||||||
|
quotaSizeInBytes && userInteraction.serverInfo && quotaSizeInBytes > userInteraction.serverInfo.diskSizeRaw,
|
||||||
|
);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (password !== confirmPassword && confirmPassword.length > 0) {
|
if (password !== confirmPassword && confirmPassword.length > 0) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import { serverInfo } from '$lib/stores/server-info.store';
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { updateUserAdmin, type UserAdminResponseDto } from '@immich/sdk';
|
import { updateUserAdmin, type UserAdminResponseDto } from '@immich/sdk';
|
||||||
import { mdiAccountEditOutline } from '@mdi/js';
|
import { mdiAccountEditOutline } from '@mdi/js';
|
||||||
@ -37,7 +37,8 @@
|
|||||||
let quotaSizeWarning = $derived(
|
let quotaSizeWarning = $derived(
|
||||||
previousQutoa !== convertToBytes(Number(quotaSize), ByteUnit.GiB) &&
|
previousQutoa !== convertToBytes(Number(quotaSize), ByteUnit.GiB) &&
|
||||||
!!quotaSize &&
|
!!quotaSize &&
|
||||||
convertToBytes(Number(quotaSize), ByteUnit.GiB) > $serverInfo.diskSizeRaw,
|
userInteraction.serverInfo &&
|
||||||
|
convertToBytes(Number(quotaSize), ByteUnit.GiB) > userInteraction.serverInfo.diskSizeRaw,
|
||||||
);
|
);
|
||||||
|
|
||||||
const editUser = async () => {
|
const editUser = async () => {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { featureFlags } from '$lib/stores/server-config.store';
|
import { featureFlags } from '$lib/stores/server-config.store';
|
||||||
import { user } from '$lib/stores/user.store';
|
import { user } from '$lib/stores/user.store';
|
||||||
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
import { handleLogout } from '$lib/utils/auth';
|
import { handleLogout } from '$lib/utils/auth';
|
||||||
import { getAboutInfo, logout, type ServerAboutResponseDto } from '@immich/sdk';
|
import { getAboutInfo, logout, type ServerAboutResponseDto } from '@immich/sdk';
|
||||||
import { mdiHelpCircleOutline, mdiMagnify, mdiTrayArrowUp } from '@mdi/js';
|
import { mdiHelpCircleOutline, mdiMagnify, mdiTrayArrowUp } from '@mdi/js';
|
||||||
@ -38,17 +39,17 @@
|
|||||||
await handleLogout(redirectUri);
|
await handleLogout(redirectUri);
|
||||||
};
|
};
|
||||||
|
|
||||||
let aboutInfo: ServerAboutResponseDto | undefined = $state();
|
let info: ServerAboutResponseDto | undefined = $state();
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
aboutInfo = await getAboutInfo();
|
info = userInteraction.aboutInfo ?? (await getAboutInfo());
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:window bind:innerWidth />
|
<svelte:window bind:innerWidth />
|
||||||
|
|
||||||
{#if shouldShowHelpPanel && aboutInfo}
|
{#if shouldShowHelpPanel && info}
|
||||||
<HelpAndFeedbackModal onClose={() => (shouldShowHelpPanel = false)} info={aboutInfo} />
|
<HelpAndFeedbackModal onClose={() => (shouldShowHelpPanel = false)} {info} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<section id="dashboard-navbar" class="fixed z-[900] h-[var(--navbar-height)] w-screen text-sm">
|
<section id="dashboard-navbar" class="fixed z-[900] h-[var(--navbar-height)] w-screen text-sm">
|
||||||
|
@ -4,13 +4,19 @@
|
|||||||
import { getAllAlbums, type AlbumResponseDto } from '@immich/sdk';
|
import { getAllAlbums, type AlbumResponseDto } from '@immich/sdk';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
|
|
||||||
let albums: AlbumResponseDto[] = $state([]);
|
let albums: AlbumResponseDto[] = $state([]);
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
if (userInteraction.recentAlbums) {
|
||||||
|
albums = userInteraction.recentAlbums;
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const allAlbums = await getAllAlbums({});
|
const allAlbums = await getAllAlbums({});
|
||||||
albums = allAlbums.sort((a, b) => (a.updatedAt > b.updatedAt ? -1 : 1)).slice(0, 3);
|
albums = allAlbums.sort((a, b) => (a.updatedAt > b.updatedAt ? -1 : 1)).slice(0, 3);
|
||||||
|
userInteraction.recentAlbums = albums;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, $t('failed_to_load_assets'));
|
handleError(error, $t('failed_to_load_assets'));
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,24 @@
|
|||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { mdiAlert } from '@mdi/js';
|
import { mdiAlert } from '@mdi/js';
|
||||||
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
|
|
||||||
const { serverVersion, connected } = websocketStore;
|
const { serverVersion, connected } = websocketStore;
|
||||||
|
|
||||||
let isOpen = $state(false);
|
let isOpen = $state(false);
|
||||||
|
|
||||||
let info: ServerAboutResponseDto | undefined = $state();
|
let info: ServerAboutResponseDto | undefined = $state();
|
||||||
let versions: ServerVersionHistoryResponseDto[] = $state([]);
|
let versions: ServerVersionHistoryResponseDto[] = $state([]);
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
if (userInteraction.aboutInfo && userInteraction.versions && $serverVersion) {
|
||||||
|
info = userInteraction.aboutInfo;
|
||||||
|
versions = userInteraction.versions;
|
||||||
|
return;
|
||||||
|
}
|
||||||
await requestServerInfo();
|
await requestServerInfo();
|
||||||
[info, versions] = await Promise.all([getAboutInfo(), getVersionHistory()]);
|
[info, versions] = await Promise.all([getAboutInfo(), getVersionHistory()]);
|
||||||
|
userInteraction.aboutInfo = info;
|
||||||
|
userInteraction.versions = versions;
|
||||||
});
|
});
|
||||||
let isMain = $derived(info?.sourceRef === 'main' && info.repository === 'immich-app/immich');
|
let isMain = $derived(info?.sourceRef === 'main' && info.repository === 'immich-app/immich');
|
||||||
let version = $derived(
|
let version = $derived(
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { locale } from '$lib/stores/preferences.store';
|
import { locale } from '$lib/stores/preferences.store';
|
||||||
import { serverInfo } from '$lib/stores/server-info.store';
|
|
||||||
import { user } from '$lib/stores/user.store';
|
import { user } from '$lib/stores/user.store';
|
||||||
import { requestServerInfo } from '$lib/utils/auth';
|
import { requestServerInfo } from '$lib/utils/auth';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { getByteUnitString } from '../../../utils/byte-units';
|
import { getByteUnitString } from '$lib/utils/byte-units';
|
||||||
import LoadingSpinner from '../loading-spinner.svelte';
|
import LoadingSpinner from '../loading-spinner.svelte';
|
||||||
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
|
|
||||||
let usageClasses = $state('');
|
let usageClasses = $state('');
|
||||||
|
|
||||||
let hasQuota = $derived($user?.quotaSizeInBytes !== null);
|
let hasQuota = $derived($user?.quotaSizeInBytes !== null);
|
||||||
let availableBytes = $derived((hasQuota ? $user?.quotaSizeInBytes : $serverInfo?.diskSizeRaw) || 0);
|
let availableBytes = $derived((hasQuota ? $user?.quotaSizeInBytes : userInteraction.serverInfo?.diskSizeRaw) || 0);
|
||||||
let usedBytes = $derived((hasQuota ? $user?.quotaUsageInBytes : $serverInfo?.diskUseRaw) || 0);
|
let usedBytes = $derived((hasQuota ? $user?.quotaUsageInBytes : userInteraction.serverInfo?.diskUseRaw) || 0);
|
||||||
let usedPercentage = $derived(Math.min(Math.round((usedBytes / availableBytes) * 100), 100));
|
let usedPercentage = $derived(Math.min(Math.round((usedBytes / availableBytes) * 100), 100));
|
||||||
|
|
||||||
const onUpdate = () => {
|
const onUpdate = () => {
|
||||||
@ -38,6 +38,9 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
if (userInteraction.serverInfo && $user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await requestServerInfo();
|
await requestServerInfo();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -54,7 +57,7 @@
|
|||||||
<div class="hidden group-hover:sm:block md:block">
|
<div class="hidden group-hover:sm:block md:block">
|
||||||
<p class="font-medium text-immich-dark-gray dark:text-white mb-2">{$t('storage')}</p>
|
<p class="font-medium text-immich-dark-gray dark:text-white mb-2">{$t('storage')}</p>
|
||||||
|
|
||||||
{#if $serverInfo}
|
{#if userInteraction.serverInfo}
|
||||||
<p class="text-gray-500 dark:text-gray-300">
|
<p class="text-gray-500 dark:text-gray-300">
|
||||||
{$t('storage_usage', {
|
{$t('storage_usage', {
|
||||||
values: {
|
values: {
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
import type { ServerStorageResponseDto } from '@immich/sdk';
|
|
||||||
import { writable } from 'svelte/store';
|
|
||||||
|
|
||||||
export const serverInfo = writable<ServerStorageResponseDto>();
|
|
26
web/src/lib/stores/user.svelte.ts
Normal file
26
web/src/lib/stores/user.svelte.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import type {
|
||||||
|
AlbumResponseDto,
|
||||||
|
ServerAboutResponseDto,
|
||||||
|
ServerStorageResponseDto,
|
||||||
|
ServerVersionHistoryResponseDto,
|
||||||
|
} from '@immich/sdk';
|
||||||
|
|
||||||
|
interface UserInteractions {
|
||||||
|
recentAlbums?: AlbumResponseDto[];
|
||||||
|
versions?: ServerVersionHistoryResponseDto[];
|
||||||
|
aboutInfo?: ServerAboutResponseDto;
|
||||||
|
serverInfo?: ServerStorageResponseDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultUserInteraction: UserInteractions = {
|
||||||
|
recentAlbums: undefined,
|
||||||
|
versions: undefined,
|
||||||
|
aboutInfo: undefined,
|
||||||
|
serverInfo: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const resetUserInteraction = () => {
|
||||||
|
Object.assign(userInteraction, defaultUserInteraction);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const userInteraction = $state<UserInteractions>(defaultUserInteraction);
|
@ -2,8 +2,8 @@ import { browser } from '$app/environment';
|
|||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { foldersStore } from '$lib/stores/folders.svelte';
|
import { foldersStore } from '$lib/stores/folders.svelte';
|
||||||
import { purchaseStore } from '$lib/stores/purchase.store';
|
import { purchaseStore } from '$lib/stores/purchase.store';
|
||||||
import { serverInfo } from '$lib/stores/server-info.store';
|
|
||||||
import { preferences as preferences$, resetSavedUser, user as user$ } from '$lib/stores/user.store';
|
import { preferences as preferences$, resetSavedUser, user as user$ } from '$lib/stores/user.store';
|
||||||
|
import { resetUserInteraction, userInteraction } from '$lib/stores/user.svelte';
|
||||||
import { getAboutInfo, getMyPreferences, getMyUser, getStorage } from '@immich/sdk';
|
import { getAboutInfo, getMyPreferences, getMyUser, getStorage } from '@immich/sdk';
|
||||||
import { redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
@ -72,7 +72,7 @@ export const authenticate = async (options?: AuthOptions) => {
|
|||||||
export const requestServerInfo = async () => {
|
export const requestServerInfo = async () => {
|
||||||
if (get(user$)) {
|
if (get(user$)) {
|
||||||
const data = await getStorage();
|
const data = await getStorage();
|
||||||
serverInfo.set(data);
|
userInteraction.serverInfo = data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,6 +99,7 @@ export const handleLogout = async (redirectUri: string) => {
|
|||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
resetSavedUser();
|
resetSavedUser();
|
||||||
|
resetUserInteraction();
|
||||||
foldersStore.clearCache();
|
foldersStore.clearCache();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user