individual-shared-viewer.svelte 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <script lang="ts">
  2. import { goto } from '$app/navigation';
  3. import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader';
  4. import { downloadArchive } from '$lib/utils/asset-utils';
  5. import { api, AssetResponseDto, SharedLinkResponseDto } from '@api';
  6. import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store';
  7. import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
  8. import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte';
  9. import FolderDownloadOutline from 'svelte-material-icons/FolderDownloadOutline.svelte';
  10. import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
  11. import DownloadAction from '../photos-page/actions/download-action.svelte';
  12. import RemoveFromSharedLink from '../photos-page/actions/remove-from-shared-link.svelte';
  13. import AssetSelectControlBar from '../photos-page/asset-select-control-bar.svelte';
  14. import ControlAppBar from '../shared-components/control-app-bar.svelte';
  15. import GalleryViewer from '../shared-components/gallery-viewer/gallery-viewer.svelte';
  16. import SelectAll from 'svelte-material-icons/SelectAll.svelte';
  17. import ImmichLogo from '../shared-components/immich-logo.svelte';
  18. import { notificationController, NotificationType } from '../shared-components/notification/notification';
  19. import { handleError } from '../../utils/handle-error';
  20. export let sharedLink: SharedLinkResponseDto;
  21. export let isOwned: boolean;
  22. let selectedAssets: Set<AssetResponseDto> = new Set();
  23. $: assets = sharedLink.assets;
  24. $: isMultiSelectionMode = selectedAssets.size > 0;
  25. dragAndDropFilesStore.subscribe((value) => {
  26. if (value.isDragging && value.files.length > 0) {
  27. handleUploadAssets(value.files);
  28. dragAndDropFilesStore.set({ isDragging: false, files: [] });
  29. }
  30. });
  31. const downloadAssets = async () => {
  32. await downloadArchive(`immich-shared.zip`, { assetIds: assets.map((asset) => asset.id) }, sharedLink.key);
  33. };
  34. const handleUploadAssets = async (files: File[] = []) => {
  35. try {
  36. let results: (string | undefined)[] = [];
  37. if (!files || files.length === 0 || !Array.isArray(files)) {
  38. results = await openFileUploadDialog(undefined, sharedLink.key);
  39. } else {
  40. results = await fileUploadHandler(files, undefined, sharedLink.key);
  41. }
  42. const { data } = await api.sharedLinkApi.addSharedLinkAssets({
  43. id: sharedLink.id,
  44. assetIdsDto: {
  45. assetIds: results.filter((id) => !!id) as string[],
  46. },
  47. key: sharedLink.key,
  48. });
  49. const added = data.filter((item) => item.success).length;
  50. notificationController.show({
  51. message: `Added ${added} assets`,
  52. type: NotificationType.Info,
  53. });
  54. } catch (e) {
  55. handleError(e, 'Unable to add assets to shared link');
  56. }
  57. };
  58. const handleSelectAll = () => {
  59. selectedAssets = new Set(assets);
  60. };
  61. </script>
  62. <section class="bg-immich-bg dark:bg-immich-dark-bg">
  63. {#if isMultiSelectionMode}
  64. <AssetSelectControlBar assets={selectedAssets} clearSelect={() => (selectedAssets = new Set())}>
  65. <CircleIconButton title="Select all" logo={SelectAll} on:click={handleSelectAll} />
  66. {#if sharedLink?.allowDownload}
  67. <DownloadAction filename="immich-shared.zip" sharedLinkKey={sharedLink.key} />
  68. {/if}
  69. {#if isOwned}
  70. <RemoveFromSharedLink bind:sharedLink />
  71. {/if}
  72. </AssetSelectControlBar>
  73. {:else}
  74. <ControlAppBar on:close-button-click={() => goto('/photos')} backIcon={ArrowLeft} showBackButton={false}>
  75. <svelte:fragment slot="leading">
  76. <a
  77. data-sveltekit-preload-data="hover"
  78. class="flex gap-2 place-items-center hover:cursor-pointer ml-6"
  79. href="https://immich.app"
  80. >
  81. <ImmichLogo height="30" width="30" />
  82. <h1 class="font-immich-title text-lg text-immich-primary dark:text-immich-dark-primary">IMMICH</h1>
  83. </a>
  84. </svelte:fragment>
  85. <svelte:fragment slot="trailing">
  86. {#if sharedLink?.allowUpload}
  87. <CircleIconButton title="Add Photos" on:click={() => handleUploadAssets()} logo={FileImagePlusOutline} />
  88. {/if}
  89. {#if sharedLink?.allowDownload}
  90. <CircleIconButton title="Download" on:click={downloadAssets} logo={FolderDownloadOutline} />
  91. {/if}
  92. </svelte:fragment>
  93. </ControlAppBar>
  94. {/if}
  95. <section class="flex flex-col my-[160px] px-6 sm:px-12 md:px-24 lg:px-40">
  96. <GalleryViewer {assets} {sharedLink} bind:selectedAssets viewFrom="shared-link-page" />
  97. </section>
  98. </section>