mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
refactor(web): shared link key auth (#3855)
This commit is contained in:
parent
10c2bda3a9
commit
9bbef4a97b
21 changed files with 115 additions and 108 deletions
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
export let assetStore: AssetStore | null = null;
|
||||
export let asset: AssetResponseDto;
|
||||
export let publicSharedKey = '';
|
||||
export let showNavigation = true;
|
||||
export let sharedLink: SharedLinkResponseDto | undefined = undefined;
|
||||
|
||||
|
|
@ -72,6 +71,10 @@
|
|||
$: asset.id && !sharedLink && getAllAlbums(); // Update the album information when the asset ID changes
|
||||
|
||||
const getAllAlbums = async () => {
|
||||
if (api.isSharedLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await api.albumApi.getAllAlbums({ assetId: asset.id });
|
||||
appearsInAlbums = data;
|
||||
|
|
@ -84,7 +87,9 @@
|
|||
switch (key) {
|
||||
case 'a':
|
||||
case 'A':
|
||||
if (shiftKey) toggleArchive();
|
||||
if (shiftKey) {
|
||||
toggleArchive();
|
||||
}
|
||||
return;
|
||||
case 'ArrowLeft':
|
||||
navigateAssetBackward();
|
||||
|
|
@ -94,7 +99,9 @@
|
|||
return;
|
||||
case 'd':
|
||||
case 'D':
|
||||
if (shiftKey) downloadFile(asset, publicSharedKey);
|
||||
if (shiftKey) {
|
||||
downloadFile(asset);
|
||||
}
|
||||
return;
|
||||
case 'Delete':
|
||||
isShowDeleteConfirmation = true;
|
||||
|
|
@ -272,7 +279,7 @@
|
|||
showDownloadButton={shouldShowDownloadButton}
|
||||
on:goBack={closeViewer}
|
||||
on:showDetail={showDetailInfoHandler}
|
||||
on:download={() => downloadFile(asset, publicSharedKey)}
|
||||
on:download={() => downloadFile(asset)}
|
||||
on:delete={() => (isShowDeleteConfirmation = true)}
|
||||
on:favorite={toggleFavorite}
|
||||
on:addToAlbum={() => openAlbumPicker(false)}
|
||||
|
|
@ -304,7 +311,6 @@
|
|||
{:else if asset.type === AssetTypeEnum.Image}
|
||||
{#if shouldPlayMotionPhoto && asset.livePhotoVideoId}
|
||||
<VideoViewer
|
||||
{publicSharedKey}
|
||||
assetId={asset.livePhotoVideoId}
|
||||
on:close={closeViewer}
|
||||
on:onVideoEnded={() => (shouldPlayMotionPhoto = false)}
|
||||
|
|
@ -312,12 +318,12 @@
|
|||
{:else if asset.exifInfo?.projectionType === ProjectionType.EQUIRECTANGULAR || asset.originalPath
|
||||
.toLowerCase()
|
||||
.endsWith('.insp')}
|
||||
<PanoramaViewer {publicSharedKey} {asset} />
|
||||
<PanoramaViewer {asset} />
|
||||
{:else}
|
||||
<PhotoViewer {publicSharedKey} {asset} on:close={closeViewer} />
|
||||
<PhotoViewer {asset} on:close={closeViewer} />
|
||||
{/if}
|
||||
{:else}
|
||||
<VideoViewer {publicSharedKey} assetId={asset.id} on:close={closeViewer} />
|
||||
<VideoViewer assetId={asset.id} on:close={closeViewer} />
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
|
|
@ -338,7 +344,6 @@
|
|||
<DetailPanel
|
||||
{asset}
|
||||
albums={appearsInAlbums}
|
||||
{sharedLink}
|
||||
on:close={() => ($isShowDetail = false)}
|
||||
on:close-viewer={handleCloseViewer}
|
||||
on:description-focus-in={disableKeyDownEvent}
|
||||
|
|
|
|||
|
|
@ -9,21 +9,20 @@
|
|||
import ImageOutline from 'svelte-material-icons/ImageOutline.svelte';
|
||||
import MapMarkerOutline from 'svelte-material-icons/MapMarkerOutline.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { AssetResponseDto, AlbumResponseDto, api, ThumbnailFormat, SharedLinkResponseDto } from '@api';
|
||||
import { AssetResponseDto, AlbumResponseDto, api, ThumbnailFormat } from '@api';
|
||||
import { asByteUnitString } from '../../utils/byte-units';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
import { getAssetFilename } from '$lib/utils/asset-utils';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let albums: AlbumResponseDto[] = [];
|
||||
export let sharedLink: SharedLinkResponseDto | undefined = undefined;
|
||||
|
||||
let textarea: HTMLTextAreaElement;
|
||||
let description: string;
|
||||
|
||||
$: {
|
||||
// Get latest description from server
|
||||
if (asset.id && !sharedLink) {
|
||||
if (asset.id && !api.isSharedLink) {
|
||||
api.assetApi.getAssetById({ id: asset.id }).then((res) => {
|
||||
people = res.data?.people || [];
|
||||
textarea.value = res.data?.exifInfo?.description || '';
|
||||
|
|
@ -91,13 +90,15 @@
|
|||
<p class="text-lg text-immich-fg dark:text-immich-dark-fg">Info</p>
|
||||
</div>
|
||||
|
||||
<section class="mx-4 mt-10">
|
||||
<section
|
||||
class="mx-4 mt-10"
|
||||
style:display={$page?.data?.user?.id !== asset.ownerId && textarea?.value == '' ? 'none' : 'block'}
|
||||
>
|
||||
<textarea
|
||||
bind:this={textarea}
|
||||
class="max-h-[500px]
|
||||
w-full resize-none overflow-hidden border-b border-gray-500 bg-transparent text-base text-black outline-none transition-all focus:border-b-2 focus:border-immich-primary disabled:border-none dark:text-white dark:focus:border-immich-dark-primary"
|
||||
placeholder={$page?.data?.user?.id !== asset.ownerId ? '' : 'Add a description'}
|
||||
style:display={$page?.data?.user?.id !== asset.ownerId && textarea?.value == '' ? 'none' : 'block'}
|
||||
on:focusin={handleFocusIn}
|
||||
on:focusout={handleFocusOut}
|
||||
on:input={autoGrowHeight}
|
||||
|
|
@ -106,7 +107,7 @@
|
|||
/>
|
||||
</section>
|
||||
|
||||
{#if people.length > 0}
|
||||
{#if !api.isSharedLink && people.length > 0}
|
||||
<section class="px-4 py-4 text-sm">
|
||||
<h2>PEOPLE</h2>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@
|
|||
import { api, AssetResponseDto } from '@api';
|
||||
import View360, { EquirectProjection } from '@egjs/svelte-view360';
|
||||
import './panorama-viewer.css';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let publicSharedKey = '';
|
||||
|
||||
let dataUrl = '';
|
||||
let errorMessage = '';
|
||||
|
||||
const loadAssetData = async () => {
|
||||
try {
|
||||
const { data } = await api.assetApi.serveFile(
|
||||
{ id: asset.id, isThumb: false, isWeb: false, key: publicSharedKey },
|
||||
{ id: asset.id, isThumb: false, isWeb: false, key: api.getKey() },
|
||||
{ responseType: 'blob' },
|
||||
);
|
||||
if (data instanceof Blob) {
|
||||
|
|
|
|||
|
|
@ -8,12 +8,10 @@
|
|||
import { photoZoomState } from '$lib/stores/zoom-image.store';
|
||||
|
||||
export let asset: AssetResponseDto;
|
||||
export let publicSharedKey = '';
|
||||
export let element: HTMLDivElement | undefined = undefined;
|
||||
|
||||
let imgElement: HTMLDivElement;
|
||||
|
||||
let assetData: string;
|
||||
|
||||
let copyImageToClipboard: (src: string) => Promise<Blob>;
|
||||
let canCopyImagesToClipboard: () => boolean;
|
||||
|
||||
|
|
@ -28,7 +26,7 @@
|
|||
const loadAssetData = async () => {
|
||||
try {
|
||||
const { data } = await api.assetApi.serveFile(
|
||||
{ id: asset.id, isThumb: false, isWeb: true, key: publicSharedKey },
|
||||
{ id: asset.id, isThumb: false, isWeb: true, key: api.getKey() },
|
||||
{
|
||||
responseType: 'blob',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
import { handleError } from '../../utils/handle-error';
|
||||
|
||||
export let assetId: string;
|
||||
export let publicSharedKey: string | undefined = undefined;
|
||||
|
||||
let isVideoLoading = true;
|
||||
const dispatch = createEventDispatcher<{ onVideoEnded: void }>();
|
||||
|
|
@ -37,7 +36,7 @@
|
|||
bind:volume={$videoViewerVolume}
|
||||
poster={api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Jpeg)}
|
||||
>
|
||||
<source src={api.getAssetFileUrl(assetId, false, true, publicSharedKey)} type="video/mp4" />
|
||||
<source src={api.getAssetFileUrl(assetId, false, true)} type="video/mp4" />
|
||||
<track kind="captions" />
|
||||
</video>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue