mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
feat(web/server) Add more options to public shared link (#1348)
* Added migration files * Added logic for shared album level * Added permission for EXIF * Update shared link response dto * Added condition to show download button * Create and edit link with new parameter: * Remove deadcode * PR feedback * More refactor * Move logic of allow original file to service * Simplify * Wording
This commit is contained in:
parent
4cfac47674
commit
b07891089f
41 changed files with 520 additions and 73 deletions
|
|
@ -320,6 +320,7 @@
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
$downloadAssets = {};
|
||||
console.error('Error downloading file ', e);
|
||||
notificationController.show({
|
||||
type: NotificationType.Error,
|
||||
|
|
@ -460,11 +461,13 @@
|
|||
<CircleIconButton title="Remove album" on:click={removeAlbum} logo={DeleteOutline} />
|
||||
{/if}
|
||||
|
||||
<CircleIconButton
|
||||
title="Download"
|
||||
on:click={() => downloadAlbum()}
|
||||
logo={FolderDownloadOutline}
|
||||
/>
|
||||
{#if !isPublicShared || (isPublicShared && sharedLink?.allowDownload)}
|
||||
<CircleIconButton
|
||||
title="Download"
|
||||
on:click={() => downloadAlbum()}
|
||||
logo={FolderDownloadOutline}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if !isPublicShared}
|
||||
<CircleIconButton
|
||||
|
|
@ -534,11 +537,7 @@
|
|||
{/if}
|
||||
|
||||
{#if album.assetCount > 0}
|
||||
<GalleryViewer
|
||||
assets={album.assets}
|
||||
key={sharedLink?.key ?? ''}
|
||||
bind:selectedAssets={multiSelectAsset}
|
||||
/>
|
||||
<GalleryViewer assets={album.assets} {sharedLink} bind:selectedAssets={multiSelectAsset} />
|
||||
{:else}
|
||||
<!-- Album is empty - Show asset selectection buttons -->
|
||||
<section id="empty-album" class=" mt-[200px] flex place-content-center place-items-center">
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
export let showCopyButton: boolean;
|
||||
export let showMotionPlayButton: boolean;
|
||||
export let isMotionPhotoPlaying = false;
|
||||
export let showDownloadButton: boolean;
|
||||
|
||||
const isOwner = asset.ownerId === $page.data.user?.id;
|
||||
|
||||
|
|
@ -77,11 +78,14 @@
|
|||
}}
|
||||
/>
|
||||
{/if}
|
||||
<CircleIconButton
|
||||
logo={CloudDownloadOutline}
|
||||
on:click={() => dispatch('download')}
|
||||
title="Download"
|
||||
/>
|
||||
|
||||
{#if showDownloadButton}
|
||||
<CircleIconButton
|
||||
logo={CloudDownloadOutline}
|
||||
on:click={() => dispatch('download')}
|
||||
title="Download"
|
||||
/>
|
||||
{/if}
|
||||
<CircleIconButton
|
||||
logo={InformationOutline}
|
||||
on:click={() => dispatch('showDetail')}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,13 @@
|
|||
import { downloadAssets } from '$lib/stores/download';
|
||||
import VideoViewer from './video-viewer.svelte';
|
||||
import AlbumSelectionModal from '../shared-components/album-selection-modal.svelte';
|
||||
import { api, AssetResponseDto, AssetTypeEnum, AlbumResponseDto } from '@api';
|
||||
import {
|
||||
api,
|
||||
AssetResponseDto,
|
||||
AssetTypeEnum,
|
||||
AlbumResponseDto,
|
||||
SharedLinkResponseDto
|
||||
} from '@api';
|
||||
import {
|
||||
notificationController,
|
||||
NotificationType
|
||||
|
|
@ -22,6 +28,7 @@
|
|||
export let asset: AssetResponseDto;
|
||||
export let publicSharedKey = '';
|
||||
export let showNavigation = true;
|
||||
export let sharedLink: SharedLinkResponseDto | undefined = undefined;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
let halfLeftHover = false;
|
||||
|
|
@ -31,6 +38,7 @@
|
|||
let isShowAlbumPicker = false;
|
||||
let addToSharedAlbum = true;
|
||||
let shouldPlayMotionPhoto = false;
|
||||
let shouldShowDownloadButton = sharedLink ? sharedLink.allowDownload : true;
|
||||
const onKeyboardPress = (keyInfo: KeyboardEvent) => handleKeyboardPress(keyInfo.key);
|
||||
|
||||
onMount(async () => {
|
||||
|
|
@ -166,6 +174,7 @@
|
|||
}, 2000);
|
||||
}
|
||||
} catch (e) {
|
||||
$downloadAssets = {};
|
||||
console.error('Error downloading file ', e);
|
||||
notificationController.show({
|
||||
type: NotificationType.Error,
|
||||
|
|
@ -247,6 +256,7 @@
|
|||
isMotionPhotoPlaying={shouldPlayMotionPhoto}
|
||||
showCopyButton={asset.type === AssetTypeEnum.Image}
|
||||
showMotionPlayButton={!!asset.livePhotoVideoId}
|
||||
showDownloadButton={shouldShowDownloadButton}
|
||||
on:goBack={closeViewer}
|
||||
on:showDetail={showDetailInfoHandler}
|
||||
on:download={handleDownload}
|
||||
|
|
|
|||
|
|
@ -136,15 +136,17 @@
|
|||
/>
|
||||
{/if}
|
||||
|
||||
<CircleIconButton
|
||||
title="Download"
|
||||
on:click={() => downloadAssets(true)}
|
||||
logo={FolderDownloadOutline}
|
||||
/>
|
||||
{#if sharedLink?.allowDownload}
|
||||
<CircleIconButton
|
||||
title="Download"
|
||||
on:click={() => downloadAssets(true)}
|
||||
logo={FolderDownloadOutline}
|
||||
/>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</ControlAppBar>
|
||||
{/if}
|
||||
<section class="flex flex-col my-[160px] px-6 sm:px-12 md:px-24 lg:px-40">
|
||||
<GalleryViewer {assets} key={sharedLink.key} bind:selectedAssets />
|
||||
<GalleryViewer {assets} {sharedLink} bind:selectedAssets />
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
<div
|
||||
use:clickOutside
|
||||
on:outclick={() => dispatch('close')}
|
||||
class="bg-immich-bg dark:bg-immich-dark-gray dark:text-immich-dark-fg w-[450px] min-h-[200px] max-h-[500px] rounded-lg shadow-md"
|
||||
class="bg-immich-bg dark:bg-immich-dark-gray dark:text-immich-dark-fg w-[450px] min-h-[200px] max-h-[600px] rounded-lg shadow-md"
|
||||
>
|
||||
<div class="flex justify-between place-items-center px-5 py-3">
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
let sharedLink = '';
|
||||
let description = '';
|
||||
let shouldChangeExpirationTime = false;
|
||||
let isAllowDownload = true;
|
||||
let shouldShowExif = true;
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
const expiredDateOption: ImmichDropDownOption = {
|
||||
|
|
@ -42,6 +44,8 @@
|
|||
description = editingLink.description;
|
||||
}
|
||||
isAllowUpload = editingLink.allowUpload;
|
||||
isAllowDownload = editingLink.allowDownload;
|
||||
shouldShowExif = editingLink.showExif;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -58,7 +62,9 @@
|
|||
albumId: album.id,
|
||||
expiredAt: expirationDate,
|
||||
allowUpload: isAllowUpload,
|
||||
description: description
|
||||
description: description,
|
||||
allowDownload: isAllowDownload,
|
||||
showExif: shouldShowExif
|
||||
});
|
||||
buildSharedLink(data);
|
||||
} else {
|
||||
|
|
@ -66,7 +72,9 @@
|
|||
assetIds: sharedAssets.map((a) => a.id),
|
||||
expiredAt: expirationDate,
|
||||
allowUpload: isAllowUpload,
|
||||
description: description
|
||||
description: description,
|
||||
allowDownload: isAllowDownload,
|
||||
showExif: shouldShowExif
|
||||
});
|
||||
buildSharedLink(data);
|
||||
}
|
||||
|
|
@ -132,7 +140,9 @@
|
|||
description: description,
|
||||
expiredAt: expirationDate,
|
||||
allowUpload: isAllowUpload,
|
||||
isEditExpireTime: shouldChangeExpirationTime
|
||||
isEditExpireTime: shouldChangeExpirationTime,
|
||||
allowDownload: isAllowDownload,
|
||||
showExif: shouldShowExif
|
||||
});
|
||||
|
||||
notificationController.show({
|
||||
|
|
@ -185,12 +195,12 @@
|
|||
{/if}
|
||||
{/if}
|
||||
|
||||
<div class="mt-6 mb-2">
|
||||
<div class="mt-4 mb-2">
|
||||
<p class="text-xs">LINK OPTIONS</p>
|
||||
</div>
|
||||
<div class="p-4 bg-gray-100 dark:bg-black/40 rounded-lg">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-4">
|
||||
<div class="mb-2">
|
||||
<SettingInputField
|
||||
inputType={SettingInputFieldType.TEXT}
|
||||
label="Description"
|
||||
|
|
@ -198,9 +208,19 @@
|
|||
/>
|
||||
</div>
|
||||
|
||||
<SettingSwitch bind:checked={isAllowUpload} title={'Allow public user to upload'} />
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={shouldShowExif} title={'Show metadata'} />
|
||||
</div>
|
||||
|
||||
<div class="text-sm mt-4">
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={isAllowDownload} title={'Allow public user to download'} />
|
||||
</div>
|
||||
|
||||
<div class="my-3">
|
||||
<SettingSwitch bind:checked={isAllowUpload} title={'Allow public user to upload'} />
|
||||
</div>
|
||||
|
||||
<div class="text-sm">
|
||||
{#if editingLink}
|
||||
<p class="my-2 immich-form-label">
|
||||
<SettingSwitch
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
{disabled}
|
||||
on:click={toggle}
|
||||
aria-expanded={isOpen}
|
||||
class="bg-gray-200 w-full flex p-2 rounded-lg dark:bg-gray-600 place-items-center justify-between disabled:cursor-not-allowed dark:disabled:bg-gray-300 disabled:bg-gray-600 "
|
||||
class="bg-gray-200 w-full flex p-2 rounded-lg dark:bg-gray-600 place-items-center justify-between disabled:cursor-not-allowed dark:disabled:bg-gray-300 disabled:bg-gray-600"
|
||||
>
|
||||
<div>
|
||||
{selected}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { AssetResponseDto, ThumbnailFormat } from '@api';
|
||||
import { AssetResponseDto, SharedLinkResponseDto, ThumbnailFormat } from '@api';
|
||||
|
||||
import AssetViewer from '../../asset-viewer/asset-viewer.svelte';
|
||||
import ImmichThumbnail from '../../shared-components/immich-thumbnail.svelte';
|
||||
|
||||
export let assets: AssetResponseDto[];
|
||||
export let key: string;
|
||||
export let sharedLink: SharedLinkResponseDto | undefined = undefined;
|
||||
export let selectedAssets: Set<AssetResponseDto> = new Set();
|
||||
|
||||
let isShowAssetViewer = false;
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<ImmichThumbnail
|
||||
{asset}
|
||||
{thumbnailSize}
|
||||
publicSharedKey={key}
|
||||
publicSharedKey={sharedLink?.key}
|
||||
format={assets.length < 7 ? ThumbnailFormat.Jpeg : ThumbnailFormat.Webp}
|
||||
on:click={(e) => (isMultiSelectionMode ? selectAssetHandler(e) : viewAssetHandler(e))}
|
||||
on:select={selectAssetHandler}
|
||||
|
|
@ -110,7 +110,8 @@
|
|||
{#if isShowAssetViewer}
|
||||
<AssetViewer
|
||||
asset={selectedAsset}
|
||||
publicSharedKey={key}
|
||||
publicSharedKey={sharedLink?.key}
|
||||
{sharedLink}
|
||||
on:navigate-previous={navigateAssetBackward}
|
||||
on:navigate-next={navigateAssetForward}
|
||||
on:close={closeViewer}
|
||||
|
|
|
|||
|
|
@ -122,12 +122,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-bottom">
|
||||
<div class="info-bottom flex gap-4">
|
||||
{#if link.allowUpload}
|
||||
<div
|
||||
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[80px]"
|
||||
>
|
||||
Upload
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if link.allowDownload}
|
||||
<div
|
||||
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[100px]"
|
||||
>
|
||||
Allow upload
|
||||
Download
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if link.showExif}
|
||||
<div
|
||||
class="text-xs px-2 py-1 bg-immich-primary dark:bg-immich-dark-primary text-white dark:text-immich-dark-gray flex place-items-center place-content-center rounded-full w-[60px]"
|
||||
>
|
||||
EXIF
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue