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:
Alex
2023-01-21 22:15:16 -06:00
committed by GitHub
parent 4cfac47674
commit b07891089f
41 changed files with 520 additions and 73 deletions

View File

@@ -665,6 +665,18 @@ export interface CreateAlbumShareLinkDto {
* @memberof CreateAlbumShareLinkDto
*/
'allowUpload'?: boolean;
/**
*
* @type {boolean}
* @memberof CreateAlbumShareLinkDto
*/
'allowDownload'?: boolean;
/**
*
* @type {boolean}
* @memberof CreateAlbumShareLinkDto
*/
'showExif'?: boolean;
/**
*
* @type {string}
@@ -696,6 +708,18 @@ export interface CreateAssetsShareLinkDto {
* @memberof CreateAssetsShareLinkDto
*/
'allowUpload'?: boolean;
/**
*
* @type {boolean}
* @memberof CreateAssetsShareLinkDto
*/
'allowDownload'?: boolean;
/**
*
* @type {boolean}
* @memberof CreateAssetsShareLinkDto
*/
'showExif'?: boolean;
/**
*
* @type {string}
@@ -987,6 +1011,18 @@ export interface EditSharedLinkDto {
* @memberof EditSharedLinkDto
*/
'allowUpload'?: boolean;
/**
*
* @type {boolean}
* @memberof EditSharedLinkDto
*/
'allowDownload'?: boolean;
/**
*
* @type {boolean}
* @memberof EditSharedLinkDto
*/
'showExif'?: boolean;
/**
*
* @type {boolean}
@@ -1612,6 +1648,18 @@ export interface SharedLinkResponseDto {
* @memberof SharedLinkResponseDto
*/
'allowUpload': boolean;
/**
*
* @type {boolean}
* @memberof SharedLinkResponseDto
*/
'allowDownload': boolean;
/**
*
* @type {boolean}
* @memberof SharedLinkResponseDto
*/
'showExif': boolean;
}
/**
*

View File

@@ -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">

View File

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

View File

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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

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

View File

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

View File

@@ -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>