mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
dev/add detail viewer to album (#358)
* Rename asset viewer folder * Refactor AssetViewer to be able to user with different component * Refactor AssetViewer to be able to user with different component * Added viewer for album and sharing
This commit is contained in:
parent
c129023821
commit
c028c7db4e
@ -164,6 +164,7 @@ export class AlbumRepository implements IAlbumRepository {
|
|||||||
.leftJoinAndSelect('sharedUser.userInfo', 'userInfo')
|
.leftJoinAndSelect('sharedUser.userInfo', 'userInfo')
|
||||||
.leftJoinAndSelect('album.assets', 'assets')
|
.leftJoinAndSelect('album.assets', 'assets')
|
||||||
.leftJoinAndSelect('assets.assetInfo', 'assetInfo')
|
.leftJoinAndSelect('assets.assetInfo', 'assetInfo')
|
||||||
|
.leftJoinAndSelect('assetInfo.exifInfo', 'exifInfo')
|
||||||
.orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC')
|
.orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC')
|
||||||
.getOne();
|
.getOne();
|
||||||
|
|
||||||
|
@ -1,15 +1,21 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { afterNavigate } from '$app/navigation';
|
import { afterNavigate } from '$app/navigation';
|
||||||
|
import { page } from '$app/stores';
|
||||||
import { AlbumResponseDto, ThumbnailFormat } from '@api';
|
import { AlbumResponseDto, AssetResponseDto, ThumbnailFormat } from '@api';
|
||||||
import { createEventDispatcher, onMount } from 'svelte';
|
import { createEventDispatcher, onMount } from 'svelte';
|
||||||
import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
|
import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
|
||||||
import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte';
|
import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte';
|
||||||
|
import AssetViewer from '../asset-viewer/asset-viewer.svelte';
|
||||||
import CircleAvatar from '../shared-components/circle-avatar.svelte';
|
import CircleAvatar from '../shared-components/circle-avatar.svelte';
|
||||||
import ImmichThumbnail from '../shared-components/immich-thumbnail.svelte';
|
import ImmichThumbnail from '../shared-components/immich-thumbnail.svelte';
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
export let album: AlbumResponseDto;
|
export let album: AlbumResponseDto;
|
||||||
|
|
||||||
|
let isShowAssetViewer = false;
|
||||||
|
let selectedAsset: AssetResponseDto;
|
||||||
|
let currentViewAssetIndex = 0;
|
||||||
|
|
||||||
let viewWidth: number;
|
let viewWidth: number;
|
||||||
let thumbnailSize: number = 300;
|
let thumbnailSize: number = 300;
|
||||||
let border = '';
|
let border = '';
|
||||||
@ -52,6 +58,50 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const viewAsset = (event: CustomEvent) => {
|
||||||
|
const { assetId, deviceId }: { assetId: string; deviceId: string } = event.detail;
|
||||||
|
|
||||||
|
currentViewAssetIndex = album.assets.findIndex((a) => a.id == assetId);
|
||||||
|
selectedAsset = album.assets[currentViewAssetIndex];
|
||||||
|
isShowAssetViewer = true;
|
||||||
|
pushState(selectedAsset.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
const navigateAssetForward = () => {
|
||||||
|
try {
|
||||||
|
if (currentViewAssetIndex < album.assets.length - 1) {
|
||||||
|
currentViewAssetIndex++;
|
||||||
|
selectedAsset = album.assets[currentViewAssetIndex];
|
||||||
|
pushState(selectedAsset.id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const navigateAssetBackward = () => {
|
||||||
|
try {
|
||||||
|
if (currentViewAssetIndex > 0) {
|
||||||
|
currentViewAssetIndex--;
|
||||||
|
selectedAsset = album.assets[currentViewAssetIndex];
|
||||||
|
pushState(selectedAsset.id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pushState = (assetId: string) => {
|
||||||
|
// add a URL to the browser's history
|
||||||
|
// changes the current URL in the address bar but doesn't perform any SvelteKit navigation
|
||||||
|
history.pushState(null, '', `${$page.url.pathname}/photos/${assetId}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeViewer = () => {
|
||||||
|
isShowAssetViewer = false;
|
||||||
|
history.pushState(null, '', `${$page.url.pathname}`);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="w-screen h-screen bg-immich-bg">
|
<section class="w-screen h-screen bg-immich-bg">
|
||||||
@ -97,11 +147,26 @@
|
|||||||
<div class="flex flex-wrap gap-1 w-full" bind:clientWidth={viewWidth}>
|
<div class="flex flex-wrap gap-1 w-full" bind:clientWidth={viewWidth}>
|
||||||
{#each album.assets as asset}
|
{#each album.assets as asset}
|
||||||
{#if album.assets.length < 7}
|
{#if album.assets.length < 7}
|
||||||
<ImmichThumbnail {asset} {thumbnailSize} format={ThumbnailFormat.Jpeg} />
|
<ImmichThumbnail
|
||||||
|
{asset}
|
||||||
|
{thumbnailSize}
|
||||||
|
format={ThumbnailFormat.Jpeg}
|
||||||
|
on:viewAsset={viewAsset}
|
||||||
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<ImmichThumbnail {asset} {thumbnailSize} />
|
<ImmichThumbnail {asset} {thumbnailSize} on:viewAsset={viewAsset} />
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- Overlay Asset Viewer -->
|
||||||
|
{#if isShowAssetViewer}
|
||||||
|
<AssetViewer
|
||||||
|
asset={selectedAsset}
|
||||||
|
on:navigate-backward={navigateAssetBackward}
|
||||||
|
on:navigate-forward={navigateAssetForward}
|
||||||
|
on:close={closeViewer}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import AsserViewerNavBar from './asser-viewer-nav-bar.svelte';
|
import AsserViewerNavBar from './asser-viewer-nav-bar.svelte';
|
||||||
import { flattenAssetGroupByDate } from '$lib/stores/assets';
|
|
||||||
import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
|
import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
|
||||||
import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
|
import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
|
||||||
import PhotoViewer from './photo-viewer.svelte';
|
import PhotoViewer from './photo-viewer.svelte';
|
||||||
@ -14,31 +13,16 @@
|
|||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
export let selectedAsset: AssetResponseDto;
|
export let asset: AssetResponseDto;
|
||||||
|
|
||||||
export let selectedIndex: number;
|
|
||||||
|
|
||||||
let viewDeviceId: string;
|
|
||||||
let viewAssetId: string;
|
|
||||||
|
|
||||||
let halfLeftHover = false;
|
let halfLeftHover = false;
|
||||||
let halfRightHover = false;
|
let halfRightHover = false;
|
||||||
let isShowDetail = false;
|
let isShowDetail = false;
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
viewAssetId = selectedAsset.id;
|
|
||||||
viewDeviceId = selectedAsset.deviceId;
|
|
||||||
pushState(viewAssetId);
|
|
||||||
|
|
||||||
document.addEventListener('keydown', (keyInfo) => handleKeyboardPress(keyInfo.key));
|
document.addEventListener('keydown', (keyInfo) => handleKeyboardPress(keyInfo.key));
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
|
||||||
document.removeEventListener('keydown', (b) => {
|
|
||||||
console.log('destroyed', b);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleKeyboardPress = (key: string) => {
|
const handleKeyboardPress = (key: string) => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
@ -57,38 +41,17 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const closeViewer = () => {
|
const closeViewer = () => {
|
||||||
history.pushState(null, '', `/photos`);
|
|
||||||
dispatch('close');
|
dispatch('close');
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateAssetForward = (e?: Event) => {
|
const navigateAssetForward = (e?: Event) => {
|
||||||
e?.stopPropagation();
|
e?.stopPropagation();
|
||||||
|
dispatch('navigate-forward');
|
||||||
const nextAsset = $flattenAssetGroupByDate[selectedIndex + 1];
|
|
||||||
viewDeviceId = nextAsset.deviceId;
|
|
||||||
viewAssetId = nextAsset.id;
|
|
||||||
|
|
||||||
selectedIndex = selectedIndex + 1;
|
|
||||||
selectedAsset = $flattenAssetGroupByDate[selectedIndex];
|
|
||||||
pushState(viewAssetId);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigateAssetBackward = (e?: Event) => {
|
const navigateAssetBackward = (e?: Event) => {
|
||||||
e?.stopPropagation();
|
e?.stopPropagation();
|
||||||
|
dispatch('navigate-backward');
|
||||||
const lastAsset = $flattenAssetGroupByDate[selectedIndex - 1];
|
|
||||||
viewDeviceId = lastAsset.deviceId;
|
|
||||||
viewAssetId = lastAsset.id;
|
|
||||||
|
|
||||||
selectedIndex = selectedIndex - 1;
|
|
||||||
selectedAsset = $flattenAssetGroupByDate[selectedIndex];
|
|
||||||
pushState(viewAssetId);
|
|
||||||
};
|
|
||||||
|
|
||||||
const pushState = (assetId: string) => {
|
|
||||||
// add a URL to the browser's history
|
|
||||||
// changes the current URL in the address bar but doesn't perform any SvelteKit navigation
|
|
||||||
history.pushState(null, '', `/photos/${assetId}`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showDetailInfoHandler = () => {
|
const showDetailInfoHandler = () => {
|
||||||
@ -98,19 +61,20 @@
|
|||||||
const downloadFile = async () => {
|
const downloadFile = async () => {
|
||||||
if ($session.user) {
|
if ($session.user) {
|
||||||
try {
|
try {
|
||||||
const imageName = selectedAsset.exifInfo?.imageName ? selectedAsset.exifInfo?.imageName : selectedAsset.id;
|
const imageName = asset.exifInfo?.imageName ? asset.exifInfo?.imageName : asset.id;
|
||||||
const imageExtension = selectedAsset.originalPath.split('.')[1];
|
const imageExtension = asset.originalPath.split('.')[1];
|
||||||
const imageFileName = imageName + '.' + imageExtension;
|
const imageFileName = imageName + '.' + imageExtension;
|
||||||
|
|
||||||
// If assets is already download -> return;
|
// If assets is already download -> return;
|
||||||
if ($downloadAssets[imageFileName]) {
|
if ($downloadAssets[imageFileName]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$downloadAssets[imageFileName] = 0;
|
$downloadAssets[imageFileName] = 0;
|
||||||
|
|
||||||
const { data, status } = await api.assetApi.downloadFile(
|
const { data, status } = await api.assetApi.downloadFile(
|
||||||
selectedAsset.deviceAssetId,
|
asset.deviceAssetId,
|
||||||
selectedAsset.deviceId,
|
asset.deviceId,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
{
|
{
|
||||||
@ -123,8 +87,8 @@
|
|||||||
|
|
||||||
$downloadAssets[imageFileName] = percentCompleted;
|
$downloadAssets[imageFileName] = percentCompleted;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!(data instanceof Blob)) {
|
if (!(data instanceof Blob)) {
|
||||||
@ -162,12 +126,16 @@
|
|||||||
class="absolute h-screen w-screen top-0 overflow-y-hidden bg-black z-[999] grid grid-rows-[64px_1fr] grid-cols-4 "
|
class="absolute h-screen w-screen top-0 overflow-y-hidden bg-black z-[999] grid grid-rows-[64px_1fr] grid-cols-4 "
|
||||||
>
|
>
|
||||||
<div class="col-start-1 col-span-4 row-start-1 row-span-1 z-[1000] transition-transform">
|
<div class="col-start-1 col-span-4 row-start-1 row-span-1 z-[1000] transition-transform">
|
||||||
<AsserViewerNavBar on:goBack={closeViewer} on:showDetail={showDetailInfoHandler} on:download={downloadFile} />
|
<AsserViewerNavBar
|
||||||
|
on:goBack={closeViewer}
|
||||||
|
on:showDetail={showDetailInfoHandler}
|
||||||
|
on:download={downloadFile}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`row-start-2 row-span-end col-start-1 col-span-2 flex place-items-center hover:cursor-pointer w-3/4 ${
|
class={`row-start-2 row-span-end col-start-1 col-span-2 flex place-items-center hover:cursor-pointer w-3/4 ${
|
||||||
selectedAsset.type == 'VIDEO' ? '' : 'z-[999]'
|
asset.type == AssetTypeEnum.Video ? '' : 'z-[999]'
|
||||||
}`}
|
}`}
|
||||||
on:mouseenter={() => {
|
on:mouseenter={() => {
|
||||||
halfLeftHover = true;
|
halfLeftHover = true;
|
||||||
@ -188,20 +156,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row-start-1 row-span-full col-start-1 col-span-4">
|
<div class="row-start-1 row-span-full col-start-1 col-span-4">
|
||||||
{#key selectedIndex}
|
{#key asset.id}
|
||||||
{#if viewAssetId && viewDeviceId}
|
{#if asset.type == AssetTypeEnum.Image}
|
||||||
{#if selectedAsset.type == AssetTypeEnum.Image}
|
<PhotoViewer assetId={asset.id} deviceId={asset.deviceId} on:close={closeViewer} />
|
||||||
<PhotoViewer assetId={viewAssetId} deviceId={viewDeviceId} on:close={closeViewer} />
|
|
||||||
{:else}
|
{:else}
|
||||||
<VideoViewer assetId={viewAssetId} on:close={closeViewer} />
|
<VideoViewer assetId={asset.id} on:close={closeViewer} />
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`row-start-2 row-span-full col-start-3 col-span-2 flex justify-end place-items-center hover:cursor-pointer w-3/4 justify-self-end ${
|
class={`row-start-2 row-span-full col-start-3 col-span-2 flex justify-end place-items-center hover:cursor-pointer w-3/4 justify-self-end ${
|
||||||
selectedAsset.type == 'VIDEO' ? '' : 'z-[500]'
|
asset.type == AssetTypeEnum.Video ? '' : 'z-[500]'
|
||||||
}`}
|
}`}
|
||||||
on:click={navigateAssetForward}
|
on:click={navigateAssetForward}
|
||||||
on:mouseenter={() => {
|
on:mouseenter={() => {
|
||||||
@ -228,7 +194,7 @@
|
|||||||
class="bg-immich-bg w-[360px] row-span-full transition-all "
|
class="bg-immich-bg w-[360px] row-span-full transition-all "
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<DetailPanel asset={selectedAsset} on:close={() => (isShowDetail = false)} />
|
<DetailPanel {asset} on:close={() => (isShowDetail = false)} />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</section>
|
</section>
|
@ -2,7 +2,7 @@
|
|||||||
import { session } from '$app/stores';
|
import { session } from '$app/stores';
|
||||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||||
import { fade, fly } from 'svelte/transition';
|
import { fade, fly } from 'svelte/transition';
|
||||||
import IntersectionObserver from '$lib/components/asset-viewer-page/intersection-observer.svelte';
|
import IntersectionObserver from '$lib/components/asset-viewer/intersection-observer.svelte';
|
||||||
import CheckCircle from 'svelte-material-icons/CheckCircle.svelte';
|
import CheckCircle from 'svelte-material-icons/CheckCircle.svelte';
|
||||||
import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte';
|
import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte';
|
||||||
import PauseCircleOutline from 'svelte-material-icons/PauseCircleOutline.svelte';
|
import PauseCircleOutline from 'svelte-material-icons/PauseCircleOutline.svelte';
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
{#if user.email == albumOwner.email}
|
{#if user.email == albumOwner.email}
|
||||||
<p class="text-xs text-gray-600">Owned</p>
|
<p class="text-xs text-gray-600">Owned</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="text-xs text-gray-600">Shared by {albumOwner.email}</p>
|
<p class="text-xs text-gray-600">Shared by {albumOwner.firstName} {albumOwner.lastName}</p>
|
||||||
{/if}
|
{/if}
|
||||||
{/await}
|
{/await}
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
import { blur, fade, slide } from 'svelte/transition';
|
import { blur, fade, slide } from 'svelte/transition';
|
||||||
|
|
||||||
import DownloadPanel from '$lib/components/asset-viewer-page/download-panel.svelte';
|
import DownloadPanel from '$lib/components/asset-viewer/download-panel.svelte';
|
||||||
import AnnouncementBox from '$lib/components/shared-components/announcement-box.svelte';
|
import AnnouncementBox from '$lib/components/shared-components/announcement-box.svelte';
|
||||||
import UploadPanel from '$lib/components/shared-components/upload-panel.svelte';
|
import UploadPanel from '$lib/components/shared-components/upload-panel.svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
@ -35,8 +35,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
|
|
||||||
import AlbumViewer from '$lib/components/album-page/album-viewer.svelte';
|
import AlbumViewer from '$lib/components/album-page/album-viewer.svelte';
|
||||||
|
|
||||||
export let album: AlbumResponseDto;
|
export let album: AlbumResponseDto;
|
27
web/src/routes/albums/[albumId]/photos/[assetId].svelte
Normal file
27
web/src/routes/albums/[albumId]/photos/[assetId].svelte
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<script context="module" lang="ts">
|
||||||
|
export const prerender = false;
|
||||||
|
|
||||||
|
import type { Load } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const load: Load = async ({ session, params }) => {
|
||||||
|
if (!session.user) {
|
||||||
|
return {
|
||||||
|
status: 302,
|
||||||
|
redirect: '/auth/login'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const albumId = params['albumId'];
|
||||||
|
|
||||||
|
if (albumId) {
|
||||||
|
return {
|
||||||
|
status: 302,
|
||||||
|
redirect: `/albums/${albumId}`
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
status: 302,
|
||||||
|
redirect: `/photos`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -33,7 +33,7 @@
|
|||||||
import { assetsGroupByDate, flattenAssetGroupByDate } from '$lib/stores/assets';
|
import { assetsGroupByDate, flattenAssetGroupByDate } from '$lib/stores/assets';
|
||||||
import ImmichThumbnail from '$lib/components/shared-components/immich-thumbnail.svelte';
|
import ImmichThumbnail from '$lib/components/shared-components/immich-thumbnail.svelte';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import AssetViewer from '$lib/components/asset-viewer-page/asset-viewer.svelte';
|
import AssetViewer from '$lib/components/asset-viewer/asset-viewer.svelte';
|
||||||
import { fileUploader } from '$lib/utils/file-uploader';
|
import { fileUploader } from '$lib/utils/file-uploader';
|
||||||
import { AssetResponseDto } from '@api';
|
import { AssetResponseDto } from '@api';
|
||||||
import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte';
|
import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte';
|
||||||
@ -42,13 +42,14 @@
|
|||||||
|
|
||||||
let selectedGroupThumbnail: number | null;
|
let selectedGroupThumbnail: number | null;
|
||||||
let isMouseOverGroup: boolean;
|
let isMouseOverGroup: boolean;
|
||||||
|
|
||||||
$: if (isMouseOverGroup == false) {
|
$: if (isMouseOverGroup == false) {
|
||||||
selectedGroupThumbnail = null;
|
selectedGroupThumbnail = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isShowAsset = false;
|
let isShowAssetViewer = false;
|
||||||
let currentViewAssetIndex = 0;
|
let currentViewAssetIndex = 0;
|
||||||
let currentSelectedAsset: AssetResponseDto;
|
let selectedAsset: AssetResponseDto;
|
||||||
|
|
||||||
const thumbnailMouseEventHandler = (event: CustomEvent) => {
|
const thumbnailMouseEventHandler = (event: CustomEvent) => {
|
||||||
const { selectedGroupIndex }: { selectedGroupIndex: number } = event.detail;
|
const { selectedGroupIndex }: { selectedGroupIndex: number } = event.detail;
|
||||||
@ -60,8 +61,9 @@
|
|||||||
const { assetId, deviceId }: { assetId: string; deviceId: string } = event.detail;
|
const { assetId, deviceId }: { assetId: string; deviceId: string } = event.detail;
|
||||||
|
|
||||||
currentViewAssetIndex = $flattenAssetGroupByDate.findIndex((a) => a.id == assetId);
|
currentViewAssetIndex = $flattenAssetGroupByDate.findIndex((a) => a.id == assetId);
|
||||||
currentSelectedAsset = $flattenAssetGroupByDate[currentViewAssetIndex];
|
selectedAsset = $flattenAssetGroupByDate[currentViewAssetIndex];
|
||||||
isShowAsset = true;
|
isShowAssetViewer = true;
|
||||||
|
pushState(selectedAsset.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
const uploadClickedHandler = async () => {
|
const uploadClickedHandler = async () => {
|
||||||
@ -91,6 +93,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const navigateAssetForward = () => {
|
||||||
|
try {
|
||||||
|
if (currentViewAssetIndex < $flattenAssetGroupByDate.length - 1) {
|
||||||
|
currentViewAssetIndex++;
|
||||||
|
selectedAsset = $flattenAssetGroupByDate[currentViewAssetIndex];
|
||||||
|
pushState(selectedAsset.id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error navigating asset forward', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const navigateAssetBackward = () => {
|
||||||
|
try {
|
||||||
|
if (currentViewAssetIndex > 0) {
|
||||||
|
currentViewAssetIndex--;
|
||||||
|
selectedAsset = $flattenAssetGroupByDate[currentViewAssetIndex];
|
||||||
|
pushState(selectedAsset.id);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error navigating asset backward', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const pushState = (assetId: string) => {
|
||||||
|
// add a URL to the browser's history
|
||||||
|
// changes the current URL in the address bar but doesn't perform any SvelteKit navigation
|
||||||
|
history.pushState(null, '', `/photos/${assetId}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeViewer = () => {
|
||||||
|
isShowAssetViewer = false;
|
||||||
|
history.pushState(null, '', `/photos`);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -149,10 +186,11 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- Overlay Asset Viewer -->
|
<!-- Overlay Asset Viewer -->
|
||||||
{#if isShowAsset}
|
{#if isShowAssetViewer}
|
||||||
<AssetViewer
|
<AssetViewer
|
||||||
selectedAsset={currentSelectedAsset}
|
asset={selectedAsset}
|
||||||
selectedIndex={currentViewAssetIndex}
|
on:navigate-backward={navigateAssetBackward}
|
||||||
on:close={() => (isShowAsset = false)}
|
on:navigate-forward={navigateAssetForward}
|
||||||
|
on:close={closeViewer}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user