mirror of
https://github.com/immich-app/immich.git
synced 2026-02-13 12:27:56 +03:00
refactor(web): routes (#25365)
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { resolve } from '$app/paths';
|
||||
import { shortcut } from '$lib/actions/shortcut';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import AssetTagModal from '$lib/modals/AssetTagModal.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { removeTag } from '$lib/utils/asset-utils';
|
||||
import { getAssetInfo, type AssetResponseDto } from '@immich/sdk';
|
||||
import { Icon, modalManager } from '@immich/ui';
|
||||
@@ -46,7 +45,7 @@
|
||||
<div class="flex group transition-all">
|
||||
<a
|
||||
class="inline-block h-min whitespace-nowrap ps-3 pe-1 group-hover:ps-3 py-1 text-center align-baseline leading-none text-gray-100 dark:text-immich-dark-gray bg-primary rounded-s-full hover:bg-immich-primary/80 dark:hover:bg-immich-dark-primary/80 transition-all"
|
||||
href={resolve(`${AppRoute.TAGS}/?path=${encodeURI(tag.value)}`)}
|
||||
href={Route.tags({ path: tag.value })}
|
||||
>
|
||||
<p class="text-sm">
|
||||
{tag.value}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { resolve } from '$app/paths';
|
||||
import DetailPanelDescription from '$lib/components/asset-viewer/detail-panel-description.svelte';
|
||||
import DetailPanelLocation from '$lib/components/asset-viewer/detail-panel-location.svelte';
|
||||
import DetailPanelRating from '$lib/components/asset-viewer/detail-panel-star-rating.svelte';
|
||||
import DetailPanelTags from '$lib/components/asset-viewer/detail-panel-tags.svelte';
|
||||
import { AppRoute, QueryParameter, timeToLoadTheMap } from '$lib/constants';
|
||||
import { timeToLoadTheMap } from '$lib/constants';
|
||||
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
@@ -73,6 +72,7 @@
|
||||
})(),
|
||||
);
|
||||
let previousId: string | undefined = $state();
|
||||
let previousRoute = $derived(currentAlbum?.id ? Route.viewAlbum(currentAlbum) : Route.photos());
|
||||
|
||||
$effect(() => {
|
||||
if (!previousId) {
|
||||
@@ -100,11 +100,8 @@
|
||||
};
|
||||
|
||||
const getAssetFolderHref = (asset: AssetResponseDto) => {
|
||||
const folderUrl = new URL(AppRoute.FOLDERS, globalThis.location.href);
|
||||
// Remove the last part of the path to get the parent path
|
||||
const assetParentPath = getParentPath(asset.originalPath);
|
||||
folderUrl.searchParams.set(QueryParameter.PATH, assetParentPath);
|
||||
return folderUrl.href;
|
||||
return Route.folders({ path: getParentPath(asset.originalPath) });
|
||||
};
|
||||
|
||||
const toggleAssetPath = () => (showAssetPath = !showAssetPath);
|
||||
@@ -205,11 +202,7 @@
|
||||
{#if showingHiddenPeople || !person.isHidden}
|
||||
<a
|
||||
class="w-22"
|
||||
href={resolve(
|
||||
`${AppRoute.PEOPLE}/${person.id}?${QueryParameter.PREVIOUS_ROUTE}=${
|
||||
currentAlbum?.id ? Route.viewAlbum(currentAlbum) : Route.photos()
|
||||
}`,
|
||||
)}
|
||||
href={Route.viewPerson(person, { previousRoute })}
|
||||
onfocus={() => ($boundingBoxesArray = people[index].faces)}
|
||||
onblur={() => ($boundingBoxesArray = [])}
|
||||
onmouseover={() => ($boundingBoxesArray = people[index].faces)}
|
||||
@@ -472,7 +465,7 @@
|
||||
simplified
|
||||
useLocationPin
|
||||
showSimpleControls={!showEditFaces}
|
||||
onOpenInMapView={() => goto(resolve(`${AppRoute.MAP}#12.5/${latlng.lat}/${latlng.lng}`))}
|
||||
onOpenInMapView={() => goto(Route.map({ ...latlng, zoom: 12.5 }))}
|
||||
>
|
||||
{#snippet popup({ marker })}
|
||||
{@const { lat, lon } = marker}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/state';
|
||||
import { ActionQueryParameterValue, AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { Route } from '$lib/route';
|
||||
import { handleError } from '$lib/utils/handle-error';
|
||||
import { getAllPeople, getPerson, mergePerson, type PersonResponseDto } from '@immich/sdk';
|
||||
import { Button, Icon, IconButton, modalManager, toastManager } from '@immich/ui';
|
||||
@@ -39,8 +38,7 @@
|
||||
|
||||
const handleSwapPeople = async () => {
|
||||
[person, selectedPeople[0]] = [selectedPeople[0], person];
|
||||
page.url.searchParams.set(QueryParameter.ACTION, ActionQueryParameterValue.MERGE);
|
||||
await goto(`${AppRoute.PEOPLE}/${person.id}?${page.url.searchParams.toString()}`);
|
||||
await goto(Route.viewPerson(person, { previousRoute: Route.people(), action: 'merge' }));
|
||||
};
|
||||
|
||||
const onSelect = async (selected: PersonResponseDto) => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { focusOutside } from '$lib/actions/focus-outside';
|
||||
import ActionMenuItem from '$lib/components/ActionMenuItem.svelte';
|
||||
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import { Route } from '$lib/route';
|
||||
import { getPersonActions } from '$lib/services/person.service';
|
||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||
import { type PersonResponseDto } from '@immich/sdk';
|
||||
@@ -42,7 +42,7 @@
|
||||
use:focusOutside={{ onFocusOut: () => (showVerticalDots = false) }}
|
||||
>
|
||||
<a
|
||||
href="{AppRoute.PEOPLE}/{person.id}?{QueryParameter.PREVIOUS_ROUTE}={AppRoute.PEOPLE}"
|
||||
href={Route.viewPerson(person, { previousRoute: Route.people() })}
|
||||
draggable="false"
|
||||
onfocus={() => (showVerticalDots = true)}
|
||||
>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import BottomInfo from '$lib/components/shared-components/side-bar/bottom-info.svelte';
|
||||
import RecentAlbums from '$lib/components/shared-components/side-bar/recent-albums.svelte';
|
||||
import Sidebar from '$lib/components/sidebar/sidebar.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { recentAlbumsDropdown } from '$lib/stores/preferences.store';
|
||||
@@ -45,11 +44,11 @@
|
||||
{/if}
|
||||
|
||||
{#if featureFlagsManager.value.map}
|
||||
<NavbarItem title={$t('map')} href={AppRoute.MAP} icon={mdiMapOutline} activeIcon={mdiMap} />
|
||||
<NavbarItem title={$t('map')} href={Route.map()} icon={mdiMapOutline} activeIcon={mdiMap} />
|
||||
{/if}
|
||||
|
||||
{#if $preferences.people.enabled && $preferences.people.sidebarWeb}
|
||||
<NavbarItem title={$t('people')} href={AppRoute.PEOPLE} icon={mdiAccountOutline} activeIcon={mdiAccount} />
|
||||
<NavbarItem title={$t('people')} href={Route.people()} icon={mdiAccountOutline} activeIcon={mdiAccount} />
|
||||
{/if}
|
||||
|
||||
{#if $preferences.sharedLinks.enabled && $preferences.sharedLinks.sidebarWeb}
|
||||
@@ -81,11 +80,11 @@
|
||||
</NavbarItem>
|
||||
|
||||
{#if $preferences.tags.enabled && $preferences.tags.sidebarWeb}
|
||||
<NavbarItem title={$t('tags')} href={AppRoute.TAGS} icon={{ icon: mdiTagMultipleOutline, flipped: true }} />
|
||||
<NavbarItem title={$t('tags')} href={Route.tags()} icon={{ icon: mdiTagMultipleOutline, flipped: true }} />
|
||||
{/if}
|
||||
|
||||
{#if $preferences.folders.enabled && $preferences.folders.sidebarWeb}
|
||||
<NavbarItem title={$t('folders')} href={AppRoute.FOLDERS} icon={{ icon: mdiFolderOutline, flipped: true }} />
|
||||
<NavbarItem title={$t('folders')} href={Route.folders()} icon={{ icon: mdiFolderOutline, flipped: true }} />
|
||||
{/if}
|
||||
|
||||
<NavbarItem title={$t('utilities')} href={Route.utilities()} icon={mdiToolboxOutline} activeIcon={mdiToolbox} />
|
||||
|
||||
@@ -19,16 +19,6 @@ export enum AssetAction {
|
||||
RATING = 'rating',
|
||||
}
|
||||
|
||||
export enum AppRoute {
|
||||
PEOPLE = '/people',
|
||||
SEARCH = '/search',
|
||||
MAP = '/map',
|
||||
BUY = '/buy',
|
||||
FOLDERS = '/folders',
|
||||
TAGS = '/tags',
|
||||
MAINTENANCE = '/maintenance',
|
||||
}
|
||||
|
||||
export type SharedLinkTab = 'all' | 'album' | 'individual';
|
||||
|
||||
export enum ProjectionType {
|
||||
@@ -82,10 +72,6 @@ export enum OpenQueryParam {
|
||||
PURCHASE_SETTINGS = 'user-purchase-settings',
|
||||
}
|
||||
|
||||
export enum ActionQueryParameterValue {
|
||||
MERGE = 'merge',
|
||||
}
|
||||
|
||||
export const maximumLengthSearchPeople = 1000;
|
||||
|
||||
// time to load the map before displaying the loading spinner
|
||||
|
||||
@@ -24,6 +24,20 @@ describe('Route', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe(Route.tags.name, () => {
|
||||
it('should work', () => {
|
||||
expect(Route.tags()).toBe('/tags');
|
||||
});
|
||||
|
||||
it('should support query parameters', () => {
|
||||
expect(Route.tags({ path: '/some/path' })).toBe('/tags?path=%2Fsome%2Fpath');
|
||||
});
|
||||
|
||||
it('should ignore an empty path', () => {
|
||||
expect(Route.tags({ path: '' })).toBe('/tags');
|
||||
});
|
||||
});
|
||||
|
||||
describe(Route.systemSettings.name, () => {
|
||||
it('should work', () => {
|
||||
expect(Route.systemSettings()).toBe('/admin/system-settings');
|
||||
|
||||
@@ -14,9 +14,29 @@ export const fromQueueSlug = (slug: string): QueueName | undefined => {
|
||||
};
|
||||
|
||||
type QueryValue = number | string;
|
||||
const asQueryString = (params?: Record<string, QueryValue | undefined>) => {
|
||||
const asQueryString = (
|
||||
params?: Record<string, QueryValue | undefined>,
|
||||
options?: { skipEmptyStrings?: boolean; skipNullValues?: boolean },
|
||||
) => {
|
||||
const { skipEmptyStrings = true, skipNullValues = true } = options ?? {};
|
||||
const items = Object.entries(params ?? {})
|
||||
.filter((item): item is [string, QueryValue] => item[1] !== undefined)
|
||||
.filter((item): item is [string, QueryValue] => {
|
||||
const value = item[1];
|
||||
|
||||
if (value === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skipNullValues && value === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skipEmptyStrings && value === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
||||
|
||||
return items.length === 0 ? '' : `?${items.join('&')}`;
|
||||
@@ -36,22 +56,40 @@ export const Route = {
|
||||
viewAlbumAsset: ({ albumId, assetId }: { albumId: string; assetId: string }) =>
|
||||
`/albums/${albumId}/photos/${assetId}`,
|
||||
|
||||
// buy
|
||||
buy: () => '/buy',
|
||||
|
||||
// explore
|
||||
explore: () => '/explore',
|
||||
places: () => '/places',
|
||||
|
||||
// folders
|
||||
folders: (params?: { path?: string }) => '/folders' + asQueryString(params),
|
||||
|
||||
// libraries
|
||||
libraries: () => '/admin/library-management',
|
||||
newLibrary: () => '/admin/library-management/new',
|
||||
viewLibrary: ({ id }: { id: string }) => `/admin/library-management/${id}`,
|
||||
editLibrary: ({ id }: { id: string }) => `/admin/library-management/${id}/edit`,
|
||||
|
||||
// maintenance
|
||||
maintenanceMode: (params?: { continue?: string }) => '/maintenance' + asQueryString(params),
|
||||
|
||||
// map
|
||||
map: (point?: { zoom: number; lat: number; lng: number }) =>
|
||||
'/map' + (point ? `#${point.zoom}/${point.lat}/${point.lng}` : ''),
|
||||
|
||||
// memories
|
||||
memories: (params?: { id?: string }) => '/memory' + asQueryString(params),
|
||||
|
||||
// partners
|
||||
viewPartner: ({ id }: { id: string }) => `/partners/${id}`,
|
||||
|
||||
// people
|
||||
people: () => '/people',
|
||||
viewPerson: ({ id }: { id: string }, params?: { previousRoute?: string; action?: 'merge' }) =>
|
||||
`/people/${id}` + asQueryString(params),
|
||||
|
||||
// photos
|
||||
photos: (params?: { at?: string }) => '/photos' + asQueryString(params),
|
||||
viewAsset: ({ id }: { id: string }) => `/photos/${id}`,
|
||||
@@ -82,6 +120,10 @@ export const Route = {
|
||||
// system
|
||||
systemSettings: (params?: { isOpen?: OpenQueryParam }) => '/admin/system-settings' + asQueryString(params),
|
||||
systemStatistics: () => '/admin/server-status',
|
||||
systemMaintenance: (params?: { continue?: string }) => '/admin/maintenance' + asQueryString(params),
|
||||
|
||||
// tags
|
||||
tags: (params?: { path?: string }) => '/tags' + asQueryString(params),
|
||||
|
||||
// users
|
||||
users: () => '/admin/users',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { page } from '$app/state';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { notificationManager } from '$lib/stores/notification-manager.svelte';
|
||||
import type { ReleaseEvent } from '$lib/types';
|
||||
import { createEventEmitter } from '$lib/utils/eventemitter';
|
||||
@@ -63,7 +63,7 @@ websocket
|
||||
|
||||
export const openWebsocketConnection = () => {
|
||||
try {
|
||||
if (get(user) || page.url.pathname.startsWith(AppRoute.MAINTENANCE)) {
|
||||
if (get(user) || page.url.pathname.startsWith(Route.maintenanceMode())) {
|
||||
websocket.connect();
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { Route } from '$lib/route';
|
||||
import { maintenanceAuth as maintenanceAuth$ } from '$lib/stores/maintenance.store';
|
||||
import { maintenanceLogin } from '@immich/sdk';
|
||||
|
||||
export function maintenanceCreateUrl(url: URL) {
|
||||
const target = new URL(AppRoute.MAINTENANCE, url.origin);
|
||||
target.searchParams.set('continue', url.pathname + url.search);
|
||||
return target.href;
|
||||
return new URL(Route.maintenanceMode({ continue: url.pathname + url.search }), url.origin).href;
|
||||
}
|
||||
|
||||
export function maintenanceReturnUrl(searchParams: URLSearchParams) {
|
||||
@@ -13,7 +11,7 @@ export function maintenanceReturnUrl(searchParams: URLSearchParams) {
|
||||
}
|
||||
|
||||
export function maintenanceShouldRedirect(maintenanceMode: boolean, currentUrl: URL | Location) {
|
||||
return maintenanceMode !== currentUrl.pathname.startsWith(AppRoute.MAINTENANCE);
|
||||
return maintenanceMode !== currentUrl.pathname.startsWith(Route.maintenanceMode());
|
||||
}
|
||||
|
||||
export const loadMaintenanceAuth = async () => {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import EmptyPlaceholder from '$lib/components/shared-components/empty-placeholder.svelte';
|
||||
import SingleGridRow from '$lib/components/shared-components/single-grid-row.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { Route } from '$lib/route';
|
||||
import { websocketEvents } from '$lib/stores/websocket';
|
||||
import { getAssetThumbnailUrl, getPeopleThumbnailUrl } from '$lib/utils';
|
||||
@@ -47,7 +46,7 @@
|
||||
<div class="flex justify-between">
|
||||
<p class="mb-4 font-medium dark:text-immich-dark-fg">{$t('people')}</p>
|
||||
<a
|
||||
href={AppRoute.PEOPLE}
|
||||
href={Route.people()}
|
||||
class="pe-4 text-sm font-medium hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
|
||||
draggable="false">{$t('view_all')}</a
|
||||
>
|
||||
@@ -55,7 +54,7 @@
|
||||
<SingleGridRow class="grid grid-flow-col md:grid-auto-fill-28 grid-auto-fill-20 gap-x-4">
|
||||
{#snippet children({ itemCount })}
|
||||
{#each people.slice(0, itemCount) as person (person.id)}
|
||||
<a href="{AppRoute.PEOPLE}/{person.id}" class="text-center relative">
|
||||
<a href={Route.viewPerson(person)} class="text-center relative">
|
||||
<ImageThumbnail
|
||||
circle
|
||||
shadow
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
import FavoriteAction from '$lib/components/timeline/actions/FavoriteAction.svelte';
|
||||
import TagAction from '$lib/components/timeline/actions/TagAction.svelte';
|
||||
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
|
||||
import { AppRoute, QueryParameter } from '$lib/constants';
|
||||
import SkipLink from '$lib/elements/SkipLink.svelte';
|
||||
import type { Viewport } from '$lib/managers/timeline-manager/types';
|
||||
import { Route } from '$lib/route';
|
||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { foldersStore } from '$lib/stores/folders.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
@@ -44,11 +44,7 @@
|
||||
|
||||
const handleNavigateToFolder = (folderName: string) => navigateToView(joinPaths(data.tree.path, folderName));
|
||||
|
||||
function getLinkForPath(path: string) {
|
||||
const url = new URL(AppRoute.FOLDERS, globalThis.location.href);
|
||||
url.searchParams.set(QueryParameter.PATH, path);
|
||||
return url.href;
|
||||
}
|
||||
const getLinkForPath = (path: string) => Route.folders({ path });
|
||||
|
||||
afterNavigate(function clearAssetSelection() {
|
||||
// Clear the asset selection when we navigate (like going to another folder)
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
import SearchPeople from '$lib/components/faces-page/people-search.svelte';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||
import { ActionQueryParameterValue, AppRoute, QueryParameter, SessionStorageKey } from '$lib/constants';
|
||||
import { QueryParameter, SessionStorageKey } from '$lib/constants';
|
||||
import PersonMergeSuggestionModal from '$lib/modals/PersonMergeSuggestionModal.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { locale } from '$lib/stores/preferences.store';
|
||||
import { websocketEvents } from '$lib/stores/websocket';
|
||||
import { handlePromiseError } from '$lib/utils';
|
||||
@@ -205,9 +206,7 @@
|
||||
};
|
||||
|
||||
const handleMergePeople = async (detail: PersonResponseDto) => {
|
||||
await goto(
|
||||
`${AppRoute.PEOPLE}/${detail.id}?${QueryParameter.ACTION}=${ActionQueryParameterValue.MERGE}&${QueryParameter.PREVIOUS_ROUTE}=${AppRoute.PEOPLE}`,
|
||||
);
|
||||
await goto(Route.viewPerson(detail, { previousRoute: Route.people(), action: 'merge' }));
|
||||
};
|
||||
|
||||
const onResetSearchBar = async () => {
|
||||
@@ -300,7 +299,7 @@
|
||||
[
|
||||
scrollMemory,
|
||||
{
|
||||
routeStartsWith: AppRoute.PEOPLE,
|
||||
routeStartsWith: Route.people(),
|
||||
beforeSave: () => {
|
||||
if (currentPage) {
|
||||
sessionStorage.setItem(SessionStorageKey.INFINITE_SCROLL_PAGE, currentPage.toString());
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
import TagAction from '$lib/components/timeline/actions/TagAction.svelte';
|
||||
import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte';
|
||||
import Timeline from '$lib/components/timeline/Timeline.svelte';
|
||||
import { AppRoute, PersonPageViewMode, QueryParameter, SessionStorageKey } from '$lib/constants';
|
||||
import { PersonPageViewMode, QueryParameter, SessionStorageKey } from '$lib/constants';
|
||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||
import PersonMergeSuggestionModal from '$lib/modals/PersonMergeSuggestionModal.svelte';
|
||||
@@ -219,7 +219,7 @@
|
||||
await updateAssetCount();
|
||||
return { merged: true };
|
||||
}
|
||||
await goto(`${AppRoute.PEOPLE}/${personToBeMergedInto.id}`, { replaceState: true });
|
||||
await goto(Route.viewPerson(personToBeMergedInto), { replaceState: true });
|
||||
return { merged: true };
|
||||
};
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
<main
|
||||
class="relative z-0 h-dvh overflow-hidden px-2 md:px-6 md:pt-(--navbar-height-md) pt-(--navbar-height)"
|
||||
use:scrollMemoryClearer={{
|
||||
routeStartsWith: AppRoute.PEOPLE,
|
||||
routeStartsWith: Route.people(),
|
||||
beforeClear: () => {
|
||||
sessionStorage.removeItem(SessionStorageKey.INFINITE_SCROLL_PAGE);
|
||||
},
|
||||
|
||||
@@ -21,9 +21,10 @@
|
||||
import SelectAllAssets from '$lib/components/timeline/actions/SelectAllAction.svelte';
|
||||
import SetVisibilityAction from '$lib/components/timeline/actions/SetVisibilityAction.svelte';
|
||||
import TagAction from '$lib/components/timeline/actions/TagAction.svelte';
|
||||
import { AppRoute, AssetAction, QueryParameter } from '$lib/constants';
|
||||
import { AssetAction } from '$lib/constants';
|
||||
import SkipLink from '$lib/elements/SkipLink.svelte';
|
||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { getTagActions } from '$lib/services/tag.service';
|
||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { preferences, user } from '$lib/stores/user.store';
|
||||
@@ -50,11 +51,7 @@
|
||||
|
||||
const handleNavigation = (tag: string) => navigateToView(joinPaths(data.path, tag));
|
||||
|
||||
const getLink = (path: string) => {
|
||||
const url = new URL(AppRoute.TAGS, globalThis.location.href);
|
||||
url.searchParams.set(QueryParameter.PATH, path);
|
||||
return url.href;
|
||||
};
|
||||
const getLink = (path: string) => Route.tags({ path });
|
||||
|
||||
const navigateToView = (path: string) => goto(getLink(path));
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
import AppleHeader from '$lib/components/shared-components/apple-header.svelte';
|
||||
import NavigationLoadingBar from '$lib/components/shared-components/navigation-loading-bar.svelte';
|
||||
import UploadPanel from '$lib/components/shared-components/upload-panel.svelte';
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
|
||||
import { themeManager } from '$lib/managers/theme-manager.svelte';
|
||||
@@ -89,7 +88,7 @@
|
||||
});
|
||||
|
||||
$effect.pre(() => {
|
||||
if ($user || page.url.pathname.startsWith(AppRoute.MAINTENANCE)) {
|
||||
if ($user || page.url.pathname.startsWith(Route.maintenanceMode())) {
|
||||
openWebsocketConnection();
|
||||
} else {
|
||||
closeWebsocketConnection();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { serverConfigManager } from '$lib/managers/server-config-manager.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import { getFormatter } from '$lib/utils/i18n';
|
||||
@@ -15,7 +14,7 @@ export const load = (async ({ fetch }) => {
|
||||
await init(fetch);
|
||||
|
||||
if (serverConfigManager.value.maintenanceMode) {
|
||||
redirect(307, AppRoute.MAINTENANCE);
|
||||
redirect(307, Route.maintenanceMode());
|
||||
}
|
||||
|
||||
const authenticated = await loadUser();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AppRoute, OpenQueryParam } from '$lib/constants';
|
||||
import { OpenQueryParam } from '$lib/constants';
|
||||
import { Route } from '$lib/route';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
@@ -34,7 +34,7 @@ export const load = (({ url }) => {
|
||||
// https://my.immich.app/link?target=activate_license&licenseKey=IMCL-9XC3-T4S3-37BU-GGJ5-8MWP-F2Y1-BGEX-AQTF
|
||||
const licenseKey = queryParams.get('licenseKey');
|
||||
const activationKey = queryParams.get('activationKey');
|
||||
const redirectUrl = new URL(AppRoute.BUY, url.origin);
|
||||
const redirectUrl = new URL(Route.buy(), url.origin);
|
||||
|
||||
if (licenseKey) {
|
||||
redirectUrl.searchParams.append('licenseKey', licenseKey);
|
||||
|
||||
Reference in New Issue
Block a user