diff --git a/web/src/lib/components/album-page/album-shared-link.svelte b/web/src/lib/components/album-page/album-shared-link.svelte index e7d6503da3..935fa7837c 100644 --- a/web/src/lib/components/album-page/album-shared-link.svelte +++ b/web/src/lib/components/album-page/album-shared-link.svelte @@ -1,5 +1,6 @@ diff --git a/web/src/lib/components/sharedlinks-page/actions/shared-link-copy.svelte b/web/src/lib/components/sharedlinks-page/actions/shared-link-copy.svelte index 235048d35d..06369e7792 100644 --- a/web/src/lib/components/sharedlinks-page/actions/shared-link-copy.svelte +++ b/web/src/lib/components/sharedlinks-page/actions/shared-link-copy.svelte @@ -1,25 +1,21 @@ {#if menuItem} - + handleCopySharedLinkUrl(sharedLink)} /> {:else} handleCopySharedLinkUrl(sharedLink)} /> {/if} diff --git a/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts b/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts index 76de04ea31..3b8d90f1ba 100644 --- a/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts +++ b/web/src/lib/components/sharedlinks-page/covers/__tests__/share-cover.spec.ts @@ -10,7 +10,7 @@ vi.mock('$lib/utils'); describe('ShareCover component', () => { it('renders an image when the shared link is an album', () => { const component = render(ShareCover, { - link: sharedLinkFactory.build({ album: albumFactory.build({ albumName: '123' }) }), + sharedLink: sharedLinkFactory.build({ album: albumFactory.build({ albumName: '123' }) }), preload: false, class: 'text', }); @@ -23,7 +23,7 @@ describe('ShareCover component', () => { it('renders an image when the shared link is an individual share', () => { vi.mocked(getAssetThumbnailUrl).mockReturnValue('/asdf'); const component = render(ShareCover, { - link: sharedLinkFactory.build({ assets: [assetFactory.build({ id: 'someId' })] }), + sharedLink: sharedLinkFactory.build({ assets: [assetFactory.build({ id: 'someId' })] }), preload: false, class: 'text', }); @@ -37,7 +37,7 @@ describe('ShareCover component', () => { it('renders an image when the shared link has no album or assets', () => { const component = render(ShareCover, { - link: sharedLinkFactory.build(), + sharedLink: sharedLinkFactory.build(), preload: false, class: 'text', }); @@ -48,9 +48,9 @@ describe('ShareCover component', () => { }); it.skip('renders fallback image when asset is not resized', () => { - const link = sharedLinkFactory.build({ assets: [assetFactory.build()] }); + const sharedLink = sharedLinkFactory.build({ assets: [assetFactory.build()] }); render(ShareCover, { - link, + sharedLink, preload: false, }); diff --git a/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte b/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte index 6f15cca45f..ec3deb9943 100644 --- a/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte +++ b/web/src/lib/components/sharedlinks-page/covers/share-cover.svelte @@ -1,29 +1,29 @@
- {#if link?.album} - - {:else if link.assets[0]} + {#if sharedLink?.album} + + {:else if sharedLink.assets[0]} {:else} diff --git a/web/src/lib/components/sharedlinks-page/shared-link-card.svelte b/web/src/lib/components/sharedlinks-page/shared-link-card.svelte index 33842e3f74..f811f60e77 100644 --- a/web/src/lib/components/sharedlinks-page/shared-link-card.svelte +++ b/web/src/lib/components/sharedlinks-page/shared-link-card.svelte @@ -13,14 +13,14 @@ import { t } from 'svelte-i18n'; interface Props { - link: SharedLinkResponseDto; + sharedLink: SharedLinkResponseDto; onDelete: () => void; } - let { link, onDelete }: Props = $props(); + let { sharedLink, onDelete }: Props = $props(); let now = DateTime.now(); - let expiresAt = $derived(link.expiresAt ? DateTime.fromISO(link.expiresAt) : undefined); + let expiresAt = $derived(sharedLink.expiresAt ? DateTime.fromISO(sharedLink.expiresAt) : undefined); let isExpired = $derived(expiresAt ? now > expiresAt : false); const getCountDownExpirationDate = (expiresAtDate: DateTime, now: DateTime) => { @@ -41,10 +41,10 @@ > - +
@@ -62,34 +62,34 @@

- {#if link.type === SharedLinkType.Album} - {link.album?.albumName} - {:else if link.type === SharedLinkType.Individual} + {#if sharedLink.type === SharedLinkType.Album} + {sharedLink.album?.albumName} + {:else if sharedLink.type === SharedLinkType.Individual} {$t('individual_share')} {/if}

-

{link.description ?? ''}

+

{sharedLink.description ?? ''}

- {#if link.allowUpload} + {#if sharedLink.allowUpload} {$t('upload')} {/if} - {#if link.allowDownload} + {#if sharedLink.allowDownload} {$t('download')} {/if} - {#if link.showMetadata} + {#if sharedLink.showMetadata} {$t('exif')} {/if} - {#if link.password} + {#if sharedLink.password} {$t('password')} {/if} - {#if link.slug} + {#if sharedLink.slug} {$t('custom_url')} {/if}
@@ -97,8 +97,8 @@
@@ -110,8 +110,8 @@ size="large" hideContent > - - + +
diff --git a/web/src/lib/components/timeline/actions/CreateSharedLinkAction.svelte b/web/src/lib/components/timeline/actions/CreateSharedLinkAction.svelte index 515fa64af1..06291e2188 100644 --- a/web/src/lib/components/timeline/actions/CreateSharedLinkAction.svelte +++ b/web/src/lib/components/timeline/actions/CreateSharedLinkAction.svelte @@ -1,8 +1,7 @@ diff --git a/web/src/lib/modals/AlbumShareModal.svelte b/web/src/lib/modals/AlbumShareModal.svelte index 9a60c0f710..8a4995efc4 100644 --- a/web/src/lib/modals/AlbumShareModal.svelte +++ b/web/src/lib/modals/AlbumShareModal.svelte @@ -2,8 +2,6 @@ import AlbumSharedLink from '$lib/components/album-page/album-shared-link.svelte'; import { AppRoute } from '$lib/constants'; import Dropdown from '$lib/elements/Dropdown.svelte'; - import QrCodeModal from '$lib/modals/QrCodeModal.svelte'; - import { makeSharedLinkUrl } from '$lib/utils'; import { AlbumUserRole, getAllSharedLinks, @@ -13,7 +11,7 @@ type SharedLinkResponseDto, type UserResponseDto, } from '@immich/sdk'; - import { Button, Icon, Link, Modal, ModalBody, modalManager, Stack, Text } from '@immich/ui'; + import { Button, Icon, Link, Modal, ModalBody, Stack, Text } from '@immich/ui'; import { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js'; import { onMount } from 'svelte'; import { t } from 'svelte-i18n'; @@ -29,13 +27,6 @@ let users: UserResponseDto[] = $state([]); let selectedUsers: Record = $state({}); - const handleViewQrCode = async (sharedLink: SharedLinkResponseDto) => { - await modalManager.show(QrCodeModal, { - title: $t('view_link'), - value: makeSharedLinkUrl(sharedLink), - }); - }; - const roleOptions: Array<{ title: string; value: AlbumUserRole | 'none'; icon?: string }> = [ { title: $t('role_editor'), value: AlbumUserRole.Editor, icon: mdiPencil }, { title: $t('role_viewer'), value: AlbumUserRole.Viewer, icon: mdiEye }, @@ -174,7 +165,7 @@ {#each sharedLinks as sharedLink (sharedLink.id)} - handleViewQrCode(sharedLink)} /> + {/each} {/if} diff --git a/web/src/lib/services/shared-link.service.ts b/web/src/lib/services/shared-link.service.ts new file mode 100644 index 0000000000..35bde6784f --- /dev/null +++ b/web/src/lib/services/shared-link.service.ts @@ -0,0 +1,21 @@ +import QrCodeModal from '$lib/modals/QrCodeModal.svelte'; +import { serverConfig } from '$lib/stores/server-config.store'; +import { copyToClipboard } from '$lib/utils'; +import { getFormatter } from '$lib/utils/i18n'; +import type { SharedLinkResponseDto } from '@immich/sdk'; +import { modalManager } from '@immich/ui'; +import { get } from 'svelte/store'; + +const makeSharedLinkUrl = (sharedLink: SharedLinkResponseDto) => { + const path = sharedLink.slug ? `s/${sharedLink.slug}` : `share/${sharedLink.key}`; + return new URL(path, get(serverConfig).externalDomain || globalThis.location.origin).href; +}; + +export const handleViewSharedLinkQrCode = async (sharedLink: SharedLinkResponseDto) => { + const $t = await getFormatter(); + await modalManager.show(QrCodeModal, { title: $t('view_link'), value: makeSharedLinkUrl(sharedLink) }); +}; + +export const handleCopySharedLinkUrl = async (sharedLink: SharedLinkResponseDto) => { + await copyToClipboard(makeSharedLinkUrl(sharedLink)); +}; diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index 3f2d945f39..65510352c1 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -1,7 +1,6 @@ import { defaultLang, langs, locales } from '$lib/constants'; import { authManager } from '$lib/managers/auth-manager.svelte'; import { lang } from '$lib/stores/preferences.store'; -import { serverConfig } from '$lib/stores/server-config.store'; import { handleError } from '$lib/utils/handle-error'; import { AssetJobName, @@ -269,11 +268,6 @@ export const copyToClipboard = async (secret: string) => { } }; -export const makeSharedLinkUrl = (sharedLink: SharedLinkResponseDto) => { - const path = sharedLink.slug ? `s/${sharedLink.slug}` : `share/${sharedLink.key}`; - return new URL(path, get(serverConfig).externalDomain || globalThis.location.origin).href; -}; - export const oauth = { isCallback: (location: Location) => { const search = location.search; diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 34f3240e84..1c8a6ccfa0 100644 --- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -34,15 +34,15 @@ import AlbumOptionsModal from '$lib/modals/AlbumOptionsModal.svelte'; import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte'; import AlbumUsersModal from '$lib/modals/AlbumUsersModal.svelte'; - import QrCodeModal from '$lib/modals/QrCodeModal.svelte'; import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte'; import { handleConfirmAlbumDelete, handleDownloadAlbum } from '$lib/services/album.service'; + import { handleViewSharedLinkQrCode } from '$lib/services/shared-link.service'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { featureFlags } from '$lib/stores/server-config.store'; import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; import { preferences, user } from '$lib/stores/user.store'; - import { handlePromiseError, makeSharedLinkUrl } from '$lib/utils'; + import { handlePromiseError } from '$lib/utils'; import { cancelMultiselect } from '$lib/utils/asset-utils'; import { openFileUploadDialog } from '$lib/utils/file-uploader'; import { handleError } from '$lib/utils/handle-error'; @@ -388,7 +388,7 @@ const sharedLink = await modalManager.show(SharedLinkCreateModal, { albumId: album.id }); if (sharedLink) { await refreshAlbum(); - await modalManager.show(QrCodeModal, { title: $t('view_link'), value: makeSharedLinkUrl(sharedLink) }); + await handleViewSharedLinkQrCode(sharedLink); } }; diff --git a/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte b/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte index 02f230d609..2aa24a57ba 100644 --- a/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte +++ b/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte @@ -109,8 +109,8 @@
{:else}
- {#each filteredSharedLinks as link (link.id)} - handleDeleteLink(link.id)} /> + {#each filteredSharedLinks as sharedLink (sharedLink.id)} + handleDeleteLink(sharedLink.id)} /> {/each}
{/if}