feat(web): assets now have a permanent URL (#8532)
* Remove asest redirect pages * Rename route paths to handle optional assetId * Update old references to new routes * Load and display asset from all routes that can show assetId * Add <main> in base layout, update portals to target it * Wire up updating navigation in response to open/close/prev/next * Replace events with navigation functions * Add types to param matcher * misc cleanup * Fix reload on /search pages * Avoid loading bar between photos nav. Delay loading bar by 200ms for all navigations * Update url for maps routes. Note: on page reload, next/prev is not available * Dynamically load asset-viewer on map page * When reloading a url with assetUrl, hide background page to prevent flash during load * Mostly style, review comments * Load buckets for assets on demand * Forgot this update call * typo * fix test * Fix carelessness * Review comment * merge main * remove assets * fix submodule --------- Co-authored-by: Alex <alex.tran1502@gmail.com> Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
This commit is contained in:
@@ -1,6 +1,28 @@
|
||||
<script lang="ts">
|
||||
import UploadCover from '$lib/components/shared-components/drag-and-drop-upload-overlay.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||
let { isViewing: showAssetViewer, setAsset } = assetViewingStore;
|
||||
|
||||
// This block takes care of opening the viewer.
|
||||
// $page.data.asset is loaded by route specific +page.ts loaders if that
|
||||
// route contains the assetId path.
|
||||
$: {
|
||||
if ($page.data.asset) {
|
||||
setAsset($page.data.asset);
|
||||
} else {
|
||||
$showAssetViewer = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
<div class:display-none={$showAssetViewer}>
|
||||
<slot />
|
||||
</div>
|
||||
<UploadCover />
|
||||
|
||||
<style>
|
||||
.display-none {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
+5
-5
@@ -79,6 +79,7 @@
|
||||
import AlbumDescription from '$lib/components/album-page/album-description.svelte';
|
||||
import { handlePromiseError } from '$lib/utils';
|
||||
import AlbumSummary from '$lib/components/album-page/album-summary.svelte';
|
||||
import { isAlbumsRoute, isPeopleRoute, isSearchRoute } from '$lib/utils/navigation';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@@ -137,15 +138,14 @@
|
||||
album.sharedUsers.length > 0 && !$showAssetViewer && (album.isActivityEnabled || $numberOfComments > 0);
|
||||
|
||||
afterNavigate(({ from }) => {
|
||||
assetViewingStore.showAssetViewer(false);
|
||||
|
||||
let url: string | undefined = from?.url?.pathname;
|
||||
|
||||
if (from?.route.id === '/(user)/search') {
|
||||
url = from.url.href;
|
||||
const route = from?.route?.id;
|
||||
if (isSearchRoute(route)) {
|
||||
url = from?.url.href;
|
||||
}
|
||||
|
||||
if (from?.route.id === '/(user)/albums/[albumId]' || from?.route.id === '/(user)/people/[personId]') {
|
||||
if (isAlbumsRoute(route) || isPeopleRoute(route)) {
|
||||
url = AppRoute.ALBUMS;
|
||||
}
|
||||
|
||||
+6
-1
@@ -1,13 +1,18 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import { getAlbumInfo } from '@immich/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const album = await getAlbumInfo({ id: params.albumId, withoutAssets: true });
|
||||
const [album, asset] = await Promise.all([
|
||||
getAlbumInfo({ id: params.albumId, withoutAssets: true }),
|
||||
getAssetInfoFromParam(params),
|
||||
]);
|
||||
|
||||
return {
|
||||
album,
|
||||
asset,
|
||||
meta: {
|
||||
title: album.albumName,
|
||||
},
|
||||
@@ -1,13 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = ({ params }) => {
|
||||
const albumId = params.albumId;
|
||||
|
||||
if (albumId) {
|
||||
redirect(302, `${AppRoute.ALBUMS}/${albumId}`);
|
||||
} else {
|
||||
redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
};
|
||||
+4
-1
@@ -1,10 +1,13 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
|
||||
return {
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Archive',
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = () => {
|
||||
redirect(302, AppRoute.ARCHIVE);
|
||||
};
|
||||
+5
-1
@@ -1,9 +1,13 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
|
||||
return {
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Favorites',
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = () => {
|
||||
redirect(302, AppRoute.FAVORITES);
|
||||
};
|
||||
+17
-13
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import AssetViewer from '$lib/components/asset-viewer/asset-viewer.svelte';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import MapSettingsModal from '$lib/components/map-page/map-settings-modal.svelte';
|
||||
import Map from '$lib/components/shared-components/map/map.svelte';
|
||||
@@ -16,10 +15,11 @@
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { handlePromiseError } from '$lib/utils';
|
||||
import { navigate } from '$lib/utils/navigation';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let { isViewing: showAssetViewer, asset: viewingAsset } = assetViewingStore;
|
||||
let { isViewing: showAssetViewer, asset: viewingAsset, setAssetId } = assetViewingStore;
|
||||
|
||||
let abortController: AbortController;
|
||||
let mapMarkers: MapMarkerResponseDto[] = [];
|
||||
@@ -87,20 +87,22 @@
|
||||
}
|
||||
|
||||
async function onViewAssets(assetIds: string[]) {
|
||||
await assetViewingStore.setAssetId(assetIds[0]);
|
||||
viewingAssets = assetIds;
|
||||
viewingAssetCursor = 0;
|
||||
await setAssetId(assetIds[0]);
|
||||
}
|
||||
|
||||
async function navigateNext() {
|
||||
if (viewingAssetCursor < viewingAssets.length - 1) {
|
||||
await assetViewingStore.setAssetId(viewingAssets[++viewingAssetCursor]);
|
||||
await setAssetId(viewingAssets[++viewingAssetCursor]);
|
||||
await navigate({ targetRoute: 'current', assetId: $viewingAsset.id });
|
||||
}
|
||||
}
|
||||
|
||||
async function navigatePrevious() {
|
||||
if (viewingAssetCursor > 0) {
|
||||
await assetViewingStore.setAssetId(viewingAssets[--viewingAssetCursor]);
|
||||
await setAssetId(viewingAssets[--viewingAssetCursor]);
|
||||
await navigate({ targetRoute: 'current', assetId: $viewingAsset.id });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -113,14 +115,16 @@
|
||||
>
|
||||
<Portal target="body">
|
||||
{#if $showAssetViewer}
|
||||
<AssetViewer
|
||||
asset={$viewingAsset}
|
||||
showNavigation={viewingAssets.length > 1}
|
||||
on:next={navigateNext}
|
||||
on:previous={navigatePrevious}
|
||||
on:close={() => assetViewingStore.showAssetViewer(false)}
|
||||
isShared={false}
|
||||
/>
|
||||
{#await import('../../../../../lib/components/asset-viewer/asset-viewer.svelte') then { default: AssetViewer }}
|
||||
<AssetViewer
|
||||
asset={$viewingAsset}
|
||||
showNavigation={viewingAssets.length > 1}
|
||||
on:next={navigateNext}
|
||||
on:previous={navigatePrevious}
|
||||
on:close={() => assetViewingStore.showAssetViewer(false)}
|
||||
isShared={false}
|
||||
/>
|
||||
{/await}
|
||||
{/if}
|
||||
</Portal>
|
||||
|
||||
+5
-1
@@ -1,9 +1,13 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
|
||||
return {
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Map',
|
||||
},
|
||||
+5
-1
@@ -1,10 +1,14 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
const user = await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
|
||||
return {
|
||||
user,
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Memory',
|
||||
},
|
||||
@@ -1,9 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
await authenticate();
|
||||
redirect(302, AppRoute.MEMORY);
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (() => {
|
||||
redirect(302, AppRoute.PHOTOS);
|
||||
}) satisfies PageLoad;
|
||||
+4
-1
@@ -1,18 +1,21 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import { getPerson, getPersonStatistics } from '@immich/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
|
||||
const [person, statistics] = await Promise.all([
|
||||
const [person, statistics, asset] = await Promise.all([
|
||||
getPerson({ id: params.personId }),
|
||||
getPersonStatistics({ id: params.personId }),
|
||||
getAssetInfoFromParam(params),
|
||||
]);
|
||||
|
||||
return {
|
||||
person,
|
||||
statistics,
|
||||
asset,
|
||||
meta: {
|
||||
title: person.name || 'Person',
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (({ params }) => {
|
||||
redirect(302, `${AppRoute.PEOPLE}/${params.personId}`);
|
||||
}) satisfies PageLoad;
|
||||
+4
-1
@@ -1,9 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
return {
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Photos',
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (() => {
|
||||
redirect(302, AppRoute.PHOTOS);
|
||||
}) satisfies PageLoad;
|
||||
+4
-2
@@ -38,6 +38,7 @@
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import AlbumCardGroup from '$lib/components/album-page/album-card-group.svelte';
|
||||
import { isAlbumsRoute, isPeopleRoute } from '$lib/utils/navigation';
|
||||
|
||||
const MAX_ASSET_COUNT = 5000;
|
||||
let { isViewing: showAssetViewer } = assetViewingStore;
|
||||
@@ -73,12 +74,13 @@
|
||||
if (from?.url && from.route.id !== $page.route.id) {
|
||||
previousRoute = from.url.href;
|
||||
}
|
||||
const route = from?.route?.id;
|
||||
|
||||
if (from?.route.id === '/(user)/people/[personId]') {
|
||||
if (isPeopleRoute(route)) {
|
||||
previousRoute = AppRoute.PHOTOS;
|
||||
}
|
||||
|
||||
if (from?.route.id === '/(user)/albums/[albumId]') {
|
||||
if (isAlbumsRoute(route)) {
|
||||
previousRoute = AppRoute.EXPLORE;
|
||||
}
|
||||
});
|
||||
+4
-1
@@ -1,9 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
return {
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Search',
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (() => {
|
||||
redirect(302, AppRoute.SEARCH);
|
||||
}) satisfies PageLoad;
|
||||
+4
-1
@@ -1,9 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { getAssetInfoFromParam } from '$lib/utils/navigation';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
export const load = (async ({ params }) => {
|
||||
await authenticate();
|
||||
const asset = await getAssetInfoFromParam(params);
|
||||
return {
|
||||
asset,
|
||||
meta: {
|
||||
title: 'Trash',
|
||||
},
|
||||
@@ -1,7 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (() => {
|
||||
redirect(302, AppRoute.TRASH);
|
||||
}) satisfies PageLoad;
|
||||
@@ -17,11 +17,10 @@
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import '../app.css';
|
||||
import { isAssetViewerRoute, isSharedLinkRoute } from '$lib/utils/navigation';
|
||||
|
||||
let showNavigationLoadingBar = false;
|
||||
|
||||
const isSharedLinkRoute = (route: string | null) => route?.startsWith('/(user)/share/[key]');
|
||||
|
||||
$: changeTheme($colorTheme);
|
||||
|
||||
$: if ($user) {
|
||||
@@ -62,7 +61,10 @@
|
||||
setKey($page.params.key);
|
||||
}
|
||||
|
||||
beforeNavigate(() => {
|
||||
beforeNavigate(({ from, to }) => {
|
||||
if (isAssetViewerRoute(from) && isAssetViewerRoute(to)) {
|
||||
return;
|
||||
}
|
||||
showNavigationLoadingBar = true;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user