fix: shared-link-mapper (#24794)

This commit is contained in:
Jason Rasmussen
2026-01-05 10:03:35 -05:00
committed by GitHub
parent b7bb118c00
commit e4311da1a4
11 changed files with 152 additions and 304 deletions

View File

@@ -13,8 +13,8 @@
AlbumGroupBy,
AlbumSortBy,
AlbumViewMode,
SortOrder,
locale,
SortOrder,
type AlbumViewSettings,
} from '$lib/stores/preferences.store';
import { user } from '$lib/stores/user.store';
@@ -23,7 +23,12 @@
import type { ContextMenuPosition } from '$lib/utils/context-menu';
import { handleError } from '$lib/utils/handle-error';
import { normalizeSearchString } from '$lib/utils/string-utils';
import { addUsersToAlbum, type AlbumResponseDto, type AlbumUserAddDto } from '@immich/sdk';
import {
addUsersToAlbum,
type AlbumResponseDto,
type AlbumUserAddDto,
type SharedLinkResponseDto,
} from '@immich/sdk';
import { modalManager } from '@immich/ui';
import { mdiDeleteOutline, mdiDownload, mdiRenameOutline, mdiShareVariantOutline } from '@mdi/js';
import { groupBy } from 'lodash-es';
@@ -208,12 +213,7 @@
}
case 'sharedLink': {
const success = await modalManager.show(SharedLinkCreateModal, { albumId: selectedAlbum.id });
if (success) {
selectedAlbum.shared = true;
selectedAlbum.hasSharedLink = true;
onUpdate(selectedAlbum);
}
await modalManager.show(SharedLinkCreateModal, { albumId: selectedAlbum.id });
break;
}
}
@@ -274,9 +274,15 @@
ownedAlbums = ownedAlbums.filter(({ id }) => id !== album.id);
sharedAlbums = sharedAlbums.filter(({ id }) => id !== album.id);
};
const onSharedLinkCreate = (sharedLink: SharedLinkResponseDto) => {
if (sharedLink.album) {
onUpdate(sharedLink.album);
}
};
</script>
<OnEvents {onAlbumUpdate} {onAlbumDelete} />
<OnEvents {onAlbumUpdate} {onAlbumDelete} {onSharedLinkCreate} />
{#if albums.length > 0}
{#if userSettings.view === AlbumViewMode.Cover}

View File

@@ -1,26 +0,0 @@
<script lang="ts">
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import type { AssetResponseDto } from '@immich/sdk';
import { IconButton, modalManager } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
interface Props {
asset: AssetResponseDto;
}
let { asset }: Props = $props();
const handleClick = async () => {
await modalManager.show(SharedLinkCreateModal, { assetIds: [asset.id] });
};
</script>
<IconButton
color="secondary"
shape="round"
variant="ghost"
icon={mdiShareVariantOutline}
onclick={handleClick}
aria-label={$t('share')}
/>

View File

@@ -2,6 +2,7 @@
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import CastButton from '$lib/cast/cast-button.svelte';
import ActionButton from '$lib/components/ActionButton.svelte';
import type { OnAction, PreAction } from '$lib/components/asset-viewer/actions/action';
import AddToAlbumAction from '$lib/components/asset-viewer/actions/add-to-album-action.svelte';
import AddToStackAction from '$lib/components/asset-viewer/actions/add-to-stack-action.svelte';
@@ -18,14 +19,13 @@
import SetProfilePictureAction from '$lib/components/asset-viewer/actions/set-profile-picture-action.svelte';
import SetStackPrimaryAsset from '$lib/components/asset-viewer/actions/set-stack-primary-asset.svelte';
import SetVisibilityAction from '$lib/components/asset-viewer/actions/set-visibility-action.svelte';
import ShareAction from '$lib/components/asset-viewer/actions/share-action.svelte';
import ShowDetailAction from '$lib/components/asset-viewer/actions/show-detail-action.svelte';
import UnstackAction from '$lib/components/asset-viewer/actions/unstack-action.svelte';
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
import { AppRoute } from '$lib/constants';
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
import { handleReplaceAsset } from '$lib/services/asset.service';
import { getAssetActions, handleReplaceAsset } from '$lib/services/asset.service';
import { photoViewerImgElement } from '$lib/stores/assets-store.svelte';
import { user } from '$lib/stores/user.store';
import { photoZoomState } from '$lib/stores/zoom-image.store';
@@ -113,6 +113,8 @@
let isLocked = $derived(asset.visibility === AssetVisibility.Locked);
let smartSearchEnabled = $derived(featureFlagsManager.value.smartSearch);
const { Share } = $derived(getAssetActions($t, asset));
// $: showEditorButton =
// isOwner &&
// asset.type === AssetTypeEnum.Image &&
@@ -135,9 +137,7 @@
<div class="flex gap-2 overflow-x-auto dark" data-testid="asset-viewer-navbar-actions">
<CastButton />
{#if !asset.isTrashed && $user && !isLocked}
<ShareAction {asset} />
{/if}
<ActionButton action={Share} />
{#if asset.isOffline}
<IconButton
shape="round"

View File

@@ -7,12 +7,12 @@
import { t } from 'svelte-i18n';
interface Props {
onClose: (success?: boolean) => void;
onClose: () => void;
albumId?: string;
assetIds?: string[];
}
let { onClose, albumId = $bindable(), assetIds = $bindable([]) }: Props = $props();
let { onClose, albumId, assetIds }: Props = $props();
let description = $state('');
let allowDownload = $state(true);
@@ -44,7 +44,7 @@
slug,
});
if (success) {
onClose(true);
onClose();
}
};
</script>

View File

@@ -1,6 +1,23 @@
import { eventManager } from '$lib/managers/event-manager.svelte';
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
import { user as authUser } from '$lib/stores/user.store';
import { openFileUploadDialog } from '$lib/utils/file-uploader';
import { copyAsset, deleteAssets } from '@immich/sdk';
import { AssetVisibility, copyAsset, deleteAssets, type AssetResponseDto } from '@immich/sdk';
import { modalManager, type ActionItem } from '@immich/ui';
import { mdiShareVariantOutline } from '@mdi/js';
import type { MessageFormatter } from 'svelte-i18n';
import { get } from 'svelte/store';
export const getAssetActions = ($t: MessageFormatter, asset: AssetResponseDto) => {
const Share: ActionItem = {
title: $t('share'),
icon: mdiShareVariantOutline,
$if: () => !!(get(authUser) && !asset.isTrashed && asset.visibility !== AssetVisibility.Locked),
onAction: () => modalManager.show(SharedLinkCreateModal, { assetIds: [asset.id] }),
};
return { Share };
};
export const handleReplaceAsset = async (oldAssetId: string) => {
const [newAssetId] = await openFileUploadDialog({ multiple: false });

View File

@@ -9,6 +9,7 @@ import { handleError } from '$lib/utils/handle-error';
import { getFormatter } from '$lib/utils/i18n';
import {
createSharedLink,
getSharedLinkById,
removeSharedLink,
removeSharedLinkAssets,
updateSharedLink,
@@ -58,7 +59,11 @@ export const handleCreateSharedLink = async (dto: SharedLinkCreateDto) => {
const $t = await getFormatter();
try {
const sharedLink = await createSharedLink({ sharedLinkCreateDto: dto });
let sharedLink = await createSharedLink({ sharedLinkCreateDto: dto });
if (dto.albumId) {
// fetch album details, for event
sharedLink = await getSharedLinkById({ id: sharedLink.id });
}
eventManager.emit('SharedLinkCreate', sharedLink);