refactor: view shared link (#23766)

pull/23755/head^2
Jason Rasmussen 2025-11-10 12:21:26 +07:00 committed by GitHub
parent a4e65a7ea8
commit 45304f1211
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 74 additions and 76 deletions

@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import SharedLinkCopy from '$lib/components/sharedlinks-page/actions/shared-link-copy.svelte'; import SharedLinkCopy from '$lib/components/sharedlinks-page/actions/shared-link-copy.svelte';
import { handleViewSharedLinkQrCode } from '$lib/services/shared-link.service';
import { locale } from '$lib/stores/preferences.store'; import { locale } from '$lib/stores/preferences.store';
import type { AlbumResponseDto, SharedLinkResponseDto } from '@immich/sdk'; import type { AlbumResponseDto, SharedLinkResponseDto } from '@immich/sdk';
import { IconButton, Text } from '@immich/ui'; import { IconButton, Text } from '@immich/ui';
@ -10,10 +11,9 @@
type Props = { type Props = {
album: AlbumResponseDto; album: AlbumResponseDto;
sharedLink: SharedLinkResponseDto; sharedLink: SharedLinkResponseDto;
onViewQrCode: () => void;
}; };
const { album, sharedLink, onViewQrCode }: Props = $props(); const { album, sharedLink }: Props = $props();
const getShareProperties = () => const getShareProperties = () =>
[ [
@ -46,8 +46,8 @@
color="secondary" color="secondary"
variant="ghost" variant="ghost"
icon={mdiQrcode} icon={mdiQrcode}
onclick={onViewQrCode} onclick={() => handleViewSharedLinkQrCode(sharedLink)}
/> />
<SharedLinkCopy link={sharedLink} /> <SharedLinkCopy {sharedLink} />
</div> </div>
</div> </div>

@ -9,9 +9,9 @@
import { AppRoute } from '$lib/constants'; import { AppRoute } from '$lib/constants';
import AlbumEditModal from '$lib/modals/AlbumEditModal.svelte'; import AlbumEditModal from '$lib/modals/AlbumEditModal.svelte';
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte'; import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte'; import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { handleConfirmAlbumDelete, handleDownloadAlbum } from '$lib/services/album.service'; import { handleConfirmAlbumDelete, handleDownloadAlbum } from '$lib/services/album.service';
import { handleViewSharedLinkQrCode } from '$lib/services/shared-link.service';
import { import {
AlbumFilter, AlbumFilter,
AlbumGroupBy, AlbumGroupBy,
@ -23,7 +23,6 @@
} from '$lib/stores/preferences.store'; } from '$lib/stores/preferences.store';
import { user } from '$lib/stores/user.store'; import { user } from '$lib/stores/user.store';
import { userInteraction } from '$lib/stores/user.svelte'; import { userInteraction } from '$lib/stores/user.svelte';
import { makeSharedLinkUrl } from '$lib/utils';
import { getSelectedAlbumGroupOption, sortAlbums, stringToSortOrder, type AlbumGroup } from '$lib/utils/album-utils'; import { getSelectedAlbumGroupOption, sortAlbums, stringToSortOrder, type AlbumGroup } from '$lib/utils/album-utils';
import type { ContextMenuPosition } from '$lib/utils/context-menu'; import type { ContextMenuPosition } from '$lib/utils/context-menu';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
@ -259,7 +258,7 @@
const sharedLink = await modalManager.show(SharedLinkCreateModal, { albumId: selectedAlbum.id }); const sharedLink = await modalManager.show(SharedLinkCreateModal, { albumId: selectedAlbum.id });
if (sharedLink) { if (sharedLink) {
handleSharedLinkCreated(selectedAlbum); handleSharedLinkCreated(selectedAlbum);
await modalManager.show(QrCodeModal, { title: $t('view_link'), value: makeSharedLinkUrl(sharedLink) }); await handleViewSharedLinkQrCode(sharedLink);
} }
break; break;
} }

@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte'; import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { makeSharedLinkUrl } from '$lib/utils'; import { handleViewSharedLinkQrCode } from '$lib/services/shared-link.service';
import type { AssetResponseDto } from '@immich/sdk'; import type { AssetResponseDto } from '@immich/sdk';
import { IconButton, modalManager } from '@immich/ui'; import { IconButton, modalManager } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js'; import { mdiShareVariantOutline } from '@mdi/js';
@ -15,9 +14,8 @@
const handleClick = async () => { const handleClick = async () => {
const sharedLink = await modalManager.show(SharedLinkCreateModal, { assetIds: [asset.id] }); const sharedLink = await modalManager.show(SharedLinkCreateModal, { assetIds: [asset.id] });
if (sharedLink) { if (sharedLink) {
await modalManager.show(QrCodeModal, { title: $t('view_link'), value: makeSharedLinkUrl(sharedLink) }); await handleViewSharedLinkQrCode(sharedLink);
} }
}; };
</script> </script>

@ -1,25 +1,21 @@
<script lang="ts"> <script lang="ts">
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte'; import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { copyToClipboard, makeSharedLinkUrl } from '$lib/utils'; import { handleCopySharedLinkUrl } from '$lib/services/shared-link.service';
import type { SharedLinkResponseDto } from '@immich/sdk'; import type { SharedLinkResponseDto } from '@immich/sdk';
import { IconButton } from '@immich/ui'; import { IconButton } from '@immich/ui';
import { mdiContentCopy } from '@mdi/js'; import { mdiContentCopy } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
interface Props { interface Props {
link: SharedLinkResponseDto; sharedLink: SharedLinkResponseDto;
menuItem?: boolean; menuItem?: boolean;
} }
let { link, menuItem = false }: Props = $props(); let { sharedLink, menuItem = false }: Props = $props();
const handleCopy = async () => {
await copyToClipboard(makeSharedLinkUrl(link));
};
</script> </script>
{#if menuItem} {#if menuItem}
<MenuOption text={$t('copy_link')} icon={mdiContentCopy} onClick={handleCopy} /> <MenuOption text={$t('copy_link')} icon={mdiContentCopy} onClick={() => handleCopySharedLinkUrl(sharedLink)} />
{:else} {:else}
<IconButton <IconButton
color="secondary" color="secondary"
@ -27,6 +23,6 @@
variant="ghost" variant="ghost"
aria-label={$t('copy_link')} aria-label={$t('copy_link')}
icon={mdiContentCopy} icon={mdiContentCopy}
onclick={handleCopy} onclick={() => handleCopySharedLinkUrl(sharedLink)}
/> />
{/if} {/if}

@ -10,7 +10,7 @@ vi.mock('$lib/utils');
describe('ShareCover component', () => { describe('ShareCover component', () => {
it('renders an image when the shared link is an album', () => { it('renders an image when the shared link is an album', () => {
const component = render(ShareCover, { const component = render(ShareCover, {
link: sharedLinkFactory.build({ album: albumFactory.build({ albumName: '123' }) }), sharedLink: sharedLinkFactory.build({ album: albumFactory.build({ albumName: '123' }) }),
preload: false, preload: false,
class: 'text', class: 'text',
}); });
@ -23,7 +23,7 @@ describe('ShareCover component', () => {
it('renders an image when the shared link is an individual share', () => { it('renders an image when the shared link is an individual share', () => {
vi.mocked(getAssetThumbnailUrl).mockReturnValue('/asdf'); vi.mocked(getAssetThumbnailUrl).mockReturnValue('/asdf');
const component = render(ShareCover, { const component = render(ShareCover, {
link: sharedLinkFactory.build({ assets: [assetFactory.build({ id: 'someId' })] }), sharedLink: sharedLinkFactory.build({ assets: [assetFactory.build({ id: 'someId' })] }),
preload: false, preload: false,
class: 'text', class: 'text',
}); });
@ -37,7 +37,7 @@ describe('ShareCover component', () => {
it('renders an image when the shared link has no album or assets', () => { it('renders an image when the shared link has no album or assets', () => {
const component = render(ShareCover, { const component = render(ShareCover, {
link: sharedLinkFactory.build(), sharedLink: sharedLinkFactory.build(),
preload: false, preload: false,
class: 'text', class: 'text',
}); });
@ -48,9 +48,9 @@ describe('ShareCover component', () => {
}); });
it.skip('renders fallback image when asset is not resized', () => { 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, { render(ShareCover, {
link, sharedLink,
preload: false, preload: false,
}); });

@ -1,29 +1,29 @@
<script lang="ts"> <script lang="ts">
import type { SharedLinkResponseDto } from '@immich/sdk';
import AlbumCover from '$lib/components/album-page/album-cover.svelte'; import AlbumCover from '$lib/components/album-page/album-cover.svelte';
import NoCover from '$lib/components/sharedlinks-page/covers/no-cover.svelte';
import AssetCover from '$lib/components/sharedlinks-page/covers/asset-cover.svelte'; import AssetCover from '$lib/components/sharedlinks-page/covers/asset-cover.svelte';
import NoCover from '$lib/components/sharedlinks-page/covers/no-cover.svelte';
import { getAssetThumbnailUrl } from '$lib/utils'; import { getAssetThumbnailUrl } from '$lib/utils';
import type { SharedLinkResponseDto } from '@immich/sdk';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
interface Props { interface Props {
link: SharedLinkResponseDto; sharedLink: SharedLinkResponseDto;
preload?: boolean; preload?: boolean;
class?: string; class?: string;
} }
let { link, preload = false, class: className = '' }: Props = $props(); let { sharedLink, preload = false, class: className = '' }: Props = $props();
</script> </script>
<div class="relative shrink-0 size-24"> <div class="relative shrink-0 size-24">
{#if link?.album} {#if sharedLink?.album}
<AlbumCover album={link.album} class={className} {preload} /> <AlbumCover album={sharedLink.album} class={className} {preload} />
{:else if link.assets[0]} {:else if sharedLink.assets[0]}
<AssetCover <AssetCover
alt={$t('individual_share')} alt={$t('individual_share')}
class={className} class={className}
{preload} {preload}
src={getAssetThumbnailUrl(link.assets[0].id)} src={getAssetThumbnailUrl(sharedLink.assets[0].id)}
/> />
{:else} {:else}
<NoCover alt={$t('unnamed_share')} class={className} {preload} /> <NoCover alt={$t('unnamed_share')} class={className} {preload} />

@ -13,14 +13,14 @@
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
interface Props { interface Props {
link: SharedLinkResponseDto; sharedLink: SharedLinkResponseDto;
onDelete: () => void; onDelete: () => void;
} }
let { link, onDelete }: Props = $props(); let { sharedLink, onDelete }: Props = $props();
let now = DateTime.now(); 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); let isExpired = $derived(expiresAt ? now > expiresAt : false);
const getCountDownExpirationDate = (expiresAtDate: DateTime, now: DateTime) => { const getCountDownExpirationDate = (expiresAtDate: DateTime, now: DateTime) => {
@ -41,10 +41,10 @@
> >
<svelte:element <svelte:element
this={isExpired ? 'div' : 'a'} this={isExpired ? 'div' : 'a'}
href={isExpired ? undefined : `${AppRoute.SHARE}/${link.key}`} href={isExpired ? undefined : `${AppRoute.SHARE}/${sharedLink.key}`}
class="flex gap-4 w-full py-4" class="flex gap-4 w-full py-4"
> >
<ShareCover class="transition-all duration-300 hover:shadow-lg" {link} /> <ShareCover class="transition-all duration-300 hover:shadow-lg" {sharedLink} />
<div class="flex flex-col justify-between"> <div class="flex flex-col justify-between">
<div class="info-top"> <div class="info-top">
@ -62,34 +62,34 @@
<div class="text-sm pb-2"> <div class="text-sm pb-2">
<p class="flex place-items-center gap-2 text-primary break-all uppercase"> <p class="flex place-items-center gap-2 text-primary break-all uppercase">
{#if link.type === SharedLinkType.Album} {#if sharedLink.type === SharedLinkType.Album}
{link.album?.albumName} {sharedLink.album?.albumName}
{:else if link.type === SharedLinkType.Individual} {:else if sharedLink.type === SharedLinkType.Individual}
{$t('individual_share')} {$t('individual_share')}
{/if} {/if}
</p> </p>
<p class="text-sm">{link.description ?? ''}</p> <p class="text-sm">{sharedLink.description ?? ''}</p>
</div> </div>
</div> </div>
<div class="flex flex-wrap gap-2 text-xl"> <div class="flex flex-wrap gap-2 text-xl">
{#if link.allowUpload} {#if sharedLink.allowUpload}
<Badge rounded="full"><span class="text-xs px-1">{$t('upload')}</span></Badge> <Badge rounded="full"><span class="text-xs px-1">{$t('upload')}</span></Badge>
{/if} {/if}
{#if link.allowDownload} {#if sharedLink.allowDownload}
<Badge rounded="full"><span class="text-xs px-1">{$t('download')}</span></Badge> <Badge rounded="full"><span class="text-xs px-1">{$t('download')}</span></Badge>
{/if} {/if}
{#if link.showMetadata} {#if sharedLink.showMetadata}
<Badge rounded="full"><span class="uppercase text-xs px-1">{$t('exif')}</span></Badge> <Badge rounded="full"><span class="uppercase text-xs px-1">{$t('exif')}</span></Badge>
{/if} {/if}
{#if link.password} {#if sharedLink.password}
<Badge rounded="full"><span class="text-xs px-1">{$t('password')}</span></Badge> <Badge rounded="full"><span class="text-xs px-1">{$t('password')}</span></Badge>
{/if} {/if}
{#if link.slug} {#if sharedLink.slug}
<Badge rounded="full"><span class="text-xs px-1">{$t('custom_url')}</span></Badge> <Badge rounded="full"><span class="text-xs px-1">{$t('custom_url')}</span></Badge>
{/if} {/if}
</div> </div>
@ -97,8 +97,8 @@
</svelte:element> </svelte:element>
<div class="flex flex-auto flex-col place-content-center place-items-end text-end ms-4"> <div class="flex flex-auto flex-col place-content-center place-items-end text-end ms-4">
<div class="sm:flex hidden"> <div class="sm:flex hidden">
<SharedLinkEdit sharedLink={link} /> <SharedLinkEdit {sharedLink} />
<SharedLinkCopy {link} /> <SharedLinkCopy {sharedLink} />
<SharedLinkDelete {onDelete} /> <SharedLinkDelete {onDelete} />
</div> </div>
@ -110,8 +110,8 @@
size="large" size="large"
hideContent hideContent
> >
<SharedLinkEdit menuItem sharedLink={link} /> <SharedLinkEdit menuItem {sharedLink} />
<SharedLinkCopy menuItem {link} /> <SharedLinkCopy menuItem {sharedLink} />
<SharedLinkDelete menuItem {onDelete} /> <SharedLinkDelete menuItem {onDelete} />
</ButtonContextMenu> </ButtonContextMenu>
</div> </div>

@ -1,8 +1,7 @@
<script lang="ts"> <script lang="ts">
import { getAssetControlContext } from '$lib/components/timeline/AssetSelectControlBar.svelte'; import { getAssetControlContext } from '$lib/components/timeline/AssetSelectControlBar.svelte';
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte'; import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { makeSharedLinkUrl } from '$lib/utils'; import { handleViewSharedLinkQrCode } from '$lib/services/shared-link.service';
import { IconButton, modalManager } from '@immich/ui'; import { IconButton, modalManager } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js'; import { mdiShareVariantOutline } from '@mdi/js';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
@ -15,7 +14,7 @@
}); });
if (sharedLink) { if (sharedLink) {
await modalManager.show(QrCodeModal, { title: $t('view_link'), value: makeSharedLinkUrl(sharedLink) }); await handleViewSharedLinkQrCode(sharedLink);
} }
}; };
</script> </script>

@ -2,8 +2,6 @@
import AlbumSharedLink from '$lib/components/album-page/album-shared-link.svelte'; import AlbumSharedLink from '$lib/components/album-page/album-shared-link.svelte';
import { AppRoute } from '$lib/constants'; import { AppRoute } from '$lib/constants';
import Dropdown from '$lib/elements/Dropdown.svelte'; import Dropdown from '$lib/elements/Dropdown.svelte';
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
import { makeSharedLinkUrl } from '$lib/utils';
import { import {
AlbumUserRole, AlbumUserRole,
getAllSharedLinks, getAllSharedLinks,
@ -13,7 +11,7 @@
type SharedLinkResponseDto, type SharedLinkResponseDto,
type UserResponseDto, type UserResponseDto,
} from '@immich/sdk'; } 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 { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
@ -29,13 +27,6 @@
let users: UserResponseDto[] = $state([]); let users: UserResponseDto[] = $state([]);
let selectedUsers: Record<string, { user: UserResponseDto; role: AlbumUserRole }> = $state({}); let selectedUsers: Record<string, { user: UserResponseDto; role: AlbumUserRole }> = $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 }> = [ const roleOptions: Array<{ title: string; value: AlbumUserRole | 'none'; icon?: string }> = [
{ title: $t('role_editor'), value: AlbumUserRole.Editor, icon: mdiPencil }, { title: $t('role_editor'), value: AlbumUserRole.Editor, icon: mdiPencil },
{ title: $t('role_viewer'), value: AlbumUserRole.Viewer, icon: mdiEye }, { title: $t('role_viewer'), value: AlbumUserRole.Viewer, icon: mdiEye },
@ -174,7 +165,7 @@
<Stack gap={4}> <Stack gap={4}>
{#each sharedLinks as sharedLink (sharedLink.id)} {#each sharedLinks as sharedLink (sharedLink.id)}
<AlbumSharedLink {album} {sharedLink} onViewQrCode={() => handleViewQrCode(sharedLink)} /> <AlbumSharedLink {album} {sharedLink} />
{/each} {/each}
</Stack> </Stack>
{/if} {/if}

@ -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));
};

@ -1,7 +1,6 @@
import { defaultLang, langs, locales } from '$lib/constants'; import { defaultLang, langs, locales } from '$lib/constants';
import { authManager } from '$lib/managers/auth-manager.svelte'; import { authManager } from '$lib/managers/auth-manager.svelte';
import { lang } from '$lib/stores/preferences.store'; import { lang } from '$lib/stores/preferences.store';
import { serverConfig } from '$lib/stores/server-config.store';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
import { import {
AssetJobName, 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 = { export const oauth = {
isCallback: (location: Location) => { isCallback: (location: Location) => {
const search = location.search; const search = location.search;

@ -34,15 +34,15 @@
import AlbumOptionsModal from '$lib/modals/AlbumOptionsModal.svelte'; import AlbumOptionsModal from '$lib/modals/AlbumOptionsModal.svelte';
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte'; import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
import AlbumUsersModal from '$lib/modals/AlbumUsersModal.svelte'; import AlbumUsersModal from '$lib/modals/AlbumUsersModal.svelte';
import QrCodeModal from '$lib/modals/QrCodeModal.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte'; import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { handleConfirmAlbumDelete, handleDownloadAlbum } from '$lib/services/album.service'; 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 { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { assetViewingStore } from '$lib/stores/asset-viewing.store';
import { featureFlags } from '$lib/stores/server-config.store'; import { featureFlags } from '$lib/stores/server-config.store';
import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store';
import { preferences, user } from '$lib/stores/user.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 { cancelMultiselect } from '$lib/utils/asset-utils';
import { openFileUploadDialog } from '$lib/utils/file-uploader'; import { openFileUploadDialog } from '$lib/utils/file-uploader';
import { handleError } from '$lib/utils/handle-error'; import { handleError } from '$lib/utils/handle-error';
@ -388,7 +388,7 @@
const sharedLink = await modalManager.show(SharedLinkCreateModal, { albumId: album.id }); const sharedLink = await modalManager.show(SharedLinkCreateModal, { albumId: album.id });
if (sharedLink) { if (sharedLink) {
await refreshAlbum(); await refreshAlbum();
await modalManager.show(QrCodeModal, { title: $t('view_link'), value: makeSharedLinkUrl(sharedLink) }); await handleViewSharedLinkQrCode(sharedLink);
} }
}; };

@ -109,8 +109,8 @@
</div> </div>
{:else} {:else}
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
{#each filteredSharedLinks as link (link.id)} {#each filteredSharedLinks as sharedLink (sharedLink.id)}
<SharedLinkCard {link} onDelete={() => handleDeleteLink(link.id)} /> <SharedLinkCard {sharedLink} onDelete={() => handleDeleteLink(sharedLink.id)} />
{/each} {/each}
</div> </div>
{/if} {/if}