chore(web): migration svelte 5 syntax (#13883)

This commit is contained in:
Alex 2024-11-14 08:43:25 -06:00 committed by GitHub
parent 9203a61709
commit 0b3742cf13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
310 changed files with 6435 additions and 4176 deletions

View file

@ -1,4 +1,4 @@
<script lang="ts" context="module">
<script lang="ts" module>
void maplibregl.setRTLTextPlugin(mapboxRtlUrl, true);
</script>
@ -6,12 +6,13 @@
import Icon from '$lib/components/elements/icon.svelte';
import { Theme } from '$lib/constants';
import { colorTheme, mapSettings } from '$lib/stores/preferences.store';
import { serverConfig } from '$lib/stores/server-config.store';
import { getAssetThumbnailUrl, handlePromiseError } from '$lib/utils';
import { getServerConfig, type MapMarkerResponseDto } from '@immich/sdk';
import { type MapMarkerResponseDto } from '@immich/sdk';
import mapboxRtlUrl from '@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js?url';
import { mdiCog, mdiMap, mdiMapMarker } from '@mdi/js';
import type { Feature, GeoJsonProperties, Geometry, Point } from 'geojson';
import type { GeoJSONSource, LngLatLike, StyleSpecification } from 'maplibre-gl';
import type { GeoJSONSource, LngLatLike } from 'maplibre-gl';
import maplibregl from 'maplibre-gl';
import { t } from 'svelte-i18n';
import {
@ -30,14 +31,43 @@
type Map,
} from 'svelte-maplibre';
export let mapMarkers: MapMarkerResponseDto[];
export let showSettingsModal: boolean | undefined = undefined;
export let zoom: number | undefined = undefined;
export let center: LngLatLike | undefined = undefined;
export let hash = false;
export let simplified = false;
export let clickable = false;
export let useLocationPin = false;
interface Props {
mapMarkers: MapMarkerResponseDto[];
showSettingsModal?: boolean | undefined;
zoom?: number | undefined;
center?: LngLatLike | undefined;
hash?: boolean;
simplified?: boolean;
clickable?: boolean;
useLocationPin?: boolean;
onOpenInMapView?: (() => Promise<void> | void) | undefined;
onSelect?: (assetIds: string[]) => void;
onClickPoint?: ({ lat, lng }: { lat: number; lng: number }) => void;
popup?: import('svelte').Snippet<[{ marker: MapMarkerResponseDto }]>;
}
let {
mapMarkers = $bindable(),
showSettingsModal = $bindable(undefined),
zoom = undefined,
center = $bindable(undefined),
hash = false,
simplified = false,
clickable = false,
useLocationPin = false,
onOpenInMapView = undefined,
onSelect = () => {},
onClickPoint = () => {},
popup,
}: Props = $props();
let map: maplibregl.Map | undefined = $state();
let marker: maplibregl.Marker | null = null;
const theme = $derived($mapSettings.allowDarkMode ? $colorTheme.value : Theme.LIGHT);
const styleUrl = $derived(theme === Theme.DARK ? $serverConfig.mapDarkStyleUrl : $serverConfig.mapLightStyleUrl);
const style = $derived(fetch(styleUrl).then((response) => response.json()));
export function addClipMapMarker(lng: number, lat: number) {
if (map) {
if (marker) {
@ -46,26 +76,9 @@
center = { lng, lat };
marker = new maplibregl.Marker().setLngLat([lng, lat]).addTo(map);
map.setZoom(15);
}
}
export let onOpenInMapView: (() => Promise<void> | void) | undefined = undefined;
export let onSelect: (assetIds: string[]) => void = () => {};
export let onClickPoint: ({ lat, lng }: { lat: number; lng: number }) => void = () => {};
let map: maplibregl.Map;
let marker: maplibregl.Marker | null = null;
// svelte-ignore reactive_declaration_non_reactive_property
$: style = (async () => {
const config = await getServerConfig();
const theme = $mapSettings.allowDarkMode ? $colorTheme.value : Theme.LIGHT;
const styleUrl = theme === Theme.DARK ? config.mapDarkStyleUrl : config.mapLightStyleUrl;
const style = await fetch(styleUrl).then((response) => response.json());
return style as StyleSpecification;
})();
function handleAssetClick(assetId: string, map: Map | null) {
if (!map) {
return;
@ -93,7 +106,9 @@
marker.remove();
}
marker = new maplibregl.Marker().setLngLat([lng, lat]).addTo(map);
if (map) {
marker = new maplibregl.Marker().setLngLat([lng, lat]).addTo(map);
}
}
}
@ -135,92 +150,96 @@
{zoom}
attributionControl={false}
diffStyleUpdates={true}
let:map
on:load={(event) => event.detail.setMaxZoom(18)}
on:load={(event) => event.detail.on('click', handleMapClick)}
bind:map
>
<NavigationControl position="top-left" showCompass={!simplified} />
{#snippet children({ map }: { map: maplibregl.Map })}
<NavigationControl position="top-left" showCompass={!simplified} />
{#if !simplified}
<GeolocateControl position="top-left" />
<FullscreenControl position="top-left" />
<ScaleControl />
<AttributionControl compact={false} />
{/if}
{#if !simplified}
<GeolocateControl position="top-left" />
<FullscreenControl position="top-left" />
<ScaleControl />
<AttributionControl compact={false} />
{/if}
{#if showSettingsModal !== undefined}
<Control>
<ControlGroup>
<ControlButton on:click={() => (showSettingsModal = true)}><Icon path={mdiCog} size="100%" /></ControlButton>
</ControlGroup>
</Control>
{/if}
{#if showSettingsModal !== undefined}
<Control>
<ControlGroup>
<ControlButton on:click={() => (showSettingsModal = true)}><Icon path={mdiCog} size="100%" /></ControlButton
>
</ControlGroup>
</Control>
{/if}
{#if onOpenInMapView}
<Control position="top-right">
<ControlGroup>
<ControlButton on:click={() => onOpenInMapView()}>
<Icon title={$t('open_in_map_view')} path={mdiMap} size="100%" />
</ControlButton>
</ControlGroup>
</Control>
{/if}
{#if onOpenInMapView}
<Control position="top-right">
<ControlGroup>
<ControlButton on:click={() => onOpenInMapView()}>
<Icon title={$t('open_in_map_view')} path={mdiMap} size="100%" />
</ControlButton>
</ControlGroup>
</Control>
{/if}
<GeoJSON
data={{
type: 'FeatureCollection',
features: mapMarkers.map((marker) => asFeature(marker)),
}}
id="geojson"
cluster={{ radius: 500, maxZoom: 24 }}
>
<MarkerLayer
applyToClusters
asButton
let:feature
on:click={(event) => handlePromiseError(handleClusterClick(event.detail.feature.properties?.cluster_id, map))}
>
<div
class="rounded-full w-[40px] h-[40px] bg-immich-primary text-immich-gray flex justify-center items-center font-mono font-bold shadow-lg hover:bg-immich-dark-primary transition-all duration-200 hover:text-immich-dark-bg opacity-90"
>
{feature.properties?.point_count}
</div>
</MarkerLayer>
<MarkerLayer
applyToClusters={false}
asButton
let:feature
on:click={(event) => {
if (!$$slots.popup) {
handleAssetClick(event.detail.feature.properties?.id, map);
}
<GeoJSON
data={{
type: 'FeatureCollection',
features: mapMarkers.map((marker) => asFeature(marker)),
}}
id="geojson"
cluster={{ radius: 500, maxZoom: 24 }}
>
{#if useLocationPin}
<Icon
path={mdiMapMarker}
size="50px"
class="location-pin dark:text-immich-dark-primary text-immich-primary"
/>
{:else}
<img
src={getAssetThumbnailUrl(feature.properties?.id)}
class="rounded-full w-[60px] h-[60px] border-2 border-immich-primary shadow-lg hover:border-immich-dark-primary transition-all duration-200 hover:scale-150 object-cover bg-immich-primary"
alt={feature.properties?.city && feature.properties.country
? $t('map_marker_for_images', {
values: { city: feature.properties.city, country: feature.properties.country },
})
: $t('map_marker_with_image')}
/>
{/if}
{#if $$slots.popup}
<Popup offset={[0, -30]} openOn="click" closeOnClickOutside>
<slot name="popup" marker={asMarker(feature)} />
</Popup>
{/if}
</MarkerLayer>
</GeoJSON>
<MarkerLayer
applyToClusters
asButton
on:click={(event) => handlePromiseError(handleClusterClick(event.detail.feature.properties?.cluster_id, map))}
>
{#snippet children({ feature }: { feature: maplibregl.Feature })}
<div
class="rounded-full w-[40px] h-[40px] bg-immich-primary text-immich-gray flex justify-center items-center font-mono font-bold shadow-lg hover:bg-immich-dark-primary transition-all duration-200 hover:text-immich-dark-bg opacity-90"
>
{feature.properties?.point_count}
</div>
{/snippet}
</MarkerLayer>
<MarkerLayer
applyToClusters={false}
asButton
on:click={(event) => {
if (!popup) {
handleAssetClick(event.detail.feature.properties?.id, map);
}
}}
>
{#snippet children({ feature }: { feature: Feature<Geometry, GeoJsonProperties> })}
{#if useLocationPin}
<Icon
path={mdiMapMarker}
size="50px"
class="location-pin dark:text-immich-dark-primary text-immich-primary"
/>
{:else}
<img
src={getAssetThumbnailUrl(feature.properties?.id)}
class="rounded-full w-[60px] h-[60px] border-2 border-immich-primary shadow-lg hover:border-immich-dark-primary transition-all duration-200 hover:scale-150 object-cover bg-immich-primary"
alt={feature.properties?.city && feature.properties.country
? $t('map_marker_for_images', {
values: { city: feature.properties.city, country: feature.properties.country },
})
: $t('map_marker_with_image')}
/>
{/if}
{#if popup}
<Popup offset={[0, -30]} openOn="click" closeOnClickOutside>
{@render popup?.({ marker: asMarker(feature) })}
</Popup>
{/if}
{/snippet}
</MarkerLayer>
</GeoJSON>
{/snippet}
</MapLibre>
<style>
.location-pin {