diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b6fa9e75f..b3bc68d2e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -822,6 +822,9 @@ importers:
'@photo-sphere-viewer/video-plugin':
specifier: ^5.14.0
version: 5.15.1(@photo-sphere-viewer/core@5.15.1)
+ '@tanstack/svelte-query':
+ specifier: ^6.3.2
+ version: 6.3.2(svelte@5.57.2(@typescript-eslint/types@8.71.2))
'@types/geojson':
specifier: ^7946.0.16
version: 7946.0.16
@@ -4699,6 +4702,14 @@ packages:
peerDependencies:
vite: ^5.2.0 || ^6 || ^7 || ^8
+ '@tanstack/query-core@5.104.2':
+ resolution: {integrity: sha512-/qbsxJK5c3Ve1aFIULWYNcT2jeRUAiD4HME6Eu2ZdpofHoVgAjpkQhLg5xHuOoBkTPQUJLfP7zOxy0qsBcqROA==}
+
+ '@tanstack/svelte-query@6.3.2':
+ resolution: {integrity: sha512-bMPh3iyijRxqLlulDqJO80wm6mJughvVVTV4SZFMgTNSiA5AJJoOHJ3btQtYpeHgN0dMALhfo4R8chwB/9JA2Q==}
+ peerDependencies:
+ svelte: ^5.25.0
+
'@testing-library/dom@10.4.1':
resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
engines: {node: '>=18'}
@@ -17623,6 +17634,13 @@ snapshots:
tailwindcss: 4.3.3
vite: 8.3.0(@types/node@24.19.2)(esbuild@0.28.2)(jiti@2.7.0)(sass@1.102.0)(terser@5.49.0)(tsx@4.23.15)(yaml@2.9.1)
+ '@tanstack/query-core@5.104.2': {}
+
+ '@tanstack/svelte-query@6.3.2(svelte@5.57.2(@typescript-eslint/types@8.71.2))':
+ dependencies:
+ '@tanstack/query-core': 5.104.2
+ svelte: 5.57.2(@typescript-eslint/types@8.71.2)
+
'@testing-library/dom@10.4.1':
dependencies:
'@babel/code-frame': 7.29.7
diff --git a/web/package.json b/web/package.json
index 0d147c19e..a238f9ac3 100644
--- a/web/package.json
+++ b/web/package.json
@@ -36,6 +36,7 @@
"@photo-sphere-viewer/resolution-plugin": "^5.14.0",
"@photo-sphere-viewer/settings-plugin": "^5.14.0",
"@photo-sphere-viewer/video-plugin": "^5.14.0",
+ "@tanstack/svelte-query": "^6.3.2",
"@types/geojson": "^7946.0.16",
"@zoom-image/core": "^0.42.0",
"@zoom-image/svelte": "^0.3.0",
diff --git a/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte b/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte
index 999fa5537..eed418c39 100644
--- a/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte
+++ b/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte
@@ -6,11 +6,12 @@
import FormatMessage from '$lib/elements/FormatMessage.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
- import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
+ import { createDefinedQuery, executeMutation } from '$lib/queries/client';
+ import { getConfigQuery, updateConfigMutation } from '$lib/queries/system-config.query';
import StorageTemplateVariablesModal from '$lib/modals/StorageTemplateVariablesModal.svelte';
import { Route } from '$lib/route';
- import { handleSystemConfigSave } from '$lib/services/system-config.service';
import { getStorageTemplateOptions, type SystemConfigTemplateStorageOptionDto } from '@immich/sdk';
+ import { cloneDeep } from 'lodash-es';
import { Code, Heading, IconButton, Link, modalManager, Text } from '@immich/ui';
import { mdiInformationOutline } from '@mdi/js';
import handlebar from 'handlebars';
@@ -39,8 +40,9 @@
type StorageTemplateOption = (typeof StorageTemplateOption)[keyof typeof StorageTemplateOption];
const disabled = $derived(featureFlagsManager.value.configFile);
- const config = $derived(systemConfigManager.value);
- let configToEdit = $state(systemConfigManager.cloneValue());
+ const query = createDefinedQuery(getConfigQuery());
+ const config = $derived(query.data);
+ let configToEdit = $state(cloneDeep(config));
// TODO remove once we support partial overwriting with database values
if (preselectDate && !featureFlagsManager.value.configFile && !configToEdit.storageTemplate.enabled) {
@@ -50,7 +52,7 @@
let templateOptions: SystemConfigTemplateStorageOptionDto | undefined = $state();
let selectedPreset = $state('');
- let customTemplate = $state(systemConfigManager.value.storageTemplate.template);
+ let customTemplate = $state(config.storageTemplate.template);
const getTemplateOptions = async () => {
templateOptions = await getStorageTemplateOptions();
@@ -151,9 +153,9 @@
}
});
- onDestroy(async () => {
+ onDestroy(() => {
if (saveOnClose) {
- await handleSystemConfigSave({ storageTemplate: configToEdit.storageTemplate });
+ void executeMutation(updateConfigMutation(), { storageTemplate: configToEdit.storageTemplate });
}
});
diff --git a/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte b/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte
index 3948b6bbc..fb40e600c 100644
--- a/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte
+++ b/web/src/lib/components/shared-components/settings/SystemConfigButtonRow.svelte
@@ -1,9 +1,10 @@
@@ -52,6 +52,8 @@
-
+
diff --git a/web/src/lib/managers/system-config-manager.svelte.ts b/web/src/lib/managers/system-config-manager.svelte.ts
deleted file mode 100644
index e002ea148..000000000
--- a/web/src/lib/managers/system-config-manager.svelte.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { getConfig, getConfigDefaults, type AdminConfigDto } from '@immich/sdk';
-import { cloneDeep } from 'lodash-es';
-import { eventManager } from '$lib/managers/event-manager.svelte';
-
-class SystemConfigManager {
- #value?: AdminConfigDto = $state();
- #defaultValue?: AdminConfigDto = $state();
-
- constructor() {
- eventManager.on({
- SystemConfigUpdate: (config) => (this.#value = config),
- });
- }
-
- async init() {
- await this.#loadConfig();
- await this.#loadDefault();
- }
-
- get value() {
- if (!this.#value) {
- throw new Error('Server config manager must be initialized first');
- }
-
- return this.#value;
- }
-
- set value(config: AdminConfigDto) {
- this.#value = config;
- }
-
- get defaultValue() {
- if (!this.#defaultValue) {
- throw new Error('Server config manager must be initialized first');
- }
-
- return this.#defaultValue;
- }
-
- cloneValue() {
- return cloneDeep(this.value);
- }
-
- cloneDefaultValue() {
- return cloneDeep(this.defaultValue);
- }
-
- async #loadConfig() {
- this.#value = await getConfig();
- }
-
- async #loadDefault() {
- this.#defaultValue = await getConfigDefaults();
- }
-}
-
-export const systemConfigManager = new SystemConfigManager();
diff --git a/web/src/lib/queries/client.ts b/web/src/lib/queries/client.ts
new file mode 100644
index 000000000..513f05476
--- /dev/null
+++ b/web/src/lib/queries/client.ts
@@ -0,0 +1,49 @@
+import {
+ createQuery,
+ QueryClient,
+ type CreateMutationOptions,
+ type DataTag,
+ type DefaultError,
+ type DefinedCreateQueryResult,
+ type NonUndefinedGuard,
+ type QueryKey,
+ type UndefinedInitialDataOptions,
+} from '@tanstack/svelte-query';
+import { noop } from 'lodash-es';
+import { eventManager } from '$lib/managers/event-manager.svelte';
+
+const createQueryClient = () => {
+ const client = new QueryClient({
+ defaultOptions: {
+ queries: {
+ retry: false,
+ },
+ },
+ });
+
+ eventManager.on({ AuthLogout: () => client.clear() });
+
+ return client;
+};
+
+export const queryClient = createQueryClient();
+
+export const createDefinedQuery = (
+ options: UndefinedInitialDataOptions & {
+ queryKey: DataTag;
+ },
+): DefinedCreateQueryResult => {
+ const initialData = queryClient.getQueryData>(
+ options.queryKey,
+ );
+ if (initialData === undefined) {
+ throw new Error(`${options.queryKey.join('/')} must be loaded first`);
+ }
+
+ return createQuery(() => ({ ...options, initialData }));
+};
+
+export const executeMutation = (
+ options: CreateMutationOptions,
+ variables: TVariables,
+) => queryClient.getMutationCache().build(queryClient, options).execute(variables).catch(noop);
diff --git a/web/src/lib/queries/system-config.query.ts b/web/src/lib/queries/system-config.query.ts
new file mode 100644
index 000000000..fb7646570
--- /dev/null
+++ b/web/src/lib/queries/system-config.query.ts
@@ -0,0 +1,51 @@
+import { getConfig, getConfigDefaults, updateConfig, type AdminConfigDto } from '@immich/sdk';
+import { toastManager } from '@immich/ui';
+import { mutationOptions, queryOptions } from '@tanstack/svelte-query';
+import { isEqual } from 'lodash-es';
+import { eventManager } from '$lib/managers/event-manager.svelte';
+import { queryClient } from '$lib/queries/client';
+import { handleError } from '$lib/utils/handle-error';
+import { getFormatter } from '$lib/utils/i18n';
+
+export const getConfigQuery = () =>
+ queryOptions({
+ queryKey: ['system-config'],
+ queryFn: ({ signal }) => getConfig({ signal }),
+ staleTime: Infinity,
+ });
+
+export const getConfigDefaultsQuery = () =>
+ queryOptions({
+ queryKey: ['system-config', 'defaults'],
+ queryFn: ({ signal }) => getConfigDefaults({ signal }),
+ staleTime: Infinity,
+ });
+
+export const updateConfigMutation = () =>
+ mutationOptions({
+ mutationFn: async (update: Partial) => {
+ const config = await getConfig();
+ const adminConfigDto = { ...config, ...update };
+
+ if (isEqual(config, adminConfigDto)) {
+ return;
+ }
+
+ return updateConfig({ adminConfigDto });
+ },
+ onSuccess: async (config) => {
+ if (!config) {
+ return;
+ }
+
+ queryClient.setQueryData(getConfigQuery().queryKey, config);
+ eventManager.emit('SystemConfigUpdate', config);
+
+ const $t = await getFormatter();
+ toastManager.primary($t('settings_saved'));
+ },
+ onError: async (error) => {
+ const $t = await getFormatter();
+ handleError(error, $t('errors.unable_to_save_settings'));
+ },
+ });
diff --git a/web/src/lib/services/system-config.service.ts b/web/src/lib/services/system-config.service.ts
index 6fa8bf0f1..568d59575 100644
--- a/web/src/lib/services/system-config.service.ts
+++ b/web/src/lib/services/system-config.service.ts
@@ -1,12 +1,10 @@
-import { getConfig, updateConfig, type ServerFeaturesDto, type AdminConfigDto } from '@immich/sdk';
-import { toastManager, type ActionItem } from '@immich/ui';
+import type { AdminConfigDto, ServerFeaturesDto } from '@immich/sdk';
+import type { ActionItem } from '@immich/ui';
import { mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js';
-import { isEqual } from 'lodash-es';
import type { MessageFormatter } from 'svelte-i18n';
-import { eventManager } from '$lib/managers/event-manager.svelte';
+import { executeMutation } from '$lib/queries/client';
+import { updateConfigMutation } from '$lib/queries/system-config.query';
import { copyToClipboard, downloadJson } from '$lib/utils';
-import { handleError } from '$lib/utils/handle-error';
-import { getFormatter } from '$lib/utils/i18n';
export const getSystemConfigActions = (
$t: MessageFormatter,
@@ -44,26 +42,7 @@ export const getSystemConfigActions = (
return { CopyToClipboard, Download, Upload };
};
-export const handleSystemConfigSave = async (update: Partial) => {
- const $t = await getFormatter();
- const config = await getConfig();
- const adminConfigDto = { ...config, ...update };
-
- if (isEqual(config, adminConfigDto)) {
- return;
- }
-
- try {
- const newConfig = await updateConfig({ adminConfigDto });
-
- eventManager.emit('SystemConfigUpdate', newConfig);
- toastManager.primary($t('settings_saved'));
- } catch (error) {
- handleError(error, $t('errors.unable_to_save_settings'));
- }
-};
-
-export const handleUploadConfig = () => {
+const handleUploadConfig = () => {
const input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', '.json');
@@ -76,8 +55,7 @@ export const handleUploadConfig = () => {
}
const reader = async () => {
const text = await file.text();
- const newConfig = JSON.parse(text);
- await handleSystemConfigSave(newConfig);
+ await executeMutation(updateConfigMutation(), JSON.parse(text));
};
reader()
.catch((error) => console.error('Error handling JSON config upload', error))
diff --git a/web/src/lib/stores/websocket.ts b/web/src/lib/stores/websocket.ts
index 6c4ac1cfd..283038054 100644
--- a/web/src/lib/stores/websocket.ts
+++ b/web/src/lib/stores/websocket.ts
@@ -13,6 +13,8 @@ import { get, writable } from 'svelte/store';
import { page } from '$app/state';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
+import { queryClient } from '$lib/queries/client';
+import { getConfigQuery } from '$lib/queries/system-config.query';
import { Route } from '$lib/route';
import { maintenanceStore } from '$lib/stores/maintenance.store';
import { notificationManager } from '$lib/stores/notification-manager.svelte';
@@ -68,6 +70,10 @@ websocket
})
.on('disconnect', () => websocketStore.connected.set(false))
.on('on_server_version', (serverVersion) => websocketStore.serverVersion.set(serverVersion))
+ .on(
+ 'on_config_update',
+ () => void queryClient.invalidateQueries({ queryKey: getConfigQuery().queryKey, exact: true }),
+ )
.on('AppRestartV1', (mode) => websocketStore.serverRestarting.set(mode))
.on('MaintenanceStatusV1', (status) => {
maintenanceStore.status.set(status);
diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte
index f07b2774a..b72f581b7 100644
--- a/web/src/routes/+layout.svelte
+++ b/web/src/routes/+layout.svelte
@@ -12,6 +12,7 @@
import { eventManager } from '$lib/managers/event-manager.svelte';
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
import ServerRestartingModal from '$lib/modals/ServerRestartingModal.svelte';
+ import { queryClient } from '$lib/queries/client';
import { Route } from '$lib/route';
import { lang, locale } from '$lib/stores/preferences.store';
import { sidebarStore } from '$lib/stores/sidebar.svelte';
@@ -37,6 +38,7 @@
} from '@immich/ui';
import { En } from 'media-chrome/lang/en';
import { addTranslation } from 'media-chrome/utils/i18n';
+ import { QueryClientProvider } from '@tanstack/svelte-query';
import { onMount, type Snippet } from 'svelte';
import { t } from 'svelte-i18n';
import { get } from 'svelte/store';
@@ -256,30 +258,32 @@
{/if}
-
- {#if page.data.error}
-
- {:else}
- {@render children?.()}
- {/if}
+
+
+ {#if page.data.error}
+
+ {:else}
+ {@render children?.()}
+ {/if}
- {#if showNavigationLoadingBar}
-
- {/if}
+ {#if showNavigationLoadingBar}
+
+ {/if}
-
-
-
+
+
+
-
-
+
+
+
diff --git a/web/src/routes/admin/+layout.ts b/web/src/routes/admin/+layout.ts
index 64356d82a..df213963e 100644
--- a/web/src/routes/admin/+layout.ts
+++ b/web/src/routes/admin/+layout.ts
@@ -1,8 +1,6 @@
-import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
import { authenticate } from '$lib/utils/auth';
import type { LayoutLoad } from './$types';
export const load = (async ({ url }) => {
await authenticate(url, { admin: true });
- await systemConfigManager.init();
}) satisfies LayoutLoad;
diff --git a/web/src/routes/admin/system-settings/+page.svelte b/web/src/routes/admin/system-settings/+page.svelte
index fb0b14bf2..ab3b43ac4 100644
--- a/web/src/routes/admin/system-settings/+page.svelte
+++ b/web/src/routes/admin/system-settings/+page.svelte
@@ -21,7 +21,8 @@
import SettingAccordion from '$lib/components/shared-components/settings/SettingAccordion.svelte';
import SearchBar from '$lib/elements/SearchBar.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
- import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
+ import { createDefinedQuery } from '$lib/queries/client';
+ import { getConfigQuery } from '$lib/queries/system-config.query';
import { getSystemConfigActions } from '$lib/services/system-config.service';
import { Alert, CommandPaletteDefaultProvider, Container } from '@immich/ui';
import {
@@ -56,6 +57,8 @@
const { data }: Props = $props();
+ const config = createDefinedQuery(getConfigQuery());
+
const settings: Array<{
component: Component;
title: string;
@@ -208,7 +211,7 @@
);
const { CopyToClipboard, Upload, Download } = $derived(
- getSystemConfigActions($t, featureFlagsManager.value, systemConfigManager.value),
+ getSystemConfigActions($t, featureFlagsManager.value, config.data),
);
diff --git a/web/src/routes/admin/system-settings/+page.ts b/web/src/routes/admin/system-settings/+page.ts
index 38deb249c..32d7f4298 100644
--- a/web/src/routes/admin/system-settings/+page.ts
+++ b/web/src/routes/admin/system-settings/+page.ts
@@ -1,17 +1,15 @@
-import { getConfig, getConfigDefaults } from '@immich/sdk';
+import { queryClient } from '$lib/queries/client';
+import { getConfigDefaultsQuery, getConfigQuery } from '$lib/queries/system-config.query';
import { authenticate } from '$lib/utils/auth';
import { getFormatter } from '$lib/utils/i18n';
import type { PageLoad } from './$types';
export const load = (async ({ url }) => {
await authenticate(url, { admin: true });
- const config = await getConfig();
- const defaultConfig = await getConfigDefaults();
+ await Promise.all([queryClient.query(getConfigQuery()), queryClient.query(getConfigDefaultsQuery())]);
const $t = await getFormatter();
return {
- config,
- defaultConfig,
meta: {
title: $t('admin.system_settings'),
},
diff --git a/web/src/routes/admin/system-settings/AuthSettings.svelte b/web/src/routes/admin/system-settings/AuthSettings.svelte
index 2ef24d517..7fd23dc79 100644
--- a/web/src/routes/admin/system-settings/AuthSettings.svelte
+++ b/web/src/routes/admin/system-settings/AuthSettings.svelte
@@ -6,19 +6,23 @@
import { SettingInputFieldType } from '$lib/constants';
import FormatMessage from '$lib/elements/FormatMessage.svelte';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
- import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
import AuthDisableLoginConfirmModal from '$lib/modals/AuthDisableLoginConfirmModal.svelte';
+ import { createDefinedQuery } from '$lib/queries/client';
+ import { getConfigQuery } from '$lib/queries/system-config.query';
import { handleError } from '$lib/utils/handle-error';
import { OAuthTokenEndpointAuthMethod, unlinkAllOAuthAccountsAdmin } from '@immich/sdk';
import { Button, Link, modalManager, Text, toastManager } from '@immich/ui';
import { mdiRestart } from '@mdi/js';
+ import { cloneDeep } from 'lodash-es';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import SettingSelect from './SettingSelect.svelte';
+ const query = createDefinedQuery(getConfigQuery());
+ const config = $derived(query.data);
+
const disabled = $derived(featureFlagsManager.value.configFile);
- const config = $derived(systemConfigManager.value);
- let configToEdit = $state(systemConfigManager.cloneValue());
+ let configToEdit = $state(cloneDeep(config));
const handleToggleOverride = () => {
// click runs before bind
diff --git a/web/src/routes/admin/system-settings/BackupSettings.svelte b/web/src/routes/admin/system-settings/BackupSettings.svelte
index 644be2e32..4e147794a 100644
--- a/web/src/routes/admin/system-settings/BackupSettings.svelte
+++ b/web/src/routes/admin/system-settings/BackupSettings.svelte
@@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/ImageSettings.svelte b/web/src/routes/admin/system-settings/ImageSettings.svelte
index d7fd86e71..cbde1597e 100644
--- a/web/src/routes/admin/system-settings/ImageSettings.svelte
+++ b/web/src/routes/admin/system-settings/ImageSettings.svelte
@@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte b/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte
index 0a1b5eb0b..0c01cbaed 100644
--- a/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte
+++ b/web/src/routes/admin/system-settings/IntegrityChecksSettings.svelte
@@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/JobSettings.svelte b/web/src/routes/admin/system-settings/JobSettings.svelte
index b38c3c261..f0e319b2e 100644
--- a/web/src/routes/admin/system-settings/JobSettings.svelte
+++ b/web/src/routes/admin/system-settings/JobSettings.svelte
@@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/MachineLearningSettings.svelte b/web/src/routes/admin/system-settings/MachineLearningSettings.svelte
index eb4362914..74d4856c8 100644
--- a/web/src/routes/admin/system-settings/MachineLearningSettings.svelte
+++ b/web/src/routes/admin/system-settings/MachineLearningSettings.svelte
@@ -1,4 +1,6 @@
diff --git a/web/src/routes/admin/system-settings/MapSettings.svelte b/web/src/routes/admin/system-settings/MapSettings.svelte
index 07eb5292a..f987ee103 100644
--- a/web/src/routes/admin/system-settings/MapSettings.svelte
+++ b/web/src/routes/admin/system-settings/MapSettings.svelte
@@ -1,4 +1,7 @@
diff --git a/web/src/routes/admin/system-settings/MetadataSettings.svelte b/web/src/routes/admin/system-settings/MetadataSettings.svelte
index d49292694..825af6405 100644
--- a/web/src/routes/admin/system-settings/MetadataSettings.svelte
+++ b/web/src/routes/admin/system-settings/MetadataSettings.svelte
@@ -1,13 +1,17 @@
diff --git a/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte b/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte
index 653448e06..45eb82bd5 100644
--- a/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte
+++ b/web/src/routes/admin/system-settings/NewVersionCheckSettings.svelte
@@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte b/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte
index 88290a0f4..05a562ed8 100644
--- a/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte
+++ b/web/src/routes/admin/system-settings/NightlyTasksSettings.svelte
@@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/NotificationSettings.svelte b/web/src/routes/admin/system-settings/NotificationSettings.svelte
index 9de2a2d7d..cfe672ed4 100644
--- a/web/src/routes/admin/system-settings/NotificationSettings.svelte
+++ b/web/src/routes/admin/system-settings/NotificationSettings.svelte
@@ -1,4 +1,5 @@
diff --git a/web/src/routes/admin/system-settings/TemplateSettings.svelte b/web/src/routes/admin/system-settings/TemplateSettings.svelte
index bcc9cc90c..33f9b4b14 100644
--- a/web/src/routes/admin/system-settings/TemplateSettings.svelte
+++ b/web/src/routes/admin/system-settings/TemplateSettings.svelte
@@ -2,7 +2,8 @@
import SettingAccordion from '$lib/components/shared-components/settings/SettingAccordion.svelte';
import SettingTextarea from './SettingTextarea.svelte';
import FormatMessage from '$lib/elements/FormatMessage.svelte';
- import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
+ import { createDefinedQuery } from '$lib/queries/client';
+ import { getConfigQuery } from '$lib/queries/system-config.query';
import EmailTemplatePreviewModal from '$lib/modals/EmailTemplatePreviewModal.svelte';
import { handleError } from '$lib/utils/handle-error';
import { type AdminConfigDto, type AdminConfigTemplateEmailsDto, getNotificationTemplateAdmin } from '@immich/sdk';
@@ -17,6 +18,8 @@
let { config = $bindable() }: Props = $props();
+ const saved = createDefinedQuery(getConfigQuery());
+
let loadingPreview = $state(false);
const getTemplate = async (name: string, template: string) => {
@@ -53,7 +56,7 @@
];
const isEdited = (templateKey: keyof AdminConfigTemplateEmailsDto) =>
- config.templates.email[templateKey] !== systemConfigManager.value.templates.email[templateKey];
+ config.templates.email[templateKey] !== saved.data.templates.email[templateKey];
const onsubmit = (event: Event) => {
event.preventDefault();
diff --git a/web/src/routes/admin/system-settings/ThemeSettings.svelte b/web/src/routes/admin/system-settings/ThemeSettings.svelte
index 7149825d0..90a8a04bc 100644
--- a/web/src/routes/admin/system-settings/ThemeSettings.svelte
+++ b/web/src/routes/admin/system-settings/ThemeSettings.svelte
@@ -1,14 +1,18 @@
diff --git a/web/src/routes/admin/system-settings/TrashSettings.svelte b/web/src/routes/admin/system-settings/TrashSettings.svelte
index 6829d8487..e4734b005 100644
--- a/web/src/routes/admin/system-settings/TrashSettings.svelte
+++ b/web/src/routes/admin/system-settings/TrashSettings.svelte
@@ -1,16 +1,20 @@
diff --git a/web/src/routes/admin/system-settings/UserSettings.svelte b/web/src/routes/admin/system-settings/UserSettings.svelte
index 7ac33709a..f235ff1ed 100644
--- a/web/src/routes/admin/system-settings/UserSettings.svelte
+++ b/web/src/routes/admin/system-settings/UserSettings.svelte
@@ -1,16 +1,20 @@
diff --git a/web/src/routes/auth/onboarding/+page.svelte b/web/src/routes/auth/onboarding/+page.svelte
index 65e5f95b7..f41280676 100644
--- a/web/src/routes/auth/onboarding/+page.svelte
+++ b/web/src/routes/auth/onboarding/+page.svelte
@@ -12,7 +12,8 @@
import OnboardingUserPrivacy from './OnboardingUserPrivacy.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
- import { systemConfigManager } from '$lib/managers/system-config-manager.svelte';
+ import { queryClient } from '$lib/queries/client';
+ import { getConfigQuery } from '$lib/queries/system-config.query';
import { Route } from '$lib/route';
import { OnboardingRole } from '$lib/types';
import { setUserOnboarding, updateAdminOnboarding } from '@immich/sdk';
@@ -155,7 +156,7 @@
onMount(async () => {
if (userRole === OnboardingRole.SERVER) {
- await systemConfigManager.init();
+ await queryClient.query(getConfigQuery());
}
});
diff --git a/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte b/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte
index 3bae79b9a..0f10fdda1 100644
--- a/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte
+++ b/web/src/routes/auth/onboarding/OnboardingServerPrivacy.svelte
@@ -1,14 +1,19 @@