feat: sveltekit 3 (#32737)

(cherry picked from commit 2576ee28cfb790e99ddf401a129e1d9a18713121)
This commit is contained in:
Daniel Dietzler
2026-10-27 23:11:06 +03:00
committed by Codex
parent 621504fcda
commit e5b4dd1041
619 changed files with 2898 additions and 2883 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ test.describe('Shared Links', () => {
test('show error for invalid shared link', async ({ page }) => {
await page.goto('/share/invalid');
await page.getByRole('heading', { name: 'Invalid share key' }).waitFor();
await page.getByRole('heading', { name: 'Page not found' }).waitFor();
});
test('auth on navigation from shared link to timeline', async ({ context, page }) => {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"importOrder": ["<THIRD_PARTY_MODULES>", "<BUILTIN_MODULES>", "^\\$(.*)$", "^@test-data(.*)$", "^[./]"],
"importOrder": ["<THIRD_PARTY_MODULES>", "<BUILTIN_MODULES>", "^\\$(.*)$", "^#test-data(.*)$", "^[./]"],
"importOrderSeparation": false,
"jsonRecursiveSort": true,
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }],
+2 -1
View File
@@ -53,7 +53,7 @@ export default defineConfig(
tsconfigRootDir: import.meta.dirname,
},
},
// ignores: ['**/service-worker/**'],
ignores: ['**/service-worker/**'],
},
{
ignores: [
@@ -74,6 +74,7 @@ export default defineConfig(
'tailwind.config.js',
'coverage',
'vite.config.ts',
'**/service-worker/**',
],
},
typescriptEslint.configs.recommended,
+13 -5
View File
@@ -3,6 +3,14 @@
"version": "3.3.5",
"license": "GNU Affero General Public License version 3",
"type": "module",
"imports": {
"#lib": "./src/lib/index.js",
"#lib/*": "./src/lib/*",
"#tests": "./src/../tests",
"#tests/*": "./src/../tests/*",
"#i18n/*": "../i18n/*",
"#test-data/*": "./src/test-data/*"
},
"scripts": {
"dev": "vite dev --host 0.0.0.0 --port 3000",
"build": "vite build",
@@ -78,9 +86,9 @@
"@faker-js/faker": "^10.0.0",
"@koddsson/eslint-plugin-tscompat": "^0.2.0",
"@socket.io/component-emitter": "^3.1.0",
"@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/adapter-static": "^4.0.0",
"@sveltejs/enhanced-img": "^0.11.0",
"@sveltejs/kit": "^2.56.1",
"@sveltejs/kit": "^3.0.0",
"@sveltejs/vite-plugin-svelte": "7.3.1",
"@tailwindcss/vite": "^4.2.4",
"@testing-library/jest-dom": "^7.0.0",
@@ -110,13 +118,13 @@
"prettier-plugin-sort-json": "^4.1.1",
"prettier-plugin-svelte": "^4.0.0",
"rollup-plugin-visualizer": "^7.0.0",
"svelte": "5.57.1",
"svelte-check": "^4.4.6",
"svelte": "5.57.2",
"svelte-check": "^4.7.5",
"svelte-eslint-parser": "^1.8.1",
"tailwindcss": "^4.2.4",
"typescript": "npm:@typescript/typescript6@^6.0.2",
"typescript-eslint": "8.71.2",
"vite": "^8.0.0",
"vite": "^8.0.12",
"vitest": "^5.0.0"
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
import type en from '#i18n/en.json';
import 'svelte-i18n';
import type en from '$i18n/en.json';
/// <reference types="@sveltejs/kit" />
@@ -34,7 +34,7 @@ type NestedKeys<T, K = keyof T> = K extends keyof T & string
: never;
declare module 'svelte-i18n' {
import type { InterpolationValues } from '$lib/elements/format-message';
import type { InterpolationValues } from '#lib/elements/format-message.js';
import type { Readable } from 'svelte/store';
type Translations = NestedKeys<typeof en>;
+6
View File
@@ -0,0 +1,6 @@
import { defineEnvVars } from '@sveltejs/kit/env';
export const variables = defineEnvVars({
PUBLIC_IMMICH_BUY_HOST: { public: true, static: true },
PUBLIC_IMMICH_PAY_HOST: { public: true, static: true },
});
+10 -6
View File
@@ -1,5 +1,5 @@
import { isHttpError, type ApiHttpError } from '@immich/sdk';
import type { HandleClientError } from '@sveltejs/kit';
import type { HandleClientError } from '@sveltejs/kit/hooks';
const DEFAULT_MESSAGE = 'Hmm, not sure about that. Check the logs or open a ticket?';
@@ -19,19 +19,23 @@ const parseHTTPError = (httpError: ApiHttpError) => {
};
};
const parseError = (error: unknown, status: number, message: string) => {
const parseError = (error: App.Error | { status: number; message: string }) => {
if (isHttpError(error)) {
return parseHTTPError(error);
}
return {
message: (error as Error)?.message || message || DEFAULT_MESSAGE,
code: status,
message: error.message || DEFAULT_MESSAGE,
code: error.status,
};
};
export const handleError: HandleClientError = ({ error, status, message }) => {
const result = parseError(error, status, message);
export const handleError: HandleClientError = ({ kind, error }) => {
if (kind === 'unknown') {
console.error(error);
return;
}
const result = parseError(error);
console.error(`[hooks.client.ts]:handleError ${result.message}`, error);
return result;
};
+3 -3
View File
@@ -1,6 +1,6 @@
import type { Handle } from '@sveltejs/kit';
import GoogleSans from '$lib/assets/fonts/GoogleSans/GoogleSans.ttf?url';
import GoogleSansCode from '$lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf?url';
import GoogleSans from '#lib/assets/fonts/GoogleSans/GoogleSans.ttf?url';
import GoogleSansCode from '#lib/assets/fonts/GoogleSansCode/GoogleSansCode.ttf?url';
import type { Handle } from '@sveltejs/kit/hooks';
// only used during the build to replace the variables from app.html
export const handle = (async ({ event, resolve }) => {
@@ -1,8 +1,8 @@
import FocusTrapTest from '#lib/actions/__test__/FocusTrapTest.svelte';
import { setDefaultTabbleOptions } from '#lib/utils/focus-util.js';
import { render, screen } from '@testing-library/svelte';
import userEvent from '@testing-library/user-event';
import { tick } from 'svelte';
import FocusTrapTest from '$lib/actions/__test__/FocusTrapTest.svelte';
import { setDefaultTabbleOptions } from '$lib/utils/focus-util';
setDefaultTabbleOptions({ displayCheck: 'none' });
@@ -1,5 +1,5 @@
<script lang="ts">
import { focusTrap } from '$lib/actions/focus-trap';
import { focusTrap } from '#lib/actions/focus-trap.js';
interface Props {
show: boolean;
+1 -1
View File
@@ -1,5 +1,5 @@
import { matchesShortcut } from '#lib/actions/shortcut.js';
import type { ActionReturn } from 'svelte/action';
import { matchesShortcut } from '$lib/actions/shortcut';
interface Options {
onOutclick?: () => void;
@@ -1,6 +1,6 @@
import { shortcuts } from '#lib/actions/shortcut.js';
import { tick } from 'svelte';
import type { Action } from 'svelte/action';
import { shortcuts } from '$lib/actions/shortcut';
interface Options {
/**
+1 -1
View File
@@ -1,5 +1,5 @@
import { getTabbable } from '#lib/utils/focus-util.js';
import { tick } from 'svelte';
import { getTabbable } from '$lib/utils/focus-util';
interface Options {
/**
+1 -1
View File
@@ -1,4 +1,4 @@
import { cancelImageUrl } from '$lib/utils/sw-messaging';
import { cancelImageUrl } from '#lib/utils/sw-messaging.js';
export function loadImage(src: string, onLoad: () => void, onError: () => void, onStart?: () => void) {
let destroyed = false;
+1 -1
View File
@@ -1,5 +1,5 @@
import { shortcuts } from '#lib/actions/shortcut.js';
import type { Action } from 'svelte/action';
import { shortcuts } from '$lib/actions/shortcut';
/**
* Enables keyboard navigation (up and down arrows) for a list of elements.
+19 -35
View File
@@ -1,6 +1,6 @@
import { navigating } from '$app/stores';
import { SessionStorageKey } from '$lib/constants';
import { handlePromiseError } from '$lib/utils';
import { SessionStorageKey } from '#lib/constants.js';
import { handlePromiseError } from '#lib/utils.js';
import { navigating } from '$app/state';
interface Options {
/**
@@ -31,19 +31,17 @@ export function scrollMemory(
node: HTMLElement,
{ routeStartsWith, beforeSave, beforeClear, beforeScroll }: PageOptions,
) {
const unsubscribeNavigating = navigating.subscribe((navigation) => {
const existingScroll = sessionStorage.getItem(SessionStorageKey.SCROLL_POSITION);
if (navigation?.to && !existingScroll) {
// Save current scroll information when going into a subpage.
if (navigation.to.url.pathname.startsWith(routeStartsWith)) {
beforeSave?.();
sessionStorage.setItem(SessionStorageKey.SCROLL_POSITION, node.scrollTop.toString());
} else {
beforeClear?.();
sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION);
}
const existingScroll = sessionStorage.getItem(SessionStorageKey.SCROLL_POSITION);
if (navigating?.to && !existingScroll) {
// Save current scroll information when going into a subpage.
if (navigating.to.url.pathname.startsWith(routeStartsWith)) {
beforeSave?.();
sessionStorage.setItem(SessionStorageKey.SCROLL_POSITION, node.scrollTop.toString());
} else {
beforeClear?.();
sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION);
}
});
}
handlePromiseError(
(async () => {
@@ -60,28 +58,14 @@ export function scrollMemory(
sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION);
})(),
);
return {
destroy() {
unsubscribeNavigating();
},
};
}
export function scrollMemoryClearer(_node: HTMLElement, { routeStartsWith, beforeClear }: Options) {
const unsubscribeNavigating = navigating.subscribe((navigation) => {
// Forget scroll position from main page if going somewhere else.
if (!navigation?.to || navigation?.to.url.pathname.startsWith(routeStartsWith)) {
return;
}
// Forget scroll position from main page if going somewhere else.
if (!navigating?.to || navigating?.to.url.pathname.startsWith(routeStartsWith)) {
return;
}
beforeClear?.();
sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION);
});
return {
destroy() {
unsubscribeNavigating();
},
};
beforeClear?.();
sessionStorage.removeItem(SessionStorageKey.SCROLL_POSITION);
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { createZoomImageWheel } from '@zoom-image/core';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
// Minimal touch shape — avoids importing DOM TouchEvent which isn't available in all TS targets.
type TouchEventLike = {
+5 -5
View File
@@ -1,3 +1,8 @@
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { readPreloadedQuery } from '#lib/queries/client.js';
import { getUserConfigQuery } from '#lib/queries/config-user.query.js';
import { Route } from '#lib/route.js';
import { copyToClipboard } from '#lib/utils.js';
import { defaultProvider, screencastManager, themeManager, ThemePreference, type ActionItem } from '@immich/ui';
import {
mdiAccountMultipleOutline,
@@ -30,11 +35,6 @@ import {
import type { MessageFormatter } from 'svelte-i18n';
import { goto } from '$app/navigation';
import { page } from '$app/state';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { readPreloadedQuery } from '$lib/queries/client';
import { getUserConfigQuery } from '$lib/queries/config-user.query';
import { Route } from '$lib/route';
import { copyToClipboard } from '$lib/utils';
export const getPagesProvider = ($t: MessageFormatter) => {
const adminPages: ActionItem[] = [
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/MenuOption.svelte';
import { isEnabled } from '$lib/utils';
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
import { isEnabled } from '#lib/utils.js';
import { type ActionItem } from '@immich/ui';
type Props = {
+13 -13
View File
@@ -1,5 +1,5 @@
<script module lang="ts">
import { TUNABLES } from '$lib/utils/tunables';
import { TUNABLES } from '#lib/utils/tunables.js';
// Chrome renders HDR images with normally invisible seam lines in a regular
// grid pattern. When the user pinch/scroll zooms, these seams become visible
@@ -50,20 +50,20 @@
</script>
<script lang="ts">
import AlphaBackground from '$lib/components/AlphaBackground.svelte';
import BrokenAsset from '$lib/components/assets/BrokenAsset.svelte';
import DelayedLoadingSpinner from '$lib/components/DelayedLoadingSpinner.svelte';
import ImageLayer from '$lib/components/ImageLayer.svelte';
import Thumbhash from '$lib/components/Thumbhash.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { getAssetUrls } from '$lib/utils';
import { AdaptiveImageLoader, type QualityList } from '$lib/utils/adaptive-image-loader.svelte';
import { scaleToCover, scaleToFit, type Size } from '$lib/utils/container-utils';
import { getAltText } from '$lib/utils/thumbnail-util';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import AlphaBackground from '#lib/components/AlphaBackground.svelte';
import BrokenAsset from '#lib/components/assets/BrokenAsset.svelte';
import DelayedLoadingSpinner from '#lib/components/DelayedLoadingSpinner.svelte';
import ImageLayer from '#lib/components/ImageLayer.svelte';
import Thumbhash from '#lib/components/Thumbhash.svelte';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { getAssetUrls } from '#lib/utils.js';
import { AdaptiveImageLoader, type QualityList } from '#lib/utils/adaptive-image-loader.svelte.js';
import { scaleToCover, scaleToFit, type Size } from '#lib/utils/container-utils.js';
import { getAltText } from '#lib/utils/thumbnail-util.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import type { AssetResponseDto, SharedLinkResponseDto } from '@immich/sdk';
import { untrack, type Snippet } from 'svelte';
import { languageManager } from '$lib/managers/language-manager.svelte';
import { languageManager } from '#lib/managers/language-manager.svelte.js';
type Props = {
asset: AssetResponseDto;
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import HeaderActionButton from '$lib/components/HeaderActionButton.svelte';
import HeaderActionButton from '#lib/components/HeaderActionButton.svelte';
import { Card, CardBody, CardHeader, CardTitle, Icon, type ActionItem, type IconLike } from '@immich/ui';
import type { Snippet } from 'svelte';
@@ -1,5 +1,5 @@
<script lang="ts">
import { cleanClass } from '$lib';
import { cleanClass } from '#lib';
import type { ClassValue } from 'svelte/elements';
interface Props {
@@ -1,5 +1,5 @@
<script lang="ts">
import ApiKeyGrid from '$lib/components/user-settings-page/UserApiKeyGrid.svelte';
import ApiKeyGrid from '#lib/components/user-settings-page/UserApiKeyGrid.svelte';
import { Permission } from '@immich/sdk';
import { Checkbox, IconButton, Input, Label } from '@immich/ui';
import { mdiClose } from '@mdi/js';
@@ -1,6 +1,6 @@
<script lang="ts">
import { assetViewerManager, type Events } from '$lib/managers/asset-viewer-manager.svelte';
import type { EventCallback, EventMap } from '$lib/utils/base-event-manager.svelte';
import { assetViewerManager, type Events } from '#lib/managers/asset-viewer-manager.svelte.js';
import type { EventCallback, EventMap } from '#lib/utils/base-event-manager.svelte.js';
import { onMount } from 'svelte';
type Props = {
@@ -1,5 +1,5 @@
<script lang="ts">
import type { HeaderButtonActionItem } from '$lib/types';
import type { HeaderButtonActionItem } from '#lib/types.js';
import {
Breadcrumbs,
Button,
@@ -1,5 +1,5 @@
<script lang="ts">
import { locale } from '$lib/stores/preferences.store';
import { locale } from '#lib/stores/preferences.store.js';
import type { CalendarHeatmapResponseDto } from '@immich/sdk';
import { Text } from '@immich/ui';
import { DateTime, Info } from 'luxon';
@@ -1,5 +1,5 @@
<script lang="ts">
import type { HeaderButtonActionItem } from '$lib/types';
import type { HeaderButtonActionItem } from '#lib/types.js';
import { Button, type Variants } from '@immich/ui';
type Props = {
+3 -3
View File
@@ -1,8 +1,8 @@
import Image from '#lib/components/Image.svelte';
import { cancelImageUrl } from '#lib/utils/sw-messaging.js';
import { fireEvent, render } from '@testing-library/svelte';
import Image from '$lib/components/Image.svelte';
import { cancelImageUrl } from '$lib/utils/sw-messaging';
vi.mock('$lib/utils/sw-messaging', () => ({
vi.mock('#lib/utils/sw-messaging.js', () => ({
cancelImageUrl: vi.fn(),
}));
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { isFirefox } from '$lib/utils/asset-utils';
import { cancelImageUrl } from '$lib/utils/sw-messaging';
import { isFirefox } from '#lib/utils/asset-utils.js';
import { cancelImageUrl } from '#lib/utils/sw-messaging.js';
import { onDestroy, untrack } from 'svelte';
import type { HTMLImgAttributes } from 'svelte/elements';
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import Image from '$lib/components/Image.svelte';
import type { AdaptiveImageLoader, ImageQuality } from '$lib/utils/adaptive-image-loader.svelte';
import Image from '#lib/components/Image.svelte';
import type { AdaptiveImageLoader, ImageQuality } from '#lib/utils/adaptive-image-loader.svelte.js';
type Props = {
adaptiveImageLoader: AdaptiveImageLoader;
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { cleanClass } from '$lib';
import { cleanClass } from '#lib';
import type { ClassValue } from 'svelte/elements';
interface Props {
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { eventManager, type Events } from '$lib/managers/event-manager.svelte';
import type { EventCallback, EventMap } from '$lib/utils/base-event-manager.svelte';
import { eventManager, type Events } from '#lib/managers/event-manager.svelte.js';
import type { EventCallback, EventMap } from '#lib/utils/base-event-manager.svelte.js';
import { onMount } from 'svelte';
type Props = {
@@ -1,7 +1,7 @@
<script lang="ts">
import AlbumThumbnail from '$lib/components/album-page/AlbumThumbnail.svelte';
import AlbumThumbnail from '#lib/components/album-page/AlbumThumbnail.svelte';
import { Button, Text, Label, modalManager } from '@immich/ui';
import AlbumPickerModal from '$lib/modals/AlbumPickerModal.svelte';
import AlbumPickerModal from '#lib/modals/AlbumPickerModal.svelte';
import { t } from 'svelte-i18n';
type Props = {
@@ -1,8 +1,8 @@
<script lang="ts">
import SchemaAlbumPicker from '$lib/components/SchemaAlbumPicker.svelte';
import Self from '$lib/components/SchemaConfiguration.svelte';
import SchemaTagPicker from '$lib/components/SchemaTagPicker.svelte';
import type { JSONSchemaProperty, SchemaConfig } from '$lib/types';
import SchemaAlbumPicker from '#lib/components/SchemaAlbumPicker.svelte';
import Self from '#lib/components/SchemaConfiguration.svelte';
import SchemaTagPicker from '#lib/components/SchemaTagPicker.svelte';
import type { JSONSchemaProperty, SchemaConfig } from '#lib/types.js';
import {
CodeBlock,
Field,
@@ -1,6 +1,6 @@
<script lang="ts">
import Combobox from '$lib/components/shared-components/Combobox.svelte';
import TagPill from '$lib/components/shared-components/TagPill.svelte';
import Combobox from '#lib/components/shared-components/Combobox.svelte';
import TagPill from '#lib/components/shared-components/TagPill.svelte';
import { getAllTags, type TagResponseDto } from '@immich/sdk';
import { onMount } from 'svelte';
import { t } from 'svelte-i18n';
@@ -1,6 +1,6 @@
<script lang="ts">
import { Button, DatePicker, Field } from '@immich/ui';
import { locale } from '$lib/stores/preferences.store';
import { locale } from '#lib/stores/preferences.store.js';
import { DateTime, Duration } from 'luxon';
import { t } from 'svelte-i18n';
@@ -1,5 +1,5 @@
import { renderWithTooltips } from '#tests/helpers';
import userEvent from '@testing-library/user-event';
import { renderWithTooltips } from '$tests/helpers';
import SharedLinkFormFields from './SharedLinkFormFields.svelte';
describe('SharedLinkFormFields component', () => {
@@ -1,5 +1,5 @@
<script lang="ts">
import SharedLinkExpiration from '$lib/components/SharedLinkExpiration.svelte';
import SharedLinkExpiration from '#lib/components/SharedLinkExpiration.svelte';
import { Field, HelperText, Input, PasswordInput, Switch, Text } from '@immich/ui';
import { t } from 'svelte-i18n';
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { decodeBase64 } from '$lib/utils';
import { TUNABLES } from '$lib/utils/tunables';
import { decodeBase64 } from '#lib/utils.js';
import { TUNABLES } from '#lib/utils/tunables.js';
import type { HTMLCanvasAttributes } from 'svelte/elements';
import { fade } from 'svelte/transition';
import { thumbHashToRGBA } from 'thumbhash';
@@ -1,15 +1,15 @@
<script lang="ts">
import SettingInputField from '$lib/components/shared-components/settings/SettingInputField.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/SettingSwitch.svelte';
import SettingButtonsRow from '$lib/components/shared-components/settings/SystemConfigButtonRow.svelte';
import { SettingInputFieldType } from '$lib/constants';
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 { createPreloadedQuery, executeMutation } from '$lib/queries/client';
import { getAdminConfigQuery, updateAdminConfigMutation } from '$lib/queries/config-admin.query';
import StorageTemplateVariablesModal from '$lib/modals/StorageTemplateVariablesModal.svelte';
import { Route } from '$lib/route';
import SettingInputField from '#lib/components/shared-components/settings/SettingInputField.svelte';
import SettingSwitch from '#lib/components/shared-components/settings/SettingSwitch.svelte';
import SettingButtonsRow from '#lib/components/shared-components/settings/SystemConfigButtonRow.svelte';
import { SettingInputFieldType } from '#lib/constants.js';
import FormatMessage from '#lib/elements/FormatMessage.svelte';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { featureFlagsManager } from '#lib/managers/feature-flags-manager.svelte.js';
import { createPreloadedQuery, executeMutation } from '#lib/queries/client.js';
import { getAdminConfigQuery, updateAdminConfigMutation } from '#lib/queries/config-admin.query.js';
import StorageTemplateVariablesModal from '#lib/modals/StorageTemplateVariablesModal.svelte';
import { Route } from '#lib/route.js';
import { getStorageTemplateOptions, type SystemConfigTemplateStorageOptionDto } from '@immich/sdk';
import { cloneDeep } from 'lodash-es';
import { Code, Heading, IconButton, Link, modalManager, Text } from '@immich/ui';
@@ -1,5 +1,5 @@
<script lang="ts">
import { locale } from '$lib/stores/preferences.store';
import { locale } from '#lib/stores/preferences.store.js';
import type { SystemConfigTemplateStorageOptionDto } from '@immich/sdk';
import { Card, CardBody, CardHeader, Heading, Text } from '@immich/ui';
import { DateTime } from 'luxon';
@@ -1,7 +1,7 @@
<script lang="ts">
import AlbumCover from '$lib/components/album-page/AlbumCover.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { getShortDateRange } from '$lib/utils/date-time';
import AlbumCover from '#lib/components/album-page/AlbumCover.svelte';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { getShortDateRange } from '#lib/utils/date-time.js';
import { type AlbumResponseDto } from '@immich/sdk';
import { ContextMenuButton, type MenuItems } from '@immich/ui';
import { t } from 'svelte-i18n';
@@ -1,10 +1,10 @@
<script lang="ts">
import AlbumCard from '$lib/components/album-page/AlbumCard.svelte';
import Portal from '$lib/elements/Portal.svelte';
import { Route } from '$lib/route';
import { getAlbumActions } from '$lib/services/album.service';
import { albumViewSettings } from '$lib/stores/preferences.store';
import { type AlbumGroup, isAlbumGroupCollapsed, toggleAlbumGroupCollapsing } from '$lib/utils/album-utils';
import AlbumCard from '#lib/components/album-page/AlbumCard.svelte';
import Portal from '#lib/elements/Portal.svelte';
import { Route } from '#lib/route.js';
import { getAlbumActions } from '#lib/services/album.service.js';
import { albumViewSettings } from '#lib/stores/preferences.store.js';
import { type AlbumGroup, isAlbumGroupCollapsed, toggleAlbumGroupCollapsing } from '#lib/utils/album-utils.js';
import type { AlbumResponseDto } from '@immich/sdk';
import { Icon, menuManager, type ActionItem } from '@immich/ui';
import { mdiChevronRight } from '@mdi/js';
@@ -1,7 +1,7 @@
<script lang="ts">
import AssetCover from '$lib/components/sharedlinks-page/covers/AssetCover.svelte';
import NoCover from '$lib/components/sharedlinks-page/covers/NoCover.svelte';
import { getAssetMediaUrl } from '$lib/utils';
import AssetCover from '#lib/components/sharedlinks-page/covers/AssetCover.svelte';
import NoCover from '#lib/components/sharedlinks-page/covers/NoCover.svelte';
import { getAssetMediaUrl } from '#lib/utils.js';
import { type AlbumResponseDto } from '@immich/sdk';
import { t } from 'svelte-i18n';
@@ -1,8 +1,8 @@
<script lang="ts">
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import MapModal from '$lib/modals/MapModal.svelte';
import { getAlbumMapMarkersQuery } from '$lib/queries/album.query';
import { navigate } from '$lib/utils/navigation';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import MapModal from '#lib/modals/MapModal.svelte';
import { getAlbumMapMarkersQuery } from '#lib/queries/album.query.js';
import { navigate } from '#lib/utils/navigation.js';
import { type AlbumResponseDto } from '@immich/sdk';
import { IconButton, modalManager } from '@immich/ui';
import { mdiMapOutline } from '@mdi/js';
@@ -1,6 +1,6 @@
<script lang="ts">
import { getSharedLinkActions } from '$lib/services/shared-link.service';
import { locale } from '$lib/stores/preferences.store';
import { getSharedLinkActions } from '#lib/services/shared-link.service.js';
import { locale } from '#lib/stores/preferences.store.js';
import type { AlbumResponseDto, SharedLinkResponseDto } from '@immich/sdk';
import { ActionButton, Text } from '@immich/ui';
import { DateTime } from 'luxon';
@@ -1,5 +1,5 @@
<script lang="ts">
import { getAlbumDateRange } from '$lib/utils/date-time';
import { getAlbumDateRange } from '#lib/utils/date-time.js';
import type { AlbumResponseDto } from '@immich/sdk';
import { t } from 'svelte-i18n';
@@ -1,7 +1,7 @@
<script lang="ts">
import AlbumCover from '$lib/components/album-page/AlbumCover.svelte';
import { getAlbumQuery } from '$lib/queries/album.query';
import { queryClient } from '$lib/queries/client';
import AlbumCover from '#lib/components/album-page/AlbumCover.svelte';
import { getAlbumQuery } from '#lib/queries/album.query.js';
import { queryClient } from '#lib/queries/client.js';
import { IconButton, Text, LoadingSpinner } from '@immich/ui';
import { mdiTrashCanOutline } from '@mdi/js';
import { createQuery } from '@tanstack/svelte-query';
@@ -1,20 +1,20 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import AlbumMap from '$lib/components/album-page/AlbumMap.svelte';
import DownloadAction from '$lib/components/timeline/actions/DownloadAction.svelte';
import SelectAllAssets from '$lib/components/timeline/actions/SelectAllAction.svelte';
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
import Timeline from '$lib/components/timeline/Timeline.svelte';
import { assetMultiSelectManager } from '$lib/managers/asset-multi-select-manager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import { handleDownloadAlbum } from '$lib/services/album.service';
import { getGlobalActions } from '$lib/services/app.service';
import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store';
import { mediaQueryManager } from '$lib/stores/media-query-manager.svelte';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { handlePromiseError } from '$lib/utils';
import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader';
import { shortcut } from '#lib/actions/shortcut.js';
import AlbumMap from '#lib/components/album-page/AlbumMap.svelte';
import DownloadAction from '#lib/components/timeline/actions/DownloadAction.svelte';
import SelectAllAssets from '#lib/components/timeline/actions/SelectAllAction.svelte';
import AssetSelectControlBar from '#lib/components/timeline/AssetSelectControlBar.svelte';
import Timeline from '#lib/components/timeline/Timeline.svelte';
import { assetMultiSelectManager } from '#lib/managers/asset-multi-select-manager.svelte.js';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { TimelineManager } from '#lib/managers/timeline-manager/timeline-manager.svelte.js';
import { handleDownloadAlbum } from '#lib/services/album.service.js';
import { getGlobalActions } from '#lib/services/app.service.js';
import { dragAndDropFilesStore } from '#lib/stores/drag-and-drop-files.store.js';
import { mediaQueryManager } from '#lib/stores/media-query-manager.svelte.js';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '#lib/stores/slideshow.store.js';
import { handlePromiseError } from '#lib/utils.js';
import { fileUploadHandler, openFileUploadDialog } from '#lib/utils/file-uploader.js';
import type { AlbumResponseDto, SharedLinkResponseDto } from '@immich/sdk';
import { ActionButton, IconButton, Logo } from '@immich/ui';
import { mdiDownload, mdiFileImagePlusOutline, mdiPresentationPlay } from '@mdi/js';
@@ -22,8 +22,8 @@
import ControlAppBar from '../shared-components/ControlAppBar.svelte';
import ThemeButton from '../shared-components/ThemeButton.svelte';
import AlbumSummary from './AlbumSummary.svelte';
import { createPreloadedQuery } from '$lib/queries/client';
import { getPublicConfigQuery } from '$lib/queries/config-public.query';
import { createPreloadedQuery } from '#lib/queries/client.js';
import { getPublicConfigQuery } from '#lib/queries/config-public.query.js';
const query = createPreloadedQuery(getPublicConfigQuery);
const publicConfig = $derived(query.data);
@@ -1,8 +1,8 @@
<script lang="ts">
import AlbumCardGroup from '$lib/components/album-page/AlbumCardGroup.svelte';
import AlbumsTable from '$lib/components/album-page/AlbumsTable.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { handleDeleteAlbum, isAlbumOwner } from '$lib/services/album.service';
import AlbumCardGroup from '#lib/components/album-page/AlbumCardGroup.svelte';
import AlbumsTable from '#lib/components/album-page/AlbumsTable.svelte';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { handleDeleteAlbum, isAlbumOwner } from '#lib/services/album.service.js';
import {
AlbumFilter,
AlbumGroupBy,
@@ -11,9 +11,14 @@
locale,
SortOrder,
type AlbumViewSettings,
} from '$lib/stores/preferences.store';
import { getSelectedAlbumGroupOption, sortAlbums, stringToSortOrder, type AlbumGroup } from '$lib/utils/album-utils';
import { normalizeSearchString } from '$lib/utils/string-utils';
} from '#lib/stores/preferences.store.js';
import {
getSelectedAlbumGroupOption,
sortAlbums,
stringToSortOrder,
type AlbumGroup,
} from '#lib/utils/album-utils.js';
import { normalizeSearchString } from '#lib/utils/string-utils.js';
import { type AlbumResponseDto } from '@immich/sdk';
import { groupBy } from 'lodash-es';
import { onMount, type Snippet } from 'svelte';
@@ -1,13 +1,13 @@
<script lang="ts">
import AlbumTableHeader from '$lib/components/album-page/AlbumsTableHeader.svelte';
import AlbumTableRow from '$lib/components/album-page/AlbumsTableRow.svelte';
import { AlbumGroupBy, albumViewSettings } from '$lib/stores/preferences.store';
import AlbumTableHeader from '#lib/components/album-page/AlbumsTableHeader.svelte';
import AlbumTableRow from '#lib/components/album-page/AlbumsTableRow.svelte';
import { AlbumGroupBy, albumViewSettings } from '#lib/stores/preferences.store.js';
import {
isAlbumGroupCollapsed,
sortOptionsMetadata,
toggleAlbumGroupCollapsing,
type AlbumGroup,
} from '$lib/utils/album-utils';
} from '#lib/utils/album-utils.js';
import { Icon } from '@immich/ui';
import { mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -1,6 +1,6 @@
<script lang="ts">
import { albumViewSettings, SortOrder, AlbumSortBy } from '$lib/stores/preferences.store';
import type { AlbumSortOptionMetadata } from '$lib/utils/album-utils';
import { albumViewSettings, SortOrder, AlbumSortBy } from '#lib/stores/preferences.store.js';
import type { AlbumSortOptionMetadata } from '#lib/utils/album-utils.js';
import { t } from 'svelte-i18n';
interface Props {
@@ -1,11 +1,11 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { dateFormats } from '$lib/constants';
import Portal from '$lib/elements/Portal.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { getAlbumActions } from '$lib/services/album.service';
import { locale } from '$lib/stores/preferences.store';
import { dateFormats } from '#lib/constants.js';
import Portal from '#lib/elements/Portal.svelte';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { Route } from '#lib/route.js';
import { getAlbumActions } from '#lib/services/album.service.js';
import { locale } from '#lib/stores/preferences.store.js';
import { AlbumUserRole, type AlbumResponseDto } from '@immich/sdk';
import { Icon, menuManager } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js';
@@ -1,8 +1,8 @@
import { sdkMock } from '#lib/__mocks__/sdk.mock.js';
import '@testing-library/jest-dom';
import { render, waitFor, type RenderResult } from '@testing-library/svelte';
import { init, register, waitLocale } from 'svelte-i18n';
import { sdkMock } from '$lib/__mocks__/sdk.mock';
import { albumFactory } from '@test-data/factories/album-factory';
import { albumFactory } from '#test-data/factories/album-factory';
import AlbumCard from '../AlbumCard.svelte';
describe('AlbumCard component', () => {
@@ -10,7 +10,7 @@ describe('AlbumCard component', () => {
beforeAll(async () => {
await init({ fallbackLocale: 'en-US' });
register('en-US', () => import('$i18n/en.json'));
register('en-US', () => import('#i18n/en.json'));
await waitLocale('en-US');
});
@@ -1,9 +1,9 @@
import AlbumCover from '#lib/components/album-page/AlbumCover.svelte';
import { getAssetMediaUrl } from '#lib/utils.js';
import { render } from '@testing-library/svelte';
import AlbumCover from '$lib/components/album-page/AlbumCover.svelte';
import { getAssetMediaUrl } from '$lib/utils';
import { albumFactory } from '@test-data/factories/album-factory';
import { albumFactory } from '#test-data/factories/album-factory';
vi.mock('$lib/utils');
vi.mock('#lib/utils.js');
describe('AlbumCover component', () => {
it('renders an image when the album has a thumbnail', () => {
@@ -2,17 +2,17 @@ import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/svelte';
import { init, register, waitLocale } from 'svelte-i18n';
import { writable } from 'svelte/store';
import { albumFactory } from '@test-data/factories/album-factory';
import { albumFactory } from '#test-data/factories/album-factory';
import AlbumSummary from '../AlbumSummary.svelte';
vitest.mock('$lib/stores/preferences.store', () => ({
vitest.mock('#lib/stores/preferences.store.js', () => ({
locale: writable('en'),
}));
describe('AlbumSummary component', () => {
beforeAll(async () => {
await init({ fallbackLocale: 'en-US' });
register('en-US', () => import('$i18n/en.json'));
register('en-US', () => import('#i18n/en.json'));
await waitLocale('en-US');
});
@@ -1,6 +1,6 @@
<script lang="ts">
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { locale } from '$lib/stores/preferences.store';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { locale } from '#lib/stores/preferences.store.js';
import type { ActivityResponseDto } from '@immich/sdk';
import { Button } from '@immich/ui';
import { mdiCommentOutline, mdiThumbUp, mdiThumbUpOutline } from '@mdi/js';
@@ -1,15 +1,15 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
import { activityManager } from '$lib/managers/activity-manager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { locale } from '$lib/stores/preferences.store';
import { getAssetMediaUrl } from '$lib/utils';
import { getAssetType } from '$lib/utils/asset-utils';
import { handleError } from '$lib/utils/handle-error';
import { isTenMinutesApart } from '$lib/utils/timesince';
import { shortcut } from '#lib/actions/shortcut.js';
import { timeBeforeShowLoadingSpinner } from '#lib/constants.js';
import { activityManager } from '#lib/managers/activity-manager.svelte.js';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { Route } from '#lib/route.js';
import { locale } from '#lib/stores/preferences.store.js';
import { getAssetMediaUrl } from '#lib/utils.js';
import { getAssetType } from '#lib/utils/asset-utils.js';
import { handleError } from '#lib/utils/handle-error.js';
import { isTenMinutesApart } from '#lib/utils/timesince.js';
import { ReactionType, type ActivityResponseDto, type AlbumUserResponseDto, type AssetTypeEnum } from '@immich/sdk';
import { ContextMenuButton, Icon, IconButton, LoadingSpinner, Textarea, toastManager } from '@immich/ui';
import { mdiClose, mdiSend, mdiThumbUp, mdiTrashCanOutline } from '@mdi/js';
@@ -1,8 +1,8 @@
<script lang="ts">
import { SCROLL_PROPERTIES } from '$lib/components/shared-components/album-selection/album-selection-utils';
import { mediaQueryManager } from '$lib/stores/media-query-manager.svelte';
import { getAssetMediaUrl } from '$lib/utils';
import { normalizeSearchString } from '$lib/utils/string-utils.js';
import { SCROLL_PROPERTIES } from '#lib/components/shared-components/album-selection/album-selection-utils.js';
import { mediaQueryManager } from '#lib/stores/media-query-manager.svelte.js';
import { getAssetMediaUrl } from '#lib/utils.js';
import { normalizeSearchString } from '#lib/utils/string-utils.js';
import { type AlbumResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { mdiCheckCircle } from '@mdi/js';
@@ -1,16 +1,16 @@
import { getAnimateMock } from '#lib/__mocks__/animate.mock.js';
import { getResizeObserverMock } from '#lib/__mocks__/resize-observer.mock.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { SlideshowState, slideshowStore } from '#lib/stores/slideshow.store.js';
import { renderWithTooltips } from '#tests/helpers';
import { updateAsset } from '@immich/sdk';
import { fireEvent, waitFor } from '@testing-library/svelte';
import { getAnimateMock } from '$lib/__mocks__/animate.mock';
import { getResizeObserverMock } from '$lib/__mocks__/resize-observer.mock';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { renderWithTooltips } from '$tests/helpers';
import { assetFactory } from '@test-data/factories/asset-factory';
import { preferencesFactory } from '@test-data/factories/preferences-factory';
import { userAdminFactory } from '@test-data/factories/user-factory';
import { assetFactory } from '#test-data/factories/asset-factory';
import { preferencesFactory } from '#test-data/factories/preferences-factory';
import { userAdminFactory } from '#test-data/factories/user-factory';
import AssetViewer from './AssetViewer.svelte';
vi.mock('$lib/managers/feature-flags-manager.svelte', () => ({
vi.mock('#lib/managers/feature-flags-manager.svelte.js', () => ({
featureFlagsManager: {
init: vi.fn(),
loadFeatureFlags: vi.fn(),
@@ -18,7 +18,7 @@ vi.mock('$lib/managers/feature-flags-manager.svelte', () => ({
} as never,
}));
vi.mock('$lib/stores/ocr.svelte', () => ({
vi.mock('#lib/stores/ocr.svelte.js', () => ({
ocrManager: {
clear: vi.fn(),
getAssetOcr: vi.fn(),
@@ -1,33 +1,33 @@
<script lang="ts">
import { browser } from '$app/environment';
import { focusTrap } from '$lib/actions/focus-trap';
import { shortcuts } from '$lib/actions/shortcut';
import type { Action, OnAction, PreAction } from '$lib/components/asset-viewer/actions/action';
import NextAssetAction from '$lib/components/asset-viewer/actions/NextAssetAction.svelte';
import PreviousAssetAction from '$lib/components/asset-viewer/actions/PreviousAssetAction.svelte';
import AssetViewerNavBar from '$lib/components/asset-viewer/AssetViewerNavBar.svelte';
import { preloadManager } from '$lib/components/asset-viewer/PreloadManager.svelte';
import OnEvents from '$lib/components/OnEvents.svelte';
import { AssetAction, ProjectionType } from '$lib/constants';
import { activityManager } from '$lib/managers/activity-manager.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { editManager, EditToolType } from '$lib/managers/edit/edit-manager.svelte';
import { eventManager } from '$lib/managers/event-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import { getAssetActions } from '$lib/services/asset.service';
import { faceManager } from '$lib/stores/face.svelte';
import { ocrManager } from '$lib/stores/ocr.svelte';
import { alwaysLoadOriginalVideo } from '$lib/stores/preferences.store';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { getSharedLink, handlePromiseError } from '$lib/utils';
import type { OnUndoDelete } from '$lib/utils/actions';
import { navigateToAsset } from '$lib/utils/asset-utils';
import { handleError } from '$lib/utils/handle-error';
import { navigate } from '$lib/utils/navigation';
import { InvocationTracker } from '$lib/utils/invocationTracker';
import { SlideshowHistory } from '$lib/utils/slideshow-history';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { browser } from '$app/env';
import { focusTrap } from '#lib/actions/focus-trap.js';
import { shortcuts } from '#lib/actions/shortcut.js';
import type { Action, OnAction, PreAction } from '#lib/components/asset-viewer/actions/action.js';
import NextAssetAction from '#lib/components/asset-viewer/actions/NextAssetAction.svelte';
import PreviousAssetAction from '#lib/components/asset-viewer/actions/PreviousAssetAction.svelte';
import AssetViewerNavBar from '#lib/components/asset-viewer/AssetViewerNavBar.svelte';
import { preloadManager } from '#lib/components/asset-viewer/PreloadManager.svelte.js';
import OnEvents from '#lib/components/OnEvents.svelte';
import { AssetAction, ProjectionType } from '#lib/constants.js';
import { activityManager } from '#lib/managers/activity-manager.svelte.js';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { editManager, EditToolType } from '#lib/managers/edit/edit-manager.svelte.js';
import { eventManager } from '#lib/managers/event-manager.svelte.js';
import type { TimelineAsset } from '#lib/managers/timeline-manager/types.js';
import { getAssetActions } from '#lib/services/asset.service.js';
import { faceManager } from '#lib/stores/face.svelte.js';
import { ocrManager } from '#lib/stores/ocr.svelte.js';
import { alwaysLoadOriginalVideo } from '#lib/stores/preferences.store.js';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '#lib/stores/slideshow.store.js';
import { getSharedLink, handlePromiseError } from '#lib/utils.js';
import type { OnUndoDelete } from '#lib/utils/actions.js';
import { navigateToAsset } from '#lib/utils/asset-utils.js';
import { handleError } from '#lib/utils/handle-error.js';
import { navigate } from '#lib/utils/navigation.js';
import { InvocationTracker } from '#lib/utils/invocationTracker.js';
import { SlideshowHistory } from '#lib/utils/slideshow-history.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import {
AssetTypeEnum,
getAssetInfo,
@@ -440,6 +440,7 @@
if (assetViewerManager.isPlayingMotionPhoto && asset.livePhotoVideoId) {
return 'LiveVideoViewer';
}
if (
asset.exifInfo?.projectionType === ProjectionType.EQUIRECTANGULAR ||
(asset.originalPath && asset.originalPath.toLowerCase().endsWith('.insp'))
@@ -458,14 +459,12 @@
((album && album.isActivityEnabled) || activityManager.commentCount > 0) &&
!activityManager.isLoading,
);
const showOcrButton = $derived(
$slideshowState === SlideshowState.None &&
asset.type === AssetTypeEnum.Image &&
!assetViewerManager.isShowEditor &&
ocrManager.hasOcrData,
);
const { Tag, TagPeople } = $derived(getAssetActions($t, asset));
const showDetailPanel = $derived(
asset.hasMetadata &&
@@ -507,7 +506,7 @@
{ shortcut: { key: 'ArrowUp' }, onShortcut: () => navigateStack('previous') },
{ shortcut: { key: 'ArrowDown' }, onShortcut: () => navigateStack('next') },
]}
/>
></svelte:document>
<section
id="immich-asset-viewer"
@@ -1,16 +1,16 @@
import { getResizeObserverMock } from '#lib/__mocks__/resize-observer.mock.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { queryClient } from '#lib/queries/client.js';
import { getUserConfigQuery } from '#lib/queries/config-user.query.js';
import { renderWithTooltips } from '#tests/helpers';
import type { UserConfigDto } from '@immich/sdk';
import '@testing-library/jest-dom';
import { getResizeObserverMock } from '$lib/__mocks__/resize-observer.mock';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { queryClient } from '$lib/queries/client';
import { getUserConfigQuery } from '$lib/queries/config-user.query';
import { renderWithTooltips } from '$tests/helpers';
import { assetFactory } from '@test-data/factories/asset-factory';
import { preferencesFactory } from '@test-data/factories/preferences-factory';
import { userAdminFactory } from '@test-data/factories/user-factory';
import { assetFactory } from '#test-data/factories/asset-factory';
import { preferencesFactory } from '#test-data/factories/preferences-factory';
import { userAdminFactory } from '#test-data/factories/user-factory';
import AssetViewerNavBar from './AssetViewerNavBar.svelte';
vi.mock(import('$lib/managers/feature-flags-manager.svelte'), function () {
vi.mock(import('#lib/managers/feature-flags-manager.svelte.js'), function () {
return {
featureFlagsManager: {
init: vi.fn(),
@@ -1,23 +1,23 @@
<script lang="ts">
import ActionMenuItem from '$lib/components/ActionMenuItem.svelte';
import type { OnAction, PreAction } from '$lib/components/asset-viewer/actions/action';
import ArchiveAction from '$lib/components/asset-viewer/actions/ArchiveAction.svelte';
import DeleteAction from '$lib/components/asset-viewer/actions/DeleteAction.svelte';
import RestoreAction from '$lib/components/asset-viewer/actions/RestoreAction.svelte';
import SetVisibilityAction from '$lib/components/asset-viewer/actions/SetVisibilityAction.svelte';
import LoadingDots from '$lib/components/LoadingDots.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { languageManager } from '$lib/managers/language-manager.svelte';
import { getAlbumAssetActions } from '$lib/services/album.service';
import { getGlobalActions } from '$lib/services/app.service';
import { getAssetActions } from '$lib/services/asset.service';
import { getPersonAssetActions } from '$lib/services/person.service';
import { getStackActions } from '$lib/services/stack.service';
import { getSharedLink, withoutIcons } from '$lib/utils';
import type { OnUndoDelete } from '$lib/utils/actions';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import ActionMenuItem from '#lib/components/ActionMenuItem.svelte';
import type { OnAction, PreAction } from '#lib/components/asset-viewer/actions/action.js';
import ArchiveAction from '#lib/components/asset-viewer/actions/ArchiveAction.svelte';
import DeleteAction from '#lib/components/asset-viewer/actions/DeleteAction.svelte';
import RestoreAction from '#lib/components/asset-viewer/actions/RestoreAction.svelte';
import SetVisibilityAction from '#lib/components/asset-viewer/actions/SetVisibilityAction.svelte';
import LoadingDots from '#lib/components/LoadingDots.svelte';
import ButtonContextMenu from '#lib/components/shared-components/context-menu/ButtonContextMenu.svelte';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { languageManager } from '#lib/managers/language-manager.svelte.js';
import { getAlbumAssetActions } from '#lib/services/album.service.js';
import { getGlobalActions } from '#lib/services/app.service.js';
import { getAssetActions } from '#lib/services/asset.service.js';
import { getPersonAssetActions } from '#lib/services/person.service.js';
import { getStackActions } from '#lib/services/stack.service.js';
import { getSharedLink, withoutIcons } from '#lib/utils.js';
import type { OnUndoDelete } from '#lib/utils/actions.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import {
AssetTypeEnum,
AssetVisibility,
@@ -1,19 +1,19 @@
<script lang="ts">
import { goto } from '$app/navigation';
import DetailPanelDate from '$lib/components/asset-viewer/DetailPanelDate.svelte';
import DetailPanelDescription from '$lib/components/asset-viewer/DetailPanelDescription.svelte';
import DetailPanelLocation from '$lib/components/asset-viewer/DetailPanelLocation.svelte';
import DetailPanelRating from '$lib/components/asset-viewer/DetailPanelStarRating.svelte';
import DetailPanelTags from '$lib/components/asset-viewer/DetailPanelTags.svelte';
import { timeToLoadTheMap } from '$lib/constants';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { locale } from '$lib/stores/preferences.store';
import { getAssetMediaUrl } from '$lib/utils';
import { delay, getDimensions } from '$lib/utils/asset-utils';
import { getByteUnitString } from '$lib/utils/byte-units';
import { getParentPath } from '$lib/utils/tree-utils';
import DetailPanelDate from '#lib/components/asset-viewer/DetailPanelDate.svelte';
import DetailPanelDescription from '#lib/components/asset-viewer/DetailPanelDescription.svelte';
import DetailPanelLocation from '#lib/components/asset-viewer/DetailPanelLocation.svelte';
import DetailPanelRating from '#lib/components/asset-viewer/DetailPanelStarRating.svelte';
import DetailPanelTags from '#lib/components/asset-viewer/DetailPanelTags.svelte';
import { timeToLoadTheMap } from '#lib/constants.js';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { Route } from '#lib/route.js';
import { locale } from '#lib/stores/preferences.store.js';
import { getAssetMediaUrl } from '#lib/utils.js';
import { delay, getDimensions } from '#lib/utils/asset-utils.js';
import { getByteUnitString } from '#lib/utils/byte-units.js';
import { getParentPath } from '#lib/utils/tree-utils.js';
import { AssetMediaSize, getAssetInfo, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk';
import { createQuery } from '@tanstack/svelte-query';
import { Icon, IconButton, Link, LoadingSpinner, Text } from '@immich/ui';
@@ -24,11 +24,11 @@
import PersonSidePanel from '../faces-page/PersonSidePanel.svelte';
import UserAvatar from '../shared-components/UserAvatar.svelte';
import AlbumListItemDetails from './AlbumListItemDetails.svelte';
import DetailPanelPeople from '$lib/components/asset-viewer/DetailPanelPeople.svelte';
import { faceManager } from '$lib/stores/face.svelte';
import { getAlbumsByAssetQuery } from '$lib/queries/album.query';
import { createPreloadedQuery } from '$lib/queries/client';
import { getPublicConfigQuery } from '$lib/queries/config-public.query';
import DetailPanelPeople from '#lib/components/asset-viewer/DetailPanelPeople.svelte';
import { faceManager } from '#lib/stores/face.svelte.js';
import { getAlbumsByAssetQuery } from '#lib/queries/album.query.js';
import { createPreloadedQuery } from '#lib/queries/client.js';
import { getPublicConfigQuery } from '#lib/queries/config-public.query.js';
const query = createPreloadedQuery(getPublicConfigQuery);
const publicConfig = $derived(query.data);
@@ -267,7 +267,7 @@
{#if latlng && publicConfig.map.enabled}
<div class="h-90">
{#await import('$lib/components/shared-components/map/Map.svelte')}
{#await import('#lib/components/shared-components/map/Map.svelte')}
{#await delay(timeToLoadTheMap) then}
<!-- show the loading spinner only if loading the map takes too much time -->
<div class="flex size-full items-center justify-center">
@@ -1,8 +1,8 @@
<script lang="ts">
import { authManager } from '$lib/managers/auth-manager.svelte';
import AssetChangeDateModal from '$lib/modals/AssetChangeDateModal.svelte';
import { locale } from '$lib/stores/preferences.store';
import { fromISODateTime, fromISODateTimeUTC, toTimelineAsset } from '$lib/utils/timeline-util';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import AssetChangeDateModal from '#lib/modals/AssetChangeDateModal.svelte';
import { locale } from '#lib/stores/preferences.store.js';
import { fromISODateTime, fromISODateTimeUTC, toTimelineAsset } from '#lib/utils/timeline-util.js';
import { type AssetResponseDto } from '@immich/sdk';
import { Icon, modalManager } from '@immich/ui';
import { mdiCalendar, mdiPencil } from '@mdi/js';
@@ -1,7 +1,7 @@
import '@testing-library/jest-dom';
import { render, screen } from '@testing-library/svelte';
import userEvent from '@testing-library/user-event';
import { assetFactory } from '@test-data/factories/asset-factory';
import { assetFactory } from '#test-data/factories/asset-factory';
import DetailPanelDescription from './DetailPanelDescription.svelte';
describe('DetailPanelDescription', () => {
@@ -1,6 +1,6 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import { handleError } from '$lib/utils/handle-error';
import { shortcut } from '#lib/actions/shortcut.js';
import { handleError } from '#lib/utils/handle-error.js';
import { updateAsset, type AssetResponseDto } from '@immich/sdk';
import { Textarea, toastManager } from '@immich/ui';
import { t } from 'svelte-i18n';
@@ -1,6 +1,6 @@
<script lang="ts">
import GeolocationPointPickerModal from '$lib/modals/GeolocationPointPickerModal.svelte';
import { handleError } from '$lib/utils/handle-error';
import GeolocationPointPickerModal from '#lib/modals/GeolocationPointPickerModal.svelte';
import { handleError } from '#lib/utils/handle-error.js';
import { updateAsset, type AssetResponseDto } from '@immich/sdk';
import { Icon, modalManager } from '@immich/ui';
import { mdiMapMarkerOutline, mdiPencil } from '@mdi/js';
@@ -1,11 +1,11 @@
<script lang="ts">
import ImageThumbnail from '$lib/components/assets/thumbnail/ImageThumbnail.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { faceManager } from '$lib/stores/face.svelte';
import { locale } from '$lib/stores/preferences.store';
import { getPeopleThumbnailUrl } from '$lib/utils';
import ImageThumbnail from '#lib/components/assets/thumbnail/ImageThumbnail.svelte';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { Route } from '#lib/route.js';
import { faceManager } from '#lib/stores/face.svelte.js';
import { locale } from '#lib/stores/preferences.store.js';
import { getPeopleThumbnailUrl } from '#lib/utils.js';
import { type AssetResponseDto } from '@immich/sdk';
import { IconButton, Text } from '@immich/ui';
import { mdiEye, mdiEyeOff, mdiPencil, mdiPlus } from '@mdi/js';
@@ -1,8 +1,8 @@
<script lang="ts">
import StarRating, { type Rating } from '$lib/elements/StarRating.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { handlePromiseError } from '$lib/utils';
import { handleError } from '$lib/utils/handle-error';
import StarRating, { type Rating } from '#lib/elements/StarRating.svelte';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { handlePromiseError } from '#lib/utils.js';
import { handleError } from '#lib/utils/handle-error.js';
import { updateAsset, type AssetResponseDto } from '@immich/sdk';
import { t } from 'svelte-i18n';
@@ -1,10 +1,10 @@
<script lang="ts">
import HeaderActionButton from '$lib/components/HeaderActionButton.svelte';
import OnEvents from '$lib/components/OnEvents.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { Route } from '$lib/route';
import { getAssetActions } from '$lib/services/asset.service';
import { removeTag } from '$lib/utils/asset-utils';
import HeaderActionButton from '#lib/components/HeaderActionButton.svelte';
import OnEvents from '#lib/components/OnEvents.svelte';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { Route } from '#lib/route.js';
import { getAssetActions } from '#lib/services/asset.service.js';
import { removeTag } from '#lib/utils/asset-utils.js';
import { getAssetInfo, type AssetResponseDto } from '@immich/sdk';
import { Badge, Link, Text } from '@immich/ui';
import { t } from 'svelte-i18n';
@@ -1,6 +1,6 @@
<script lang="ts">
import { authManager } from '$lib/managers/auth-manager.svelte';
import { getAssetUrl } from '$lib/utils';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { getAssetUrl } from '#lib/utils.js';
import { AssetMediaSize, viewAsset, type AssetResponseDto } from '@immich/sdk';
import { LoadingSpinner } from '@immich/ui';
import { t } from 'svelte-i18n';
@@ -1,7 +1,7 @@
<script lang="ts">
import { mediaQueryManager } from '$lib/stores/media-query-manager.svelte';
import type { OcrBox } from '$lib/utils/ocr-utils';
import { calculateBoundingBoxMatrix, calculateFittedFontSize } from '$lib/utils/ocr-utils';
import { mediaQueryManager } from '#lib/stores/media-query-manager.svelte.js';
import type { OcrBox } from '#lib/utils/ocr-utils.js';
import { calculateBoundingBoxMatrix, calculateFittedFontSize } from '#lib/utils/ocr-utils.js';
type Props = {
ocrBox: OcrBox;
@@ -1,5 +1,5 @@
<script lang="ts">
import { ocrManager } from '$lib/stores/ocr.svelte';
import { ocrManager } from '#lib/stores/ocr.svelte.js';
import { IconButton } from '@immich/ui';
import { mdiTextRecognition } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -1,10 +1,10 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import AssetViewerEvents from '$lib/components/AssetViewerEvents.svelte';
import { assetViewerManager, type Faces } from '$lib/managers/asset-viewer-manager.svelte';
import { ocrManager, type OcrBoundingBox } from '$lib/stores/ocr.svelte';
import { alwaysLoadOriginalFile } from '$lib/stores/preferences.store';
import { calculateBoundingBoxMatrix, getOcrBoundingBoxes, type Point } from '$lib/utils/ocr-utils';
import { shortcuts } from '#lib/actions/shortcut.js';
import AssetViewerEvents from '#lib/components/AssetViewerEvents.svelte';
import { assetViewerManager, type Faces } from '#lib/managers/asset-viewer-manager.svelte.js';
import { ocrManager, type OcrBoundingBox } from '#lib/stores/ocr.svelte.js';
import { alwaysLoadOriginalFile } from '#lib/stores/preferences.store.js';
import { calculateBoundingBoxMatrix, getOcrBoundingBoxes, type Point } from '#lib/utils/ocr-utils.js';
import {
EquirectangularAdapter,
Viewer,
@@ -1,22 +1,22 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import { zoomImageAction } from '$lib/actions/zoom-image';
import AdaptiveImage from '$lib/components/AdaptiveImage.svelte';
import FaceEditor from '$lib/components/asset-viewer/face-editor/FaceEditor.svelte';
import OcrBoundingBox from '$lib/components/asset-viewer/OcrBoundingBox.svelte';
import AssetViewerEvents from '$lib/components/AssetViewerEvents.svelte';
import Thumbhash from '$lib/components/Thumbhash.svelte';
import { assetViewerManager, type Faces } from '$lib/managers/asset-viewer-manager.svelte';
import { castManager } from '$lib/managers/cast-manager.svelte';
import { faceManager } from '$lib/stores/face.svelte';
import { ocrManager } from '$lib/stores/ocr.svelte';
import { SlideshowLook, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { handlePromiseError } from '$lib/utils';
import { canCopyImageToClipboard, copyImageToClipboard } from '$lib/utils/asset-utils';
import { getNaturalSize, scaleToFit, type Size } from '$lib/utils/container-utils';
import { handleError } from '$lib/utils/handle-error';
import { getOcrBoundingBoxes } from '$lib/utils/ocr-utils';
import { getBoundingBox, type BoundingBox } from '$lib/utils/people-utils';
import { shortcuts } from '#lib/actions/shortcut.js';
import { zoomImageAction } from '#lib/actions/zoom-image.js';
import AdaptiveImage from '#lib/components/AdaptiveImage.svelte';
import FaceEditor from '#lib/components/asset-viewer/face-editor/FaceEditor.svelte';
import OcrBoundingBox from '#lib/components/asset-viewer/OcrBoundingBox.svelte';
import AssetViewerEvents from '#lib/components/AssetViewerEvents.svelte';
import Thumbhash from '#lib/components/Thumbhash.svelte';
import { assetViewerManager, type Faces } from '#lib/managers/asset-viewer-manager.svelte.js';
import { castManager } from '#lib/managers/cast-manager.svelte.js';
import { faceManager } from '#lib/stores/face.svelte.js';
import { ocrManager } from '#lib/stores/ocr.svelte.js';
import { SlideshowLook, SlideshowState, slideshowStore } from '#lib/stores/slideshow.store.js';
import { handlePromiseError } from '#lib/utils.js';
import { canCopyImageToClipboard, copyImageToClipboard } from '#lib/utils/asset-utils.js';
import { getNaturalSize, scaleToFit, type Size } from '#lib/utils/container-utils.js';
import { handleError } from '#lib/utils/handle-error.js';
import { getOcrBoundingBoxes } from '#lib/utils/ocr-utils.js';
import { getBoundingBox, type BoundingBox } from '#lib/utils/people-utils.js';
import { type SharedLinkResponseDto } from '@immich/sdk';
import { toastManager } from '@immich/ui';
import { onDestroy, untrack } from 'svelte';
@@ -1,7 +1,7 @@
import { loadImage } from '#lib/actions/image-loader.svelte.js';
import { getAssetUrls } from '#lib/utils.js';
import { AdaptiveImageLoader, type QualityList } from '#lib/utils/adaptive-image-loader.svelte.js';
import type { AssetResponseDto, SharedLinkResponseDto } from '@immich/sdk';
import { loadImage } from '$lib/actions/image-loader.svelte';
import { getAssetUrls } from '$lib/utils';
import { AdaptiveImageLoader, type QualityList } from '$lib/utils/adaptive-image-loader.svelte';
type AssetCursor = {
current: AssetResponseDto;
@@ -1,10 +1,10 @@
<script lang="ts">
import { shortcuts, type ShortcutOptions } from '$lib/actions/shortcut';
import ProgressBar from '$lib/components/shared-components/progress-bar/ProgressBar.svelte';
import { ProgressBarStatus } from '$lib/constants';
import { languageManager } from '$lib/managers/language-manager.svelte';
import SlideshowSettingsModal from '$lib/modals/SlideshowSettingsModal.svelte';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { shortcuts, type ShortcutOptions } from '#lib/actions/shortcut.js';
import ProgressBar from '#lib/components/shared-components/progress-bar/ProgressBar.svelte';
import { ProgressBarStatus } from '#lib/constants.js';
import { languageManager } from '#lib/managers/language-manager.svelte.js';
import SlideshowSettingsModal from '#lib/modals/SlideshowSettingsModal.svelte';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '#lib/stores/slideshow.store.js';
import { AssetTypeEnum } from '@immich/sdk';
import { IconButton, modalManager } from '@immich/ui';
import { mdiChevronLeft, mdiChevronRight, mdiClose, mdiCog, mdiFullscreen, mdiPause, mdiPlay } from '@mdi/js';
@@ -1,6 +1,6 @@
<script lang="ts">
import { SlideshowMetadataOverlayMode, slideshowStore } from '$lib/stores/slideshow.store';
import { fromISODateTime, fromISODateTimeUTC } from '$lib/utils/timeline-util';
import { SlideshowMetadataOverlayMode, slideshowStore } from '#lib/stores/slideshow.store.js';
import { fromISODateTime, fromISODateTimeUTC } from '#lib/utils/timeline-util.js';
import type { AssetResponseDto } from '@immich/sdk';
import { Text } from '@immich/ui';
import { DateTime } from 'luxon';
@@ -1,13 +1,13 @@
<script lang="ts">
import FaceEditor from '$lib/components/asset-viewer/face-editor/FaceEditor.svelte';
import VideoRemoteViewer from '$lib/components/asset-viewer/VideoRemoteViewer.svelte';
import { assetViewerFadeDuration } from '$lib/constants';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import { castManager } from '$lib/managers/cast-manager.svelte';
import { authManager } from '$lib/managers/auth-manager.svelte';
import { mediaCapabilitiesManager } from '$lib/managers/media-capabilities-manager.svelte';
import { autoPlayVideo, lang, loopVideo as loopVideoPreference } from '$lib/stores/preferences.store';
import { getAssetHlsSessionUrl, getAssetHlsUrl, getAssetMediaUrl, getAssetPlaybackUrl } from '$lib/utils';
import FaceEditor from '#lib/components/asset-viewer/face-editor/FaceEditor.svelte';
import VideoRemoteViewer from '#lib/components/asset-viewer/VideoRemoteViewer.svelte';
import { assetViewerFadeDuration } from '#lib/constants.js';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import { castManager } from '#lib/managers/cast-manager.svelte.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import { mediaCapabilitiesManager } from '#lib/managers/media-capabilities-manager.svelte.js';
import { autoPlayVideo, lang, loopVideo as loopVideoPreference } from '#lib/stores/preferences.store.js';
import { getAssetHlsSessionUrl, getAssetHlsUrl, getAssetMediaUrl, getAssetPlaybackUrl } from '#lib/utils.js';
import { AssetMediaSize, type AssetResponseDto } from '@immich/sdk';
import { Icon, LoadingSpinner, shortcuts } from '@immich/ui';
import {
@@ -44,8 +44,8 @@
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import './immich-time-range';
import { createPreloadedQuery } from '$lib/queries/client';
import { getPublicConfigQuery } from '$lib/queries/config-public.query';
import { createPreloadedQuery } from '#lib/queries/client.js';
import { getPublicConfigQuery } from '#lib/queries/config-public.query.js';
const query = createPreloadedQuery(getPublicConfigQuery);
const publicConfig = $derived(query.data);
@@ -1,5 +1,5 @@
<script lang="ts">
import { getAssetPlaybackUrl, getAssetUrl } from '$lib/utils';
import { getAssetPlaybackUrl, getAssetUrl } from '#lib/utils.js';
import type { AssetResponseDto } from '@immich/sdk';
import { LoadingSpinner } from '@immich/ui';
import { t } from 'svelte-i18n';
@@ -1,6 +1,6 @@
<script lang="ts">
import { castManager, CastState } from '$lib/managers/cast-manager.svelte';
import { handleError } from '$lib/utils/handle-error';
import { castManager, CastState } from '#lib/managers/cast-manager.svelte.js';
import { handleError } from '#lib/utils/handle-error.js';
import { Icon, IconButton, LoadingSpinner } from '@immich/ui';
import { mdiCastConnected, mdiPause, mdiPlay } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -1,7 +1,7 @@
<script lang="ts">
import VideoNativeViewer from '$lib/components/asset-viewer/VideoNativeViewer.svelte';
import VideoPanoramaViewer from '$lib/components/asset-viewer/VideoPanoramaViewer.svelte';
import { ProjectionType } from '$lib/constants';
import VideoNativeViewer from '#lib/components/asset-viewer/VideoNativeViewer.svelte';
import VideoPanoramaViewer from '#lib/components/asset-viewer/VideoPanoramaViewer.svelte';
import { ProjectionType } from '#lib/constants.js';
import type { AssetResponseDto } from '@immich/sdk';
interface Props {
@@ -1,10 +1,10 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import type { OnAction, PreAction } from '$lib/components/asset-viewer/actions/action';
import MenuOption from '$lib/components/shared-components/context-menu/MenuOption.svelte';
import { AssetAction } from '$lib/constants';
import { toggleArchive } from '$lib/utils/asset-utils';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { shortcut } from '#lib/actions/shortcut.js';
import type { OnAction, PreAction } from '#lib/components/asset-viewer/actions/action.js';
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
import { AssetAction } from '#lib/constants.js';
import { toggleArchive } from '#lib/utils/asset-utils.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import type { AssetResponseDto } from '@immich/sdk';
import { mdiArchiveArrowDownOutline, mdiArchiveArrowUpOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -1,10 +1,10 @@
import { renderWithTooltips } from '#tests/helpers';
import type { AssetResponseDto } from '@immich/sdk';
import '@testing-library/jest-dom';
import { renderWithTooltips } from '$tests/helpers';
import { assetFactory } from '@test-data/factories/asset-factory';
import { assetFactory } from '#test-data/factories/asset-factory';
import DeleteAction from './DeleteAction.svelte';
vi.mock(import('$lib/managers/feature-flags-manager.svelte'), () => {
vi.mock(import('#lib/managers/feature-flags-manager.svelte.js'), () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return { featureFlagsManager: { init: vi.fn(), loadFeatureFlags: vi.fn(), value: { trash: true } } as any };
});
@@ -1,12 +1,12 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import { AssetAction } from '$lib/constants';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import AssetDeleteConfirmModal from '$lib/modals/AssetDeleteConfirmModal.svelte';
import { showDeleteModal } from '$lib/stores/preferences.store';
import { deleteAssets as deleteAssetsUtil, type OnUndoDelete } from '$lib/utils/actions';
import { handleError } from '$lib/utils/handle-error';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { shortcuts } from '#lib/actions/shortcut.js';
import { AssetAction } from '#lib/constants.js';
import { featureFlagsManager } from '#lib/managers/feature-flags-manager.svelte.js';
import AssetDeleteConfirmModal from '#lib/modals/AssetDeleteConfirmModal.svelte';
import { showDeleteModal } from '#lib/stores/preferences.store.js';
import { deleteAssets as deleteAssetsUtil, type OnUndoDelete } from '#lib/utils/actions.js';
import { handleError } from '#lib/utils/handle-error.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import { deleteAssets, type AssetResponseDto } from '@immich/sdk';
import { IconButton, modalManager, toastManager } from '@immich/ui';
import { mdiDeleteForeverOutline, mdiDeleteOutline } from '@mdi/js';
@@ -1,10 +1,10 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import { shortcuts } from '#lib/actions/shortcut.js';
import { Icon } from '@immich/ui';
import { mdiChevronRight, mdiChevronLeft } from '@mdi/js';
import { t } from 'svelte-i18n';
import NavigationArea from '../NavigationArea.svelte';
import { languageManager } from '$lib/managers/language-manager.svelte';
import { languageManager } from '#lib/managers/language-manager.svelte.js';
interface Props {
onNextAsset: () => void;
@@ -1,10 +1,10 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import { shortcuts } from '#lib/actions/shortcut.js';
import { Icon } from '@immich/ui';
import { mdiChevronLeft, mdiChevronRight } from '@mdi/js';
import { t } from 'svelte-i18n';
import NavigationArea from '../NavigationArea.svelte';
import { languageManager } from '$lib/managers/language-manager.svelte';
import { languageManager } from '#lib/managers/language-manager.svelte.js';
interface Props {
onPreviousAsset: () => void;
@@ -1,8 +1,8 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/MenuOption.svelte';
import { AssetAction } from '$lib/constants';
import { handleError } from '$lib/utils/handle-error';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
import { AssetAction } from '#lib/constants.js';
import { handleError } from '#lib/utils/handle-error.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import { restoreAssets, type AssetResponseDto } from '@immich/sdk';
import { toastManager } from '@immich/ui';
import { mdiHistory } from '@mdi/js';
@@ -1,8 +1,8 @@
<script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/MenuOption.svelte';
import { AssetAction } from '$lib/constants';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import { handleError } from '$lib/utils/handle-error';
import MenuOption from '#lib/components/shared-components/context-menu/MenuOption.svelte';
import { AssetAction } from '#lib/constants.js';
import type { TimelineAsset } from '#lib/managers/timeline-manager/types.js';
import { handleError } from '#lib/utils/handle-error.js';
import { AssetVisibility, updateAssets } from '@immich/sdk';
import { modalManager } from '@immich/ui';
import { mdiLockOpenVariantOutline, mdiLockOutline } from '@mdi/js';
@@ -1,5 +1,5 @@
import type { AssetAction } from '$lib/constants';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import type { AssetAction } from '#lib/constants.js';
import type { TimelineAsset } from '#lib/managers/timeline-manager/types.js';
type ActionMap = {
[AssetAction.ARCHIVE]: { asset: TimelineAsset };
@@ -1,7 +1,7 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import { editManager, EditToolType } from '$lib/managers/edit/edit-manager.svelte';
import { websocketEvents } from '$lib/stores/websocket';
import { shortcuts } from '#lib/actions/shortcut.js';
import { editManager, EditToolType } from '#lib/managers/edit/edit-manager.svelte.js';
import { websocketEvents } from '#lib/stores/websocket.js';
import { getAssetEdits, type AssetResponseDto } from '@immich/sdk';
import { Button, HStack, IconButton } from '@immich/ui';
import { mdiClose } from '@mdi/js';
@@ -1,8 +1,8 @@
<script lang="ts">
import { ResizeBoundary, transformManager } from '$lib/managers/edit/transform-manager.svelte';
import { getAssetMediaUrl } from '$lib/utils';
import { getAltText } from '$lib/utils/thumbnail-util';
import { toTimelineAsset } from '$lib/utils/timeline-util';
import { ResizeBoundary, transformManager } from '#lib/managers/edit/transform-manager.svelte.js';
import { getAssetMediaUrl } from '#lib/utils.js';
import { getAltText } from '#lib/utils/thumbnail-util.js';
import { toTimelineAsset } from '#lib/utils/timeline-util.js';
import { AssetMediaSize, type AssetResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import { onMount } from 'svelte';
@@ -1,6 +1,6 @@
<script lang="ts">
import { shortcuts } from '$lib/actions/shortcut';
import { transformManager } from '$lib/managers/edit/transform-manager.svelte';
import { shortcuts } from '#lib/actions/shortcut.js';
import { transformManager } from '#lib/managers/edit/transform-manager.svelte.js';
import { Button, HStack, IconButton } from '@immich/ui';
import { mdiFlipHorizontal, mdiFlipVertical, mdiRotateLeft, mdiRotateRight } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -1,13 +1,13 @@
<script lang="ts">
import { shortcut } from '$lib/actions/shortcut';
import ImageThumbnail from '$lib/components/assets/thumbnail/ImageThumbnail.svelte';
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
import FaceCreateTagModal from '$lib/modals/CreateFaceModal.svelte';
import { faceManager } from '$lib/stores/face.svelte';
import { getPeopleThumbnailUrl } from '$lib/utils';
import { getNaturalSize, scaleToFit } from '$lib/utils/container-utils';
import { handleError } from '$lib/utils/handle-error';
import { normalizeSearchString } from '$lib/utils/string-utils';
import { shortcut } from '#lib/actions/shortcut.js';
import ImageThumbnail from '#lib/components/assets/thumbnail/ImageThumbnail.svelte';
import { assetViewerManager } from '#lib/managers/asset-viewer-manager.svelte.js';
import FaceCreateTagModal from '#lib/modals/CreateFaceModal.svelte';
import { faceManager } from '#lib/stores/face.svelte.js';
import { getPeopleThumbnailUrl } from '#lib/utils.js';
import { getNaturalSize, scaleToFit } from '#lib/utils/container-utils.js';
import { handleError } from '#lib/utils/handle-error.js';
import { normalizeSearchString } from '#lib/utils/string-utils.js';
import { createFace, getAllPeople, type PersonResponseDto } from '@immich/sdk';
import { Button, Input, modalManager, toastManager } from '@immich/ui';
import { Canvas, InteractiveFabricObject, Rect } from 'fabric';
@@ -1,5 +1,5 @@
<script lang="ts">
import { cleanClass } from '$lib';
import { cleanClass } from '#lib';
import { Icon } from '@immich/ui';
import { mdiImageBrokenVariant } from '@mdi/js';
import { t } from 'svelte-i18n';
@@ -1,7 +1,7 @@
import ImageThumbnail from '#lib/components/assets/thumbnail/ImageThumbnail.svelte';
import { fireEvent, render } from '@testing-library/svelte';
import ImageThumbnail from '$lib/components/assets/thumbnail/ImageThumbnail.svelte';
vi.mock('$lib/utils/sw-messaging', () => ({
vi.mock('#lib/utils/sw-messaging.js', () => ({
cancelImageUrl: vi.fn(),
}));
@@ -1,6 +1,6 @@
<script lang="ts">
import BrokenAsset from '$lib/components/assets/BrokenAsset.svelte';
import Image from '$lib/components/Image.svelte';
import BrokenAsset from '#lib/components/assets/BrokenAsset.svelte';
import Image from '#lib/components/Image.svelte';
import { Icon } from '@immich/ui';
import { mdiEyeOffOutline } from '@mdi/js';
import type { ClassValue } from 'svelte/elements';
@@ -1,13 +1,13 @@
<script lang="ts">
import { ProjectionType } from '$lib/constants';
import { authManager } from '$lib/managers/auth-manager.svelte';
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
import { mediaQueryManager } from '$lib/stores/media-query-manager.svelte';
import { locale, playVideoThumbnailOnHover } from '$lib/stores/preferences.store';
import { getAssetMediaUrl, getAssetPlaybackUrl } from '$lib/utils';
import { moveFocus } from '$lib/utils/focus-util';
import { currentUrlReplaceAssetId } from '$lib/utils/navigation';
import { getAltText } from '$lib/utils/thumbnail-util';
import { ProjectionType } from '#lib/constants.js';
import { authManager } from '#lib/managers/auth-manager.svelte.js';
import type { TimelineAsset } from '#lib/managers/timeline-manager/types.js';
import { mediaQueryManager } from '#lib/stores/media-query-manager.svelte.js';
import { locale, playVideoThumbnailOnHover } from '#lib/stores/preferences.store.js';
import { getAssetMediaUrl, getAssetPlaybackUrl } from '#lib/utils.js';
import { moveFocus } from '#lib/utils/focus-util.js';
import { currentUrlReplaceAssetId } from '#lib/utils/navigation.js';
import { getAltText } from '#lib/utils/thumbnail-util.js';
import { AssetMediaSize, AssetVisibility, type UserResponseDto } from '@immich/sdk';
import { Icon } from '@immich/ui';
import {
@@ -24,7 +24,7 @@
import { onMount } from 'svelte';
import type { ClassValue } from 'svelte/elements';
import { fade } from 'svelte/transition';
import Thumbhash from '$lib/components/Thumbhash.svelte';
import Thumbhash from '#lib/components/Thumbhash.svelte';
import ImageThumbnail from './ImageThumbnail.svelte';
import VideoThumbnail from './VideoThumbnail.svelte';
interface Props {
@@ -1,5 +1,5 @@
<script lang="ts">
import { cleanClass } from '$lib';
import { cleanClass } from '#lib';
import { Icon, LoadingSpinner } from '@immich/ui';
import { mdiAlertCircleOutline, mdiPauseCircleOutline, mdiPlayCircleOutline } from '@mdi/js';
import { Duration } from 'luxon';

Some files were not shown because too many files have changed in this diff Show More