feat(web): make assets cachable (#1724)
| @@ -86,6 +86,8 @@ export default { | ||||
|  | ||||
| 	// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module | ||||
| 	moduleNameMapper: { | ||||
| 		'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': | ||||
| 			'identity-obj-proxy', | ||||
| 		'^\\$lib(.*)$': '<rootDir>/src/lib$1', | ||||
| 		'^\\@api(.*)$': '<rootDir>/src/api$1', | ||||
| 		'^\\@test-data(.*)$': '<rootDir>/src/test-data$1' | ||||
|   | ||||
							
								
								
									
										34
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						| @@ -45,6 +45,7 @@ | ||||
| 				"eslint-config-prettier": "^8.3.0", | ||||
| 				"eslint-plugin-svelte3": "^4.0.0", | ||||
| 				"factory.ts": "^1.2.0", | ||||
| 				"identity-obj-proxy": "^3.0.0", | ||||
| 				"jest": "^29.0.2", | ||||
| 				"jest-environment-jsdom": "^29.0.2", | ||||
| 				"postcss": "^8.4.13", | ||||
| @@ -6202,6 +6203,12 @@ | ||||
| 				"uglify-js": "^3.1.4" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/harmony-reflect": { | ||||
| 			"version": "1.6.2", | ||||
| 			"resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", | ||||
| 			"integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/has": { | ||||
| 			"version": "1.0.3", | ||||
| 			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", | ||||
| @@ -6337,6 +6344,18 @@ | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/identity-obj-proxy": { | ||||
| 			"version": "3.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", | ||||
| 			"integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"harmony-reflect": "^1.4.6" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=4" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ignore": { | ||||
| 			"version": "5.2.1", | ||||
| 			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", | ||||
| @@ -15822,6 +15841,12 @@ | ||||
| 				"wordwrap": "^1.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"harmony-reflect": { | ||||
| 			"version": "1.6.2", | ||||
| 			"resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", | ||||
| 			"integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"has": { | ||||
| 			"version": "1.0.3", | ||||
| 			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", | ||||
| @@ -15918,6 +15943,15 @@ | ||||
| 				"safer-buffer": ">= 2.1.2 < 3.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"identity-obj-proxy": { | ||||
| 			"version": "3.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", | ||||
| 			"integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"harmony-reflect": "^1.4.6" | ||||
| 			} | ||||
| 		}, | ||||
| 		"ignore": { | ||||
| 			"version": "5.2.1", | ||||
| 			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", | ||||
|   | ||||
| @@ -43,6 +43,7 @@ | ||||
| 		"eslint-config-prettier": "^8.3.0", | ||||
| 		"eslint-plugin-svelte3": "^4.0.0", | ||||
| 		"factory.ts": "^1.2.0", | ||||
| 		"identity-obj-proxy": "^3.0.0", | ||||
| 		"jest": "^29.0.2", | ||||
| 		"jest-environment-jsdom": "^29.0.2", | ||||
| 		"postcss": "^8.4.13", | ||||
|   | ||||
| @@ -4,13 +4,13 @@ | ||||
|  | ||||
| @font-face { | ||||
| 	font-family: 'Work Sans'; | ||||
| 	src: url('/fonts/WorkSans-VariableFont_wght.ttf') format('truetype-variations'); | ||||
| 	src: url('$lib/assets/fonts/WorkSans-VariableFont_wght.ttf') format('truetype-variations'); | ||||
| 	font-weight: 1 999; | ||||
| } | ||||
|  | ||||
| @font-face { | ||||
| 	font-family: 'Snowburst One'; | ||||
| 	src: url('/fonts/SnowburstOne-Regular.ttf') format('truetype'); | ||||
| 	src: url('$lib/assets/fonts/SnowburstOne-Regular.ttf') format('truetype'); | ||||
| } | ||||
|  | ||||
| :root { | ||||
|   | ||||
| @@ -2,7 +2,6 @@ | ||||
| <html lang="en" class="dark"> | ||||
| 	<head> | ||||
| 		<meta charset="utf-8" /> | ||||
| 		<link rel="icon" href="%sveltekit.assets%/favicon.png" /> | ||||
| 		<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
| 		%sveltekit.head% | ||||
| 	</head> | ||||
|   | ||||
| Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB | 
| Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB | 
| Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB | 
| Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB | 
| Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB | 
| Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB | 
| Before Width: | Height: | Size: 584 B After Width: | Height: | Size: 584 B | 
| @@ -44,10 +44,10 @@ describe('AlbumCard component', () => { | ||||
| 			const albumDetailsElement = sut.getByTestId('album-details'); | ||||
| 			const detailsText = `${count} items` + (shared ? ' . Shared' : ''); | ||||
|  | ||||
| 			expect(albumImgElement).toHaveAttribute('src', 'no-thumbnail.png'); | ||||
| 			expect(albumImgElement).toHaveAttribute('src'); | ||||
| 			expect(albumImgElement).toHaveAttribute('alt', album.id); | ||||
|  | ||||
| 			await waitFor(() => expect(albumImgElement).toHaveAttribute('src', 'no-thumbnail.png')); | ||||
| 			await waitFor(() => expect(albumImgElement).toHaveAttribute('src')); | ||||
|  | ||||
| 			expect(albumImgElement).toHaveAttribute('alt', album.id); | ||||
| 			expect(apiMock.assetApi.getAssetThumbnail).not.toHaveBeenCalled(); | ||||
| @@ -108,7 +108,7 @@ describe('AlbumCard component', () => { | ||||
| 			sut = render(AlbumCard, { album }); | ||||
|  | ||||
| 			const albumImgElement = sut.getByTestId('album-image'); | ||||
| 			await waitFor(() => expect(albumImgElement).toHaveAttribute('src', 'no-thumbnail.png')); | ||||
| 			await waitFor(() => expect(albumImgElement).toHaveAttribute('src')); | ||||
| 		}); | ||||
|  | ||||
| 		it('dispatches custom "click" event with the album in context', async () => { | ||||
|   | ||||
| @@ -16,14 +16,13 @@ | ||||
| 	import { createEventDispatcher, onMount } from 'svelte'; | ||||
| 	import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; | ||||
| 	import CircleIconButton from '../shared-components/circle-icon-button.svelte'; | ||||
| 	import noThumbnailUrl from '$lib/assets/no-thumbnail.png'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
|  | ||||
| 	const NO_THUMBNAIL = 'no-thumbnail.png'; | ||||
|  | ||||
| 	let imageData = `/api/asset/thumbnail/${album.albumThumbnailAssetId}?format=${ThumbnailFormat.Webp}`; | ||||
| 	if (!album.albumThumbnailAssetId) { | ||||
| 		imageData = NO_THUMBNAIL; | ||||
| 		imageData = noThumbnailUrl; | ||||
| 	} | ||||
|  | ||||
| 	const dispatchClick = createEventDispatcher<OnClick>(); | ||||
| @@ -51,7 +50,7 @@ | ||||
| 	}; | ||||
|  | ||||
| 	onMount(async () => { | ||||
| 		imageData = (await loadHighQualityThumbnail(album.albumThumbnailAssetId)) || NO_THUMBNAIL; | ||||
| 		imageData = (await loadHighQualityThumbnail(album.albumThumbnailAssetId)) || noThumbnailUrl; | ||||
| 	}); | ||||
|  | ||||
| 	const locale = navigator.language; | ||||
|   | ||||
| @@ -40,6 +40,7 @@ | ||||
| 	import { openFileUploadDialog } from '$lib/utils/file-uploader'; | ||||
| 	import { bulkDownload } from '$lib/utils/asset-utils'; | ||||
| 	import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
| 	export let sharedLink: SharedLinkResponseDto | undefined = undefined; | ||||
| @@ -419,13 +420,7 @@ | ||||
| 						class="flex gap-2 place-items-center hover:cursor-pointer ml-6" | ||||
| 						href="https://immich.app" | ||||
| 					> | ||||
| 						<img | ||||
| 							src="/immich-logo.svg" | ||||
| 							alt="immich logo" | ||||
| 							height="30" | ||||
| 							width="30" | ||||
| 							draggable="false" | ||||
| 						/> | ||||
| 						<ImmichLogo height={30} width={30} /> | ||||
| 						<h1 class="font-immich-title text-lg text-immich-primary dark:text-immich-dark-primary"> | ||||
| 							IMMICH | ||||
| 						</h1> | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| 	import Link from 'svelte-material-icons/Link.svelte'; | ||||
| 	import ShareCircle from 'svelte-material-icons/ShareCircle.svelte'; | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
| 	export let sharedUsersInAlbum: Set<UserResponseDto>; | ||||
| @@ -53,7 +54,7 @@ | ||||
| <BaseModal on:close={() => dispatch('close')}> | ||||
| 	<svelte:fragment slot="title"> | ||||
| 		<span class="flex gap-2 place-items-center"> | ||||
| 			<img src="/immich-logo.svg" width="24" alt="Immich" draggable="false" /> | ||||
| 			<ImmichLogo width={24} /> | ||||
| 			<p class="font-medium">Invite to album</p> | ||||
| 		</span> | ||||
| 	</svelte:fragment> | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <script lang="ts"> | ||||
| 	import { goto } from '$app/navigation'; | ||||
|  | ||||
| 	import { api } from '@api'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	let error: string; | ||||
| 	let success: string; | ||||
|  | ||||
| @@ -55,14 +56,7 @@ | ||||
| 	class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" | ||||
| > | ||||
| 	<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> | ||||
| 		<img | ||||
| 			class="text-center" | ||||
| 			src="/immich-logo.svg" | ||||
| 			height="100" | ||||
| 			width="100" | ||||
| 			alt="immich-logo" | ||||
| 			draggable="false" | ||||
| 		/> | ||||
| 		<ImmichLogo class="text-center" height="100" width="100" /> | ||||
| 		<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium"> | ||||
| 			Admin Registration | ||||
| 		</h1> | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { api, UserResponseDto } from '@api'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	export let user: UserResponseDto; | ||||
| 	let error: string; | ||||
| @@ -47,14 +48,7 @@ | ||||
| 	class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" | ||||
| > | ||||
| 	<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> | ||||
| 		<img | ||||
| 			class="text-center" | ||||
| 			src="/immich-logo.svg" | ||||
| 			height="100" | ||||
| 			width="100" | ||||
| 			alt="immich-logo" | ||||
| 			draggable="false" | ||||
| 		/> | ||||
| 		<ImmichLogo class="text-center" height="100" width="100" /> | ||||
| 		<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium"> | ||||
| 			Change Password | ||||
| 		</h1> | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import { api } from '@api'; | ||||
| 	import { createEventDispatcher } from 'svelte'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
| 	import { | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| @@ -80,14 +81,7 @@ | ||||
| 	class="border bg-immich-bg dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-3xl py-8 dark:text-immich-dark-fg" | ||||
| > | ||||
| 	<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> | ||||
| 		<img | ||||
| 			class="text-center" | ||||
| 			src="/immich-logo.svg" | ||||
| 			height="100" | ||||
| 			width="100" | ||||
| 			alt="immich-logo" | ||||
| 			draggable="false" | ||||
| 		/> | ||||
| 		<ImmichLogo class="text-center" height="100" width="100" /> | ||||
| 		<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium"> | ||||
| 			Create new user | ||||
| 		</h1> | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| 	import { handleError } from '$lib/utils/handle-error'; | ||||
| 	import { api, oauth, OAuthConfigResponseDto } from '@api'; | ||||
| 	import { createEventDispatcher, onMount } from 'svelte'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	let error: string; | ||||
| 	let email = ''; | ||||
| @@ -77,14 +78,7 @@ | ||||
| 	class="border bg-white dark:bg-immich-dark-gray dark:border-immich-dark-gray p-4 shadow-sm w-[500px] max-w-[95vw] rounded-md py-8" | ||||
| > | ||||
| 	<div class="flex flex-col place-items-center place-content-center gap-4 px-4"> | ||||
| 		<img | ||||
| 			class="text-center" | ||||
| 			src="/immich-logo.svg" | ||||
| 			height="100" | ||||
| 			width="100" | ||||
| 			alt="immich-logo" | ||||
| 			draggable="false" | ||||
| 		/> | ||||
| 		<ImmichLogo class="text-center" height="100" width="100" /> | ||||
| 		<h1 class="text-2xl text-immich-primary dark:text-immich-dark-primary font-medium">Login</h1> | ||||
| 	</div> | ||||
|  | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| 	} from '../shared-components/notification/notification'; | ||||
| 	import ImmichLogo from '../shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	export let sharedLink: SharedLinkResponseDto; | ||||
| 	export let isOwned: boolean; | ||||
| @@ -122,7 +123,7 @@ | ||||
| 					class="flex gap-2 place-items-center hover:cursor-pointer ml-6" | ||||
| 					href="https://immich.app" | ||||
| 				> | ||||
| 					<img src="/immich-logo.svg" alt="immich logo" height="30" width="30" draggable="false" /> | ||||
| 					<ImmichLogo height="30" width="30" /> | ||||
| 					<h1 class="font-immich-title text-lg text-immich-primary dark:text-immich-dark-primary"> | ||||
| 						IMMICH | ||||
| 					</h1> | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| <script lang="ts"> | ||||
| 	import { fade } from 'svelte/transition'; | ||||
| 	import ImmichLogo from './immich-logo.svelte'; | ||||
|  | ||||
| 	export let dropHandler: (event: DragEvent) => void; | ||||
| 	export let dragOverHandler: (event: DragEvent) => void; | ||||
| @@ -14,13 +15,6 @@ | ||||
| 	on:dragleave={dragLeaveHandler} | ||||
| 	class="fixed inset-0 w-full h-full z-[1000] flex flex-col items-center justify-center bg-gray-100/90 dark:bg-immich-dark-bg/90 text-immich-dark-gray dark:text-immich-gray" | ||||
| > | ||||
| 	<img | ||||
| 		src="/immich-logo.svg" | ||||
| 		alt="immich logo" | ||||
| 		height="200" | ||||
| 		width="200" | ||||
| 		class="animate-bounce pb-16" | ||||
| 		draggable="false" | ||||
| 	/> | ||||
| 	<ImmichLogo height="200" width="200" class="animate-bounce pb-16" /> | ||||
| 	<div class="text-2xl">Drop files anywhere to upload</div> | ||||
| </div> | ||||
|   | ||||
| @@ -0,0 +1,7 @@ | ||||
| <script lang="ts"> | ||||
| 	import immichLogoUrl from '$lib/assets/immich-logo.svg'; | ||||
|  | ||||
| 	export let draggable = false; | ||||
| </script> | ||||
|  | ||||
| <img src={immichLogoUrl} alt="Immich Logo" {draggable} {...$$restProps} /> | ||||
| @@ -8,6 +8,7 @@ | ||||
| 	import ThemeButton from '../theme-button.svelte'; | ||||
| 	import { AppRoute } from '../../../constants'; | ||||
| 	import AccountInfoPanel from './account-info-panel.svelte'; | ||||
| 	import ImmichLogo from '../immich-logo.svelte'; | ||||
| 	export let user: UserResponseDto; | ||||
| 	export let shouldShowUploadButton = true; | ||||
|  | ||||
| @@ -50,7 +51,7 @@ | ||||
| 			class="flex gap-2 place-items-center hover:cursor-pointer" | ||||
| 			href="/photos" | ||||
| 		> | ||||
| 			<img src="/immich-logo.svg" alt="immich logo" height="35" width="35" draggable="false" /> | ||||
| 			<ImmichLogo height="35" width="35" /> | ||||
| 			<h1 class="font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary"> | ||||
| 				IMMICH | ||||
| 			</h1> | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
| 	import { fade } from 'svelte/transition'; | ||||
| 	import { asByteUnitString } from '$lib/utils/byte-units'; | ||||
| 	import { UploadAsset } from '$lib/models/upload-asset'; | ||||
| 	import ImmichLogo from './immich-logo.svelte'; | ||||
|  | ||||
| 	export let uploadAsset: UploadAsset; | ||||
|  | ||||
| @@ -16,13 +17,9 @@ | ||||
| > | ||||
| 	<div class="relative"> | ||||
| 		{#if showFallbackImage} | ||||
| 			<img | ||||
| 				in:fade={{ duration: 250 }} | ||||
| 				src="immich-logo.svg" | ||||
| 				alt="Immich Logo" | ||||
| 				class="h-[70px] w-[70px] object-cover rounded-tl-lg rounded-bl-lg" | ||||
| 				draggable="false" | ||||
| 			/> | ||||
| 			<div in:fade={{ duration: 250 }}> | ||||
| 				<ImmichLogo class="h-[70px] w-[70px] object-cover rounded-tl-lg rounded-bl-lg" /> | ||||
| 			</div> | ||||
| 		{:else} | ||||
| 			<img | ||||
| 				in:fade={{ duration: 250 }} | ||||
|   | ||||
| @@ -1,13 +1,14 @@ | ||||
| <script lang="ts"> | ||||
| 	import { AlbumResponseDto, api, ThumbnailFormat, UserResponseDto } from '@api'; | ||||
| 	import { fade } from 'svelte/transition'; | ||||
| 	import noThumbnailUrl from '$lib/assets/no-thumbnail.png'; | ||||
|  | ||||
| 	export let album: AlbumResponseDto; | ||||
| 	export let user: UserResponseDto; | ||||
|  | ||||
| 	const loadImageData = async (thubmnailId: string | null) => { | ||||
| 		if (thubmnailId == null) { | ||||
| 			return '/no-thumbnail.png'; | ||||
| 			return noThumbnailUrl; | ||||
| 		} | ||||
|  | ||||
| 		const { data } = await api.assetApi.getAssetThumbnail(thubmnailId, ThumbnailFormat.Webp, { | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| 		NotificationType | ||||
| 	} from '$lib/components/shared-components/notification/notification'; | ||||
| 	import { handleError } from '$lib/utils/handle-error'; | ||||
| 	import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte'; | ||||
|  | ||||
| 	const handleCopy = async () => { | ||||
| 		// | ||||
| @@ -33,7 +34,7 @@ | ||||
| 	<section class="bg-immich-bg dark:bg-immich-dark-bg"> | ||||
| 		<div class="flex border-b dark:border-b-immich-dark-gray place-items-center px-6 py-4"> | ||||
| 			<a class="flex gap-2 place-items-center hover:cursor-pointer" href="/photos"> | ||||
| 				<img src="/immich-logo.svg" alt="immich logo" height="35" width="35" draggable="false" /> | ||||
| 				<ImmichLogo height="35" width="35" /> | ||||
| 				<h1 class="font-immich-title text-2xl text-immich-primary dark:text-immich-dark-primary"> | ||||
| 					IMMICH | ||||
| 				</h1> | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| 	import NavigationLoadingBar from '$lib/components/shared-components/navigation-loading-bar.svelte'; | ||||
| 	import NotificationList from '$lib/components/shared-components/notification/notification-list.svelte'; | ||||
| 	import { fileUploadHandler } from '$lib/utils/file-uploader'; | ||||
| 	import faviconUrl from '$lib/assets/favicon.png'; | ||||
|  | ||||
| 	let shouldShowAnnouncement: boolean; | ||||
| 	let localVersion: string; | ||||
| @@ -80,6 +81,7 @@ | ||||
| <svelte:head> | ||||
| 	<title>{$page.data.meta?.title || 'Web'} - Immich</title> | ||||
| 	{#if $page.data.meta} | ||||
| 		<link rel="icon" href={faviconUrl} /> | ||||
| 		<meta name="description" content={$page.data.meta.description} /> | ||||
|  | ||||
| 		<!-- Facebook Meta Tags --> | ||||
|   | ||||
| @@ -1,18 +1,12 @@ | ||||
| <script lang="ts"> | ||||
| 	import { goto } from '$app/navigation'; | ||||
| 	import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte'; | ||||
| </script> | ||||
|  | ||||
| <section class="h-screen w-screen flex place-items-center place-content-center"> | ||||
| 	<div class="flex flex-col place-items-center gap-8 text-center max-w-[350px]"> | ||||
| 		<div class="flex place-items-center place-content-center "> | ||||
| 			<img | ||||
| 				class="text-center" | ||||
| 				src="immich-logo.svg" | ||||
| 				height="200" | ||||
| 				width="200" | ||||
| 				alt="immich-logo" | ||||
| 				draggable="false" | ||||
| 			/> | ||||
| 			<ImmichLogo class="text-center" height="200" width="200" /> | ||||
| 		</div> | ||||
| 		<h1 | ||||
| 			class="text-4xl text-immich-primary dark:text-immich-dark-primary font-bold font-immich-title" | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| 	import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte'; | ||||
| 	import PlusBoxOutline from 'svelte-material-icons/PlusBoxOutline.svelte'; | ||||
| 	import { useAlbums } from './albums.bloc'; | ||||
| 	import empty1Url from '$lib/assets/empty-1.svg'; | ||||
|  | ||||
| 	export let data: PageData; | ||||
|  | ||||
| @@ -93,7 +94,7 @@ | ||||
| 					on:keydown={handleCreateAlbum} | ||||
| 					class="border dark:border-immich-dark-gray hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/25 hover:cursor-pointer p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center" | ||||
| 				> | ||||
| 					<img src="/empty-1.svg" alt="Empty shared album" width="500" draggable="false" /> | ||||
| 					<img src={empty1Url} alt="Empty shared album" width="500" draggable="false" /> | ||||
|  | ||||
| 					<p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg"> | ||||
| 						Create an album to organize your photos and videos | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| 	import StarMinusOutline from 'svelte-material-icons/StarMinusOutline.svelte'; | ||||
| 	import Error from '../+error.svelte'; | ||||
| 	import type { PageData } from './$types'; | ||||
| 	import empty1Url from '$lib/assets/empty-1.svg'; | ||||
|  | ||||
| 	export let data: PageData; | ||||
|  | ||||
| @@ -126,7 +127,7 @@ | ||||
| 				<div | ||||
| 					class="border dark:border-immich-dark-gray hover:bg-immich-primary/5 dark:hover:bg-immich-dark-primary/25 hover:cursor-pointer p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center" | ||||
| 				> | ||||
| 					<img src="/empty-1.svg" alt="Empty shared album" width="500" draggable="false" /> | ||||
| 					<img src={empty1Url} alt="Empty shared album" width="500" draggable="false" /> | ||||
|  | ||||
| 					<p class="text-center text-immich-text-gray-500 dark:text-immich-dark-fg"> | ||||
| 						Add favorites to quickly find your best pictures and videos | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import { error } from '@sveltejs/kit'; | ||||
| import { getThumbnailUrl } from '$lib/utils/asset-utils'; | ||||
| import { serverApi, ThumbnailFormat } from '@api'; | ||||
| import type { PageServerLoad } from './$types'; | ||||
| import featurePanelUrl from '$lib/assets/feature-panel.png'; | ||||
|  | ||||
| export const load: PageServerLoad = async ({ params, parent }) => { | ||||
| 	const { user } = await parent(); | ||||
| @@ -23,7 +24,7 @@ export const load: PageServerLoad = async ({ params, parent }) => { | ||||
| 				description: sharedLink.description || `${assetCount} shared photos & videos.`, | ||||
| 				imageUrl: assetId | ||||
| 					? getThumbnailUrl(assetId, ThumbnailFormat.Webp, sharedLink.key) | ||||
| 					: 'feature-panel.png' | ||||
| 					: featurePanelUrl | ||||
| 			}, | ||||
| 			user | ||||
| 		}; | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| 		notificationController, | ||||
| 		NotificationType | ||||
| 	} from '$lib/components/shared-components/notification/notification'; | ||||
| 	import empty2Url from '$lib/assets/empty-2.svg'; | ||||
|  | ||||
| 	export let data: PageData; | ||||
|  | ||||
| @@ -94,7 +95,7 @@ | ||||
| 				<div | ||||
| 					class="border dark:border-immich-dark-gray p-5 w-[50%] m-auto mt-10 bg-gray-50 dark:bg-immich-dark-gray rounded-3xl flex flex-col place-content-center place-items-center dark:text-immich-dark-fg" | ||||
| 				> | ||||
| 					<img src="/empty-2.svg" alt="Empty shared album" width="500" draggable="false" /> | ||||
| 					<img src={empty2Url} alt="Empty shared album" width="500" draggable="false" /> | ||||
| 					<p class="text-center text-immich-text-gray-500"> | ||||
| 						Create a shared album to share photos and videos with people in your network | ||||
| 					</p> | ||||
|   | ||||
| Before Width: | Height: | Size: 352 KiB | 
| Before Width: | Height: | Size: 113 KiB |