2022-06-03 11:04:30 -05:00
|
|
|
<script lang="ts">
|
2023-10-25 09:48:25 -04:00
|
|
|
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
2024-06-09 01:33:39 +05:30
|
|
|
import DeleteButton from './delete-button.svelte';
|
2024-02-14 08:09:49 -05:00
|
|
|
import { user } from '$lib/stores/user.store';
|
2023-08-25 18:20:45 -05:00
|
|
|
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
2024-02-14 08:09:49 -05:00
|
|
|
import { getAssetJobName } from '$lib/utils';
|
2024-05-23 20:26:22 -04:00
|
|
|
import { openFileUploadDialog } from '$lib/utils/file-uploader';
|
|
|
|
import { AssetJobName, AssetTypeEnum, type AlbumResponseDto, type AssetResponseDto } from '@immich/sdk';
|
2023-10-25 09:48:25 -04:00
|
|
|
import {
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiAccountCircleOutline,
|
2023-10-25 09:48:25 -04:00
|
|
|
mdiAlertOutline,
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiArchiveArrowDownOutline,
|
|
|
|
mdiArchiveArrowUpOutline,
|
2023-10-25 09:48:25 -04:00
|
|
|
mdiArrowLeft,
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiCogRefreshOutline,
|
2023-10-25 09:48:25 -04:00
|
|
|
mdiContentCopy,
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiDatabaseRefreshOutline,
|
2023-10-25 09:48:25 -04:00
|
|
|
mdiDotsVertical,
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiFolderDownloadOutline,
|
2023-10-25 09:48:25 -04:00
|
|
|
mdiHeart,
|
|
|
|
mdiHeartOutline,
|
2024-04-19 19:19:50 -06:00
|
|
|
mdiHistory,
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiImageAlbum,
|
|
|
|
mdiImageMinusOutline,
|
|
|
|
mdiImageOutline,
|
|
|
|
mdiImageRefreshOutline,
|
2023-10-25 09:48:25 -04:00
|
|
|
mdiInformationOutline,
|
|
|
|
mdiMagnifyMinusOutline,
|
|
|
|
mdiMagnifyPlusOutline,
|
|
|
|
mdiMotionPauseOutline,
|
2023-10-27 23:59:44 -05:00
|
|
|
mdiPlaySpeed,
|
2024-03-21 19:39:33 +01:00
|
|
|
mdiPresentationPlay,
|
2024-03-03 16:15:35 -05:00
|
|
|
mdiShareVariantOutline,
|
2024-05-23 20:26:22 -04:00
|
|
|
mdiUpload,
|
2023-10-25 09:48:25 -04:00
|
|
|
} from '@mdi/js';
|
2023-07-01 00:50:47 -04:00
|
|
|
import { createEventDispatcher } from 'svelte';
|
|
|
|
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
|
2024-06-04 21:53:00 +02:00
|
|
|
import { t } from 'svelte-i18n';
|
2024-06-18 03:52:38 +00:00
|
|
|
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
|
2022-11-08 11:20:36 -05:00
|
|
|
|
2023-07-01 00:50:47 -04:00
|
|
|
export let asset: AssetResponseDto;
|
2024-03-21 19:39:33 +01:00
|
|
|
export let album: AlbumResponseDto | null = null;
|
2023-07-01 00:50:47 -04:00
|
|
|
export let showCopyButton: boolean;
|
|
|
|
export let showZoomButton: boolean;
|
|
|
|
export let showMotionPlayButton: boolean;
|
|
|
|
export let isMotionPhotoPlaying = false;
|
|
|
|
export let showDownloadButton: boolean;
|
2023-10-14 03:46:30 +02:00
|
|
|
export let showDetailButton: boolean;
|
2024-03-03 16:15:35 -05:00
|
|
|
export let showShareButton: boolean;
|
2023-08-25 18:20:45 -05:00
|
|
|
export let showSlideshow = false;
|
2023-11-03 17:01:48 +03:00
|
|
|
export let hasStackChildren = false;
|
2024-06-07 14:22:46 -04:00
|
|
|
export let onZoomImage: () => void;
|
|
|
|
export let onCopyImage: () => void;
|
2022-11-08 11:20:36 -05:00
|
|
|
|
2024-05-24 19:59:19 +02:00
|
|
|
$: isOwner = $user && asset.ownerId === $user?.id;
|
2022-11-04 10:32:09 -04:00
|
|
|
|
2024-06-06 18:23:49 -05:00
|
|
|
type EventTypes = {
|
2023-12-15 03:54:21 +01:00
|
|
|
back: void;
|
2023-08-18 10:31:48 -04:00
|
|
|
stopMotionPhoto: void;
|
|
|
|
playMotionPhoto: void;
|
|
|
|
download: void;
|
|
|
|
showDetail: void;
|
|
|
|
favorite: void;
|
|
|
|
delete: void;
|
2024-06-09 01:33:39 +05:30
|
|
|
permanentlyDelete: void;
|
2023-08-18 10:31:48 -04:00
|
|
|
toggleArchive: void;
|
|
|
|
addToAlbum: void;
|
2024-04-19 19:19:50 -06:00
|
|
|
restoreAsset: void;
|
2023-08-18 10:31:48 -04:00
|
|
|
addToSharedAlbum: void;
|
|
|
|
asProfileImage: void;
|
2024-03-21 19:39:33 +01:00
|
|
|
setAsAlbumCover: void;
|
2023-08-18 10:31:48 -04:00
|
|
|
runJob: AssetJobName;
|
2023-08-25 18:20:45 -05:00
|
|
|
playSlideShow: void;
|
2023-10-27 15:34:01 -05:00
|
|
|
unstack: void;
|
2024-03-03 16:15:35 -05:00
|
|
|
showShareModal: void;
|
2024-06-06 18:23:49 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
const dispatch = createEventDispatcher<EventTypes>();
|
2022-11-04 10:32:09 -04:00
|
|
|
|
2023-08-18 10:31:48 -04:00
|
|
|
const onJobClick = (name: AssetJobName) => {
|
|
|
|
dispatch('runJob', name);
|
|
|
|
};
|
|
|
|
|
2024-06-06 18:23:49 -05:00
|
|
|
const onMenuClick = (eventName: keyof EventTypes) => {
|
2023-07-01 00:50:47 -04:00
|
|
|
dispatch(eventName);
|
|
|
|
};
|
2022-06-03 11:04:30 -05:00
|
|
|
</script>
|
|
|
|
|
2022-07-16 23:52:00 -05:00
|
|
|
<div
|
2023-07-18 13:19:39 -05:00
|
|
|
class="z-[1001] flex h-16 place-items-center justify-between bg-gradient-to-b from-black/40 px-3 transition-transform duration-200"
|
2022-07-16 23:52:00 -05:00
|
|
|
>
|
2023-07-01 00:50:47 -04:00
|
|
|
<div class="text-white">
|
2024-06-04 21:53:00 +02:00
|
|
|
<CircleIconButton color="opaque" icon={mdiArrowLeft} title={$t('go_back')} on:click={() => dispatch('back')} />
|
2023-07-01 00:50:47 -04:00
|
|
|
</div>
|
2024-05-24 19:59:19 +02:00
|
|
|
<div
|
|
|
|
class="flex w-[calc(100%-3rem)] justify-end gap-2 overflow-hidden text-white"
|
|
|
|
data-testid="asset-viewer-navbar-actions"
|
|
|
|
>
|
2024-03-03 16:15:35 -05:00
|
|
|
{#if showShareButton}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2024-03-03 16:15:35 -05:00
|
|
|
icon={mdiShareVariantOutline}
|
|
|
|
on:click={() => dispatch('showShareModal')}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('share')}
|
2024-03-03 16:15:35 -05:00
|
|
|
/>
|
|
|
|
{/if}
|
2023-09-20 13:16:33 +02:00
|
|
|
{#if asset.isOffline}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2023-10-25 09:48:25 -04:00
|
|
|
icon={mdiAlertOutline}
|
2023-09-20 13:16:33 +02:00
|
|
|
on:click={() => dispatch('showDetail')}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('asset_offline')}
|
2023-09-20 13:16:33 +02:00
|
|
|
/>
|
|
|
|
{/if}
|
2023-07-01 00:50:47 -04:00
|
|
|
{#if showMotionPlayButton}
|
|
|
|
{#if isMotionPhotoPlaying}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2023-10-25 09:48:25 -04:00
|
|
|
icon={mdiMotionPauseOutline}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('stop_motion_photo')}
|
2023-07-01 00:50:47 -04:00
|
|
|
on:click={() => dispatch('stopMotionPhoto')}
|
|
|
|
/>
|
|
|
|
{:else}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2023-10-27 23:59:44 -05:00
|
|
|
icon={mdiPlaySpeed}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('play_motion_photo')}
|
2023-07-01 00:50:47 -04:00
|
|
|
on:click={() => dispatch('playMotionPhoto')}
|
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
{/if}
|
|
|
|
{#if showZoomButton}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2023-07-01 00:50:47 -04:00
|
|
|
hideMobile={true}
|
2023-10-25 09:48:25 -04:00
|
|
|
icon={$photoZoomState && $photoZoomState.currentZoom > 1 ? mdiMagnifyMinusOutline : mdiMagnifyPlusOutline}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('zoom_image')}
|
2024-06-07 14:22:46 -04:00
|
|
|
on:click={onZoomImage}
|
2023-07-01 00:50:47 -04:00
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
{#if showCopyButton}
|
2024-06-07 14:22:46 -04:00
|
|
|
<CircleIconButton color="opaque" icon={mdiContentCopy} title={$t('copy_image')} on:click={onCopyImage} />
|
2023-07-01 00:50:47 -04:00
|
|
|
{/if}
|
2024-04-03 09:37:03 -05:00
|
|
|
|
|
|
|
{#if !isOwner && showDownloadButton}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2024-04-03 09:37:03 -05:00
|
|
|
icon={mdiFolderDownloadOutline}
|
|
|
|
on:click={() => dispatch('download')}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('download')}
|
2024-04-03 09:37:03 -05:00
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
|
2023-10-14 03:46:30 +02:00
|
|
|
{#if showDetailButton}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2023-10-25 09:48:25 -04:00
|
|
|
icon={mdiInformationOutline}
|
2023-10-14 03:46:30 +02:00
|
|
|
on:click={() => dispatch('showDetail')}
|
2024-06-04 21:53:00 +02:00
|
|
|
title={$t('info')}
|
2023-10-14 03:46:30 +02:00
|
|
|
/>
|
|
|
|
{/if}
|
2024-04-03 09:37:03 -05:00
|
|
|
|
2023-07-01 00:50:47 -04:00
|
|
|
{#if isOwner}
|
|
|
|
<CircleIconButton
|
2024-04-27 22:29:43 +00:00
|
|
|
color="opaque"
|
2023-10-25 09:48:25 -04:00
|
|
|
icon={asset.isFavorite ? mdiHeart : mdiHeartOutline}
|
2023-07-01 00:50:47 -04:00
|
|
|
on:click={() => dispatch('favorite')}
|
2024-06-12 13:13:10 +02:00
|
|
|
title={asset.isFavorite ? $t('unfavorite') : $t('to_favorite')}
|
2023-07-01 00:50:47 -04:00
|
|
|
/>
|
|
|
|
{/if}
|
2023-01-09 14:16:08 -06:00
|
|
|
|
2023-07-01 00:50:47 -04:00
|
|
|
{#if isOwner}
|
2024-06-09 01:33:39 +05:30
|
|
|
<DeleteButton
|
|
|
|
{asset}
|
|
|
|
on:delete={() => dispatch('delete')}
|
|
|
|
on:permanentlyDelete={() => dispatch('permanentlyDelete')}
|
2024-06-04 21:53:00 +02:00
|
|
|
/>
|
2024-06-18 03:52:38 +00:00
|
|
|
<ButtonContextMenu direction="left" align="top-right" color="opaque" title={$t('more')} icon={mdiDotsVertical}>
|
|
|
|
{#if showSlideshow}
|
2024-06-20 21:15:36 +00:00
|
|
|
<MenuOption icon={mdiPresentationPlay} onClick={() => onMenuClick('playSlideShow')} text={$t('slideshow')} />
|
2024-06-18 03:52:38 +00:00
|
|
|
{/if}
|
|
|
|
{#if showDownloadButton}
|
2024-06-20 21:15:36 +00:00
|
|
|
<MenuOption icon={mdiFolderDownloadOutline} onClick={() => onMenuClick('download')} text={$t('download')} />
|
2024-06-18 03:52:38 +00:00
|
|
|
{/if}
|
|
|
|
{#if asset.isTrashed}
|
2024-06-20 21:15:36 +00:00
|
|
|
<MenuOption icon={mdiHistory} onClick={() => onMenuClick('restoreAsset')} text={$t('restore')} />
|
2024-06-18 03:52:38 +00:00
|
|
|
{:else}
|
2024-06-20 21:15:36 +00:00
|
|
|
<MenuOption icon={mdiImageAlbum} onClick={() => onMenuClick('addToAlbum')} text={$t('add_to_album')} />
|
2024-06-18 03:52:38 +00:00
|
|
|
<MenuOption
|
|
|
|
icon={mdiShareVariantOutline}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onMenuClick('addToSharedAlbum')}
|
2024-06-18 03:52:38 +00:00
|
|
|
text={$t('add_to_shared_album')}
|
|
|
|
/>
|
|
|
|
{/if}
|
2023-05-26 09:11:10 -04:00
|
|
|
|
2024-06-18 03:52:38 +00:00
|
|
|
{#if isOwner}
|
|
|
|
{#if hasStackChildren}
|
2024-06-20 21:15:36 +00:00
|
|
|
<MenuOption icon={mdiImageMinusOutline} onClick={() => onMenuClick('unstack')} text={$t('unstack')} />
|
2024-06-18 03:52:38 +00:00
|
|
|
{/if}
|
|
|
|
{#if album}
|
|
|
|
<MenuOption
|
|
|
|
text={$t('set_as_album_cover')}
|
|
|
|
icon={mdiImageOutline}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onMenuClick('setAsAlbumCover')}
|
2024-06-18 03:52:38 +00:00
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
{#if asset.type === AssetTypeEnum.Image}
|
|
|
|
<MenuOption
|
|
|
|
icon={mdiAccountCircleOutline}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onMenuClick('asProfileImage')}
|
2024-06-18 03:52:38 +00:00
|
|
|
text={$t('set_as_profile_picture')}
|
|
|
|
/>
|
|
|
|
{/if}
|
|
|
|
<MenuOption
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onMenuClick('toggleArchive')}
|
2024-06-18 03:52:38 +00:00
|
|
|
icon={asset.isArchived ? mdiArchiveArrowUpOutline : mdiArchiveArrowDownOutline}
|
|
|
|
text={asset.isArchived ? $t('unarchive') : $t('to_archive')}
|
|
|
|
/>
|
|
|
|
<MenuOption
|
|
|
|
icon={mdiUpload}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => openFileUploadDialog({ multiple: false, assetId: asset.id })}
|
2024-06-18 03:52:38 +00:00
|
|
|
text={$t('replace_with_upload')}
|
|
|
|
/>
|
|
|
|
<hr />
|
|
|
|
<MenuOption
|
|
|
|
icon={mdiDatabaseRefreshOutline}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onJobClick(AssetJobName.RefreshMetadata)}
|
2024-06-18 03:52:38 +00:00
|
|
|
text={getAssetJobName(AssetJobName.RefreshMetadata)}
|
|
|
|
/>
|
|
|
|
<MenuOption
|
|
|
|
icon={mdiImageRefreshOutline}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onJobClick(AssetJobName.RegenerateThumbnail)}
|
2024-06-18 03:52:38 +00:00
|
|
|
text={getAssetJobName(AssetJobName.RegenerateThumbnail)}
|
|
|
|
/>
|
|
|
|
{#if asset.type === AssetTypeEnum.Video}
|
|
|
|
<MenuOption
|
|
|
|
icon={mdiCogRefreshOutline}
|
2024-06-20 21:15:36 +00:00
|
|
|
onClick={() => onJobClick(AssetJobName.TranscodeVideo)}
|
2024-06-18 03:52:38 +00:00
|
|
|
text={getAssetJobName(AssetJobName.TranscodeVideo)}
|
|
|
|
/>
|
|
|
|
{/if}
|
2023-08-18 10:31:48 -04:00
|
|
|
{/if}
|
2024-06-18 03:52:38 +00:00
|
|
|
</ButtonContextMenu>
|
2023-07-01 00:50:47 -04:00
|
|
|
{/if}
|
|
|
|
</div>
|
2022-06-03 11:04:30 -05:00
|
|
|
</div>
|