mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
feat(web+server): map improvements (#2498)
* feat(web+server): map improvements * add number format double to fix mobile
This commit is contained in:
@@ -2,22 +2,15 @@ import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api, user } }) => {
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: mapMarkers } = await api.assetApi.getMapMarkers();
|
||||
|
||||
return {
|
||||
user,
|
||||
mapMarkers,
|
||||
meta: {
|
||||
title: 'Map'
|
||||
}
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Map'
|
||||
}
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
|
||||
@@ -1,27 +1,43 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from '../map/$types';
|
||||
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
|
||||
import Portal from '$lib/components/shared-components/portal/portal.svelte';
|
||||
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 Portal from '$lib/components/shared-components/portal/portal.svelte';
|
||||
import {
|
||||
assetInteractionStore,
|
||||
isViewingAssetStoreState,
|
||||
viewingAssetStoreState
|
||||
} from '$lib/stores/asset-interaction.store';
|
||||
import { mapSettings } from '$lib/stores/preferences.store';
|
||||
import { MapMarkerResponseDto, api } from '@api';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import Cog from 'svelte-material-icons/Cog.svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let initialMapCenter: [number, number] = [48, 11];
|
||||
|
||||
$: {
|
||||
if (data.mapMarkers.length) {
|
||||
let firstMarker = data.mapMarkers[0];
|
||||
initialMapCenter = [firstMarker.lat, firstMarker.lon];
|
||||
}
|
||||
}
|
||||
|
||||
let mapMarkersPromise: Promise<MapMarkerResponseDto[]>;
|
||||
let abortController = new AbortController();
|
||||
let viewingAssets: string[] = [];
|
||||
let viewingAssetCursor = 0;
|
||||
let showSettingsModal = false;
|
||||
|
||||
onMount(() => {
|
||||
mapMarkersPromise = loadMapMarkers();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
abortController.abort();
|
||||
assetInteractionStore.clearMultiselect();
|
||||
assetInteractionStore.setIsViewingAsset(false);
|
||||
});
|
||||
|
||||
async function loadMapMarkers() {
|
||||
const { data } = await api.assetApi.getMapMarkers($mapSettings.onlyFavorites || undefined, {
|
||||
signal: abortController.signal
|
||||
});
|
||||
return data;
|
||||
}
|
||||
|
||||
function onViewAssets(assets: string[]) {
|
||||
assetInteractionStore.setViewingAssetId(assets[0]);
|
||||
@@ -40,27 +56,55 @@
|
||||
assetInteractionStore.setViewingAssetId(viewingAssets[--viewingAssetCursor]);
|
||||
}
|
||||
}
|
||||
|
||||
function getMapCenter(mapMarkers: MapMarkerResponseDto[]): [number, number] {
|
||||
const marker = mapMarkers[0];
|
||||
if (marker) {
|
||||
return [marker.lat, marker.lon];
|
||||
}
|
||||
|
||||
return [48, 11];
|
||||
}
|
||||
</script>
|
||||
|
||||
<UserPageLayout user={data.user} title={data.meta.title}>
|
||||
<div slot="buttons" />
|
||||
|
||||
<div class="h-full w-full relative z-0">
|
||||
{#await import('$lib/components/shared-components/leaflet') then { Map, TileLayer, AssetMarkerCluster }}
|
||||
<Map latlng={initialMapCenter} zoom={7}>
|
||||
<TileLayer
|
||||
allowDarkMode={true}
|
||||
urlTemplate={'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'}
|
||||
<div class="h-full w-full isolate">
|
||||
{#await import('$lib/components/shared-components/leaflet') then { Map, TileLayer, AssetMarkerCluster, Control }}
|
||||
{#await mapMarkersPromise then mapMarkers}
|
||||
<Map
|
||||
center={getMapCenter(mapMarkers)}
|
||||
zoom={7}
|
||||
allowDarkMode={$mapSettings.allowDarkMode}
|
||||
options={{
|
||||
attribution:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
maxBounds: [
|
||||
[-90, -180],
|
||||
[90, 180]
|
||||
],
|
||||
minZoom: 3
|
||||
}}
|
||||
/>
|
||||
<AssetMarkerCluster
|
||||
markers={data.mapMarkers}
|
||||
on:view={(event) => onViewAssets(event.detail.assets)}
|
||||
/>
|
||||
</Map>
|
||||
>
|
||||
<TileLayer
|
||||
urlTemplate={'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'}
|
||||
options={{
|
||||
attribution:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}}
|
||||
/>
|
||||
<AssetMarkerCluster
|
||||
markers={mapMarkers}
|
||||
on:view={(event) => onViewAssets(event.detail.assets)}
|
||||
/>
|
||||
<Control>
|
||||
<button
|
||||
class="flex justify-center items-center bg-white text-black/70 w-8 h-8 font-bold rounded-sm border-2 border-black/20 hover:bg-gray-50 focus:bg-gray-50"
|
||||
title="Open map settings"
|
||||
on:click={() => (showSettingsModal = true)}
|
||||
>
|
||||
<Cog size="100%" class="p-1" />
|
||||
</button>
|
||||
</Control>
|
||||
</Map>
|
||||
{/await}
|
||||
{/await}
|
||||
</div>
|
||||
</UserPageLayout>
|
||||
@@ -78,3 +122,20 @@
|
||||
/>
|
||||
{/if}
|
||||
</Portal>
|
||||
|
||||
{#if showSettingsModal}
|
||||
<MapSettingsModal
|
||||
settings={{ ...$mapSettings }}
|
||||
on:close={() => (showSettingsModal = false)}
|
||||
on:save={async ({ detail }) => {
|
||||
const shouldUpdate = detail.onlyFavorites !== $mapSettings.onlyFavorites;
|
||||
showSettingsModal = false;
|
||||
$mapSettings = detail;
|
||||
|
||||
if (shouldUpdate) {
|
||||
const markers = await loadMapMarkers();
|
||||
mapMarkersPromise = Promise.resolve(markers);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user