diff --git a/web/src/lib/components/album-page/album-map.svelte b/web/src/lib/components/album-page/album-map.svelte
index 8230dea92e..871e26b4f9 100644
--- a/web/src/lib/components/album-page/album-map.svelte
+++ b/web/src/lib/components/album-page/album-map.svelte
@@ -130,6 +130,7 @@
               clickable={false}
               bind:mapMarkers
               onSelect={onViewAssets}
+              showSettings={false}
             />
           {/await}
         </div>
diff --git a/web/src/lib/components/asset-viewer/detail-panel.svelte b/web/src/lib/components/asset-viewer/detail-panel.svelte
index 15bc42d001..d672b1a8b0 100644
--- a/web/src/lib/components/asset-viewer/detail-panel.svelte
+++ b/web/src/lib/components/asset-viewer/detail-panel.svelte
@@ -494,6 +494,7 @@
           },
         ]}
         center={latlng}
+        showSettings={false}
         zoom={12.5}
         simplified
         useLocationPin
diff --git a/web/src/lib/components/map-page/map-settings-modal.svelte b/web/src/lib/components/map-page/map-settings-modal.svelte
deleted file mode 100644
index c1ee1e0b80..0000000000
--- a/web/src/lib/components/map-page/map-settings-modal.svelte
+++ /dev/null
@@ -1,133 +0,0 @@
-<script lang="ts">
-  import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
-  import SettingSelect from '$lib/components/shared-components/settings/setting-select.svelte';
-  import type { MapSettings } from '$lib/stores/preferences.store';
-  import { Button, Field, Stack, Switch } from '@immich/ui';
-  import { Duration } from 'luxon';
-  import { t } from 'svelte-i18n';
-  import { fly } from 'svelte/transition';
-  import DateInput from '../elements/date-input.svelte';
-
-  interface Props {
-    settings: MapSettings;
-    onClose: () => void;
-    onSave: (settings: MapSettings) => void;
-  }
-
-  let { settings: initialValues, onClose, onSave }: Props = $props();
-  let settings = $state(initialValues);
-
-  let customDateRange = $state(!!settings.dateAfter || !!settings.dateBefore);
-
-  const onsubmit = (event: Event) => {
-    event.preventDefault();
-    onSave(settings);
-  };
-</script>
-
-<form {onsubmit}>
-  <FullScreenModal title={$t('map_settings')} {onClose}>
-    <Stack gap={4}>
-      <Field label={$t('allow_dark_mode')}>
-        <Switch bind:checked={settings.allowDarkMode} />
-      </Field>
-      <Field label={$t('only_favorites')}>
-        <Switch bind:checked={settings.onlyFavorites} />
-      </Field>
-      <Field label={$t('include_archived')}>
-        <Switch bind:checked={settings.includeArchived} />
-      </Field>
-      <Field label={$t('include_shared_partner_assets')}>
-        <Switch bind:checked={settings.withPartners} />
-      </Field>
-      <Field label={$t('include_shared_albums')}>
-        <Switch bind:checked={settings.withSharedAlbums} />
-      </Field>
-
-      {#if customDateRange}
-        <div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4">
-          <div class="flex items-center justify-between gap-8">
-            <label class="immich-form-label shrink-0 text-sm" for="date-after">{$t('date_after')}</label>
-            <DateInput
-              class="immich-form-input w-40"
-              type="date"
-              id="date-after"
-              max={settings.dateBefore}
-              bind:value={settings.dateAfter}
-            />
-          </div>
-          <div class="flex items-center justify-between gap-8">
-            <label class="immich-form-label shrink-0 text-sm" for="date-before">{$t('date_before')}</label>
-            <DateInput class="immich-form-input w-40" type="date" id="date-before" bind:value={settings.dateBefore} />
-          </div>
-          <div class="flex justify-center text-xs">
-            <Button
-              color="primary"
-              size="small"
-              variant="ghost"
-              onclick={() => {
-                customDateRange = false;
-                settings.dateAfter = '';
-                settings.dateBefore = '';
-              }}
-            >
-              {$t('remove_custom_date_range')}
-            </Button>
-          </div>
-        </div>
-      {:else}
-        <div in:fly={{ y: -10, duration: 200 }} class="flex flex-col gap-1">
-          <SettingSelect
-            label={$t('date_range')}
-            name="date-range"
-            bind:value={settings.relativeDate}
-            options={[
-              {
-                value: '',
-                text: $t('all'),
-              },
-              {
-                value: Duration.fromObject({ hours: 24 }).toISO() || '',
-                text: $t('past_durations.hours', { values: { hours: 24 } }),
-              },
-              {
-                value: Duration.fromObject({ days: 7 }).toISO() || '',
-                text: $t('past_durations.days', { values: { days: 7 } }),
-              },
-              {
-                value: Duration.fromObject({ days: 30 }).toISO() || '',
-                text: $t('past_durations.days', { values: { days: 30 } }),
-              },
-              {
-                value: Duration.fromObject({ years: 1 }).toISO() || '',
-                text: $t('past_durations.years', { values: { years: 1 } }),
-              },
-              {
-                value: Duration.fromObject({ years: 3 }).toISO() || '',
-                text: $t('past_durations.years', { values: { years: 3 } }),
-              },
-            ]}
-          />
-          <div class="text-xs">
-            <Button
-              color="primary"
-              size="small"
-              variant="ghost"
-              onclick={() => {
-                customDateRange = true;
-                settings.relativeDate = '';
-              }}
-            >
-              {$t('use_custom_date_range')}
-            </Button>
-          </div>
-        </div>
-      {/if}
-    </Stack>
-
-    {#snippet stickyBottom()}
-      <Button color="secondary" shape="round" fullWidth onclick={onClose}>{$t('cancel')}</Button>
-      <Button type="submit" shape="round" fullWidth>{$t('save')}</Button>
-    {/snippet}
-  </FullScreenModal>
-</form>
diff --git a/web/src/lib/components/shared-components/change-location.svelte b/web/src/lib/components/shared-components/change-location.svelte
index 3539945911..e502d9aeda 100644
--- a/web/src/lib/components/shared-components/change-location.svelte
+++ b/web/src/lib/components/shared-components/change-location.svelte
@@ -190,6 +190,7 @@
             simplified={true}
             clickable={true}
             onClickPoint={(selected) => (point = selected)}
+            showSettings={false}
           />
         {/await}
       </div>
diff --git a/web/src/lib/components/shared-components/map/map.svelte b/web/src/lib/components/shared-components/map/map.svelte
index 5adeb2f00f..5742799409 100644
--- a/web/src/lib/components/shared-components/map/map.svelte
+++ b/web/src/lib/components/shared-components/map/map.svelte
@@ -9,15 +9,20 @@
 <script lang="ts">
   import Icon from '$lib/components/elements/icon.svelte';
   import { Theme } from '$lib/constants';
+  import { modalManager } from '$lib/managers/modal-manager.svelte';
   import { themeManager } from '$lib/managers/theme-manager.svelte';
+  import MapSettingsModal from '$lib/modals/MapSettingsModal.svelte';
   import { mapSettings } from '$lib/stores/preferences.store';
   import { serverConfig } from '$lib/stores/server-config.store';
   import { getAssetThumbnailUrl, handlePromiseError } from '$lib/utils';
-  import { type MapMarkerResponseDto } from '@immich/sdk';
+  import { getMapMarkers, 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 { isEqual, omit } from 'lodash-es';
+  import { DateTime, Duration } from 'luxon';
   import maplibregl, { GlobeControl, type GeoJSONSource, type LngLatLike } from 'maplibre-gl';
+  import { onDestroy, onMount } from 'svelte';
   import { t } from 'svelte-i18n';
   import {
     AttributionControl,
@@ -36,8 +41,8 @@
   } from 'svelte-maplibre';
 
   interface Props {
-    mapMarkers: MapMarkerResponseDto[];
-    showSettingsModal?: boolean | undefined;
+    mapMarkers?: MapMarkerResponseDto[];
+    showSettings?: boolean;
     zoom?: number | undefined;
     center?: LngLatLike | undefined;
     hash?: boolean;
@@ -51,8 +56,8 @@
   }
 
   let {
-    mapMarkers = $bindable(),
-    showSettingsModal = $bindable(undefined),
+    mapMarkers = $bindable([]),
+    showSettings = true,
     zoom = undefined,
     center = $bindable(undefined),
     hash = false,
@@ -67,6 +72,7 @@
 
   let map: maplibregl.Map | undefined = $state();
   let marker: maplibregl.Marker | null = null;
+  let abortController: AbortController;
 
   const theme = $derived($mapSettings.allowDarkMode ? themeManager.value : Theme.LIGHT);
   const styleUrl = $derived(theme === Theme.DARK ? $serverConfig.mapDarkStyleUrl : $serverConfig.mapLightStyleUrl);
@@ -143,6 +149,72 @@
     };
   };
 
+  function getFileCreatedDates() {
+    const { relativeDate, dateAfter, dateBefore } = $mapSettings;
+
+    if (relativeDate) {
+      const duration = Duration.fromISO(relativeDate);
+      return {
+        fileCreatedAfter: duration.isValid ? DateTime.now().minus(duration).toISO() : undefined,
+      };
+    }
+
+    try {
+      return {
+        fileCreatedAfter: dateAfter ? new Date(dateAfter).toISOString() : undefined,
+        fileCreatedBefore: dateBefore ? new Date(dateBefore).toISOString() : undefined,
+      };
+    } catch {
+      $mapSettings.dateAfter = '';
+      $mapSettings.dateBefore = '';
+      return {};
+    }
+  }
+
+  async function loadMapMarkers() {
+    if (abortController) {
+      abortController.abort();
+    }
+    abortController = new AbortController();
+
+    const { includeArchived, onlyFavorites, withPartners, withSharedAlbums } = $mapSettings;
+    const { fileCreatedAfter, fileCreatedBefore } = getFileCreatedDates();
+
+    return await getMapMarkers(
+      {
+        isArchived: includeArchived && undefined,
+        isFavorite: onlyFavorites || undefined,
+        fileCreatedAfter: fileCreatedAfter || undefined,
+        fileCreatedBefore,
+        withPartners: withPartners || undefined,
+        withSharedAlbums: withSharedAlbums || undefined,
+      },
+      {
+        signal: abortController.signal,
+      },
+    );
+  }
+
+  const handleSettingsClick = async () => {
+    const settings = await modalManager.open(MapSettingsModal, { settings: { ...$mapSettings } });
+    if (settings) {
+      const shouldUpdate = !isEqual(omit(settings, 'allowDarkMode'), omit($mapSettings, 'allowDarkMode'));
+      $mapSettings = settings;
+
+      if (shouldUpdate) {
+        mapMarkers = await loadMapMarkers();
+      }
+    }
+  };
+
+  onMount(async () => {
+    mapMarkers = await loadMapMarkers();
+  });
+
+  onDestroy(() => {
+    abortController.abort();
+  });
+
   $effect(() => {
     map?.setStyle(styleUrl, {
       transformStyle: (previousStyle, nextStyle) => {
@@ -199,10 +271,10 @@
       <AttributionControl compact={false} />
     {/if}
 
-    {#if showSettingsModal !== undefined}
+    {#if showSettings}
       <Control>
         <ControlGroup>
-          <ControlButton onclick={() => (showSettingsModal = true)}><Icon path={mdiCog} size="100%" /></ControlButton>
+          <ControlButton onclick={handleSettingsClick}><Icon path={mdiCog} size="100%" /></ControlButton>
         </ControlGroup>
       </Control>
     {/if}
diff --git a/web/src/lib/modals/MapSettingsModal.svelte b/web/src/lib/modals/MapSettingsModal.svelte
new file mode 100644
index 0000000000..e7bef2ecaf
--- /dev/null
+++ b/web/src/lib/modals/MapSettingsModal.svelte
@@ -0,0 +1,135 @@
+<script lang="ts">
+  import SettingSelect from '$lib/components/shared-components/settings/setting-select.svelte';
+  import type { MapSettings } from '$lib/stores/preferences.store';
+  import { Button, Field, Modal, ModalBody, ModalFooter, Stack, Switch } from '@immich/ui';
+  import { Duration } from 'luxon';
+  import { t } from 'svelte-i18n';
+  import { fly } from 'svelte/transition';
+  import DateInput from '../components/elements/date-input.svelte';
+
+  interface Props {
+    settings: MapSettings;
+    onClose: (settings?: MapSettings) => void;
+  }
+
+  let { settings: initialValues, onClose }: Props = $props();
+  let settings = $state(initialValues);
+
+  let customDateRange = $state(!!settings.dateAfter || !!settings.dateBefore);
+
+  const onsubmit = (event: Event) => {
+    event.preventDefault();
+    onClose(settings);
+  };
+</script>
+
+<Modal title={$t('map_settings')} {onClose} size="small">
+  <ModalBody>
+    <form {onsubmit} id="map-settings-form">
+      <Stack gap={4}>
+        <Field label={$t('allow_dark_mode')}>
+          <Switch bind:checked={settings.allowDarkMode} />
+        </Field>
+        <Field label={$t('only_favorites')}>
+          <Switch bind:checked={settings.onlyFavorites} />
+        </Field>
+        <Field label={$t('include_archived')}>
+          <Switch bind:checked={settings.includeArchived} />
+        </Field>
+        <Field label={$t('include_shared_partner_assets')}>
+          <Switch bind:checked={settings.withPartners} />
+        </Field>
+        <Field label={$t('include_shared_albums')}>
+          <Switch bind:checked={settings.withSharedAlbums} />
+        </Field>
+
+        {#if customDateRange}
+          <div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4">
+            <div class="flex items-center justify-between gap-8">
+              <label class="immich-form-label shrink-0 text-sm" for="date-after">{$t('date_after')}</label>
+              <DateInput
+                class="immich-form-input w-40"
+                type="date"
+                id="date-after"
+                max={settings.dateBefore}
+                bind:value={settings.dateAfter}
+              />
+            </div>
+            <div class="flex items-center justify-between gap-8">
+              <label class="immich-form-label shrink-0 text-sm" for="date-before">{$t('date_before')}</label>
+              <DateInput class="immich-form-input w-40" type="date" id="date-before" bind:value={settings.dateBefore} />
+            </div>
+            <div class="flex justify-center text-xs">
+              <Button
+                color="primary"
+                size="small"
+                variant="ghost"
+                onclick={() => {
+                  customDateRange = false;
+                  settings.dateAfter = '';
+                  settings.dateBefore = '';
+                }}
+              >
+                {$t('remove_custom_date_range')}
+              </Button>
+            </div>
+          </div>
+        {:else}
+          <div in:fly={{ y: -10, duration: 200 }} class="flex flex-col gap-1">
+            <SettingSelect
+              label={$t('date_range')}
+              name="date-range"
+              bind:value={settings.relativeDate}
+              options={[
+                {
+                  value: '',
+                  text: $t('all'),
+                },
+                {
+                  value: Duration.fromObject({ hours: 24 }).toISO() || '',
+                  text: $t('past_durations.hours', { values: { hours: 24 } }),
+                },
+                {
+                  value: Duration.fromObject({ days: 7 }).toISO() || '',
+                  text: $t('past_durations.days', { values: { days: 7 } }),
+                },
+                {
+                  value: Duration.fromObject({ days: 30 }).toISO() || '',
+                  text: $t('past_durations.days', { values: { days: 30 } }),
+                },
+                {
+                  value: Duration.fromObject({ years: 1 }).toISO() || '',
+                  text: $t('past_durations.years', { values: { years: 1 } }),
+                },
+                {
+                  value: Duration.fromObject({ years: 3 }).toISO() || '',
+                  text: $t('past_durations.years', { values: { years: 3 } }),
+                },
+              ]}
+            />
+            <div class="text-xs">
+              <Button
+                color="primary"
+                size="small"
+                variant="ghost"
+                onclick={() => {
+                  customDateRange = true;
+                  settings.relativeDate = '';
+                }}
+              >
+                {$t('use_custom_date_range')}
+              </Button>
+            </div>
+          </div>
+        {/if}
+      </Stack>
+    </form>
+  </ModalBody>
+
+  <ModalFooter>
+    <div class="flex gap-3 w-full">
+      <Button color="secondary" shape="round" fullWidth onclick={() => onClose()}>{$t('cancel')}</Button>
+      <Button type="submit" shape="round" fullWidth form="map-settings-form">{$t('save')}</Button>
+    </div>
+  </ModalFooter>
+</Modal>
diff --git a/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/+page.svelte
index 0a71f35ff2..b1fff3a0cd 100644
--- a/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/+page.svelte
+++ b/web/src/routes/(user)/map/[[photos=photos]]/[[assetId=id]]/+page.svelte
@@ -3,21 +3,15 @@
 
   import { goto } from '$app/navigation';
   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';
   import Portal from '$lib/components/shared-components/portal/portal.svelte';
   import { AppRoute } from '$lib/constants';
   import { assetViewingStore } from '$lib/stores/asset-viewing.store';
-  import type { MapSettings } from '$lib/stores/preferences.store';
-  import { mapSettings } from '$lib/stores/preferences.store';
   import { featureFlags } from '$lib/stores/server-config.store';
-  import { getMapMarkers, type MapMarkerResponseDto } from '@immich/sdk';
-  import { isEqual } from 'lodash-es';
-  import { DateTime, Duration } from 'luxon';
-  import { onDestroy, onMount } from 'svelte';
-  import type { PageData } from './$types';
   import { handlePromiseError } from '$lib/utils';
   import { navigate } from '$lib/utils/navigation';
+  import { onDestroy } from 'svelte';
+  import type { PageData } from './$types';
 
   interface Props {
     data: PageData;
@@ -27,18 +21,10 @@
 
   let { isViewing: showAssetViewer, asset: viewingAsset, setAssetId } = assetViewingStore;
 
-  let abortController: AbortController;
-  let mapMarkers: MapMarkerResponseDto[] = $state([]);
   let viewingAssets: string[] = $state([]);
   let viewingAssetCursor = 0;
-  let showSettingsModal = $state(false);
-
-  onMount(async () => {
-    mapMarkers = await loadMapMarkers();
-  });
 
   onDestroy(() => {
-    abortController?.abort();
     assetViewingStore.showAssetViewer(false);
   });
 
@@ -47,55 +33,6 @@
       handlePromiseError(goto(AppRoute.PHOTOS));
     }
   });
-  const omit = (obj: MapSettings, key: string) => {
-    return Object.fromEntries(Object.entries(obj).filter(([k]) => k !== key));
-  };
-
-  async function loadMapMarkers() {
-    if (abortController) {
-      abortController.abort();
-    }
-    abortController = new AbortController();
-
-    const { includeArchived, onlyFavorites, withPartners, withSharedAlbums } = $mapSettings;
-    const { fileCreatedAfter, fileCreatedBefore } = getFileCreatedDates();
-
-    return await getMapMarkers(
-      {
-        isArchived: includeArchived && undefined,
-        isFavorite: onlyFavorites || undefined,
-        fileCreatedAfter: fileCreatedAfter || undefined,
-        fileCreatedBefore,
-        withPartners: withPartners || undefined,
-        withSharedAlbums: withSharedAlbums || undefined,
-      },
-      {
-        signal: abortController.signal,
-      },
-    );
-  }
-
-  function getFileCreatedDates() {
-    const { relativeDate, dateAfter, dateBefore } = $mapSettings;
-
-    if (relativeDate) {
-      const duration = Duration.fromISO(relativeDate);
-      return {
-        fileCreatedAfter: duration.isValid ? DateTime.now().minus(duration).toISO() : undefined,
-      };
-    }
-
-    try {
-      return {
-        fileCreatedAfter: dateAfter ? new Date(dateAfter).toISOString() : undefined,
-        fileCreatedBefore: dateBefore ? new Date(dateBefore).toISOString() : undefined,
-      };
-    } catch {
-      $mapSettings.dateAfter = '';
-      $mapSettings.dateBefore = '';
-      return {};
-    }
-  }
 
   async function onViewAssets(assetIds: string[]) {
     viewingAssets = assetIds;
@@ -135,7 +72,7 @@
 {#if $featureFlags.loaded && $featureFlags.map}
   <UserPageLayout title={data.meta.title}>
     <div class="isolate h-full w-full">
-      <Map hash bind:mapMarkers bind:showSettingsModal onSelect={onViewAssets} />
+      <Map hash onSelect={onViewAssets} />
     </div>
   </UserPageLayout>
   <Portal target="body">
@@ -156,20 +93,4 @@
       {/await}
     {/if}
   </Portal>
-
-  {#if showSettingsModal}
-    <MapSettingsModal
-      settings={{ ...$mapSettings }}
-      onClose={() => (showSettingsModal = false)}
-      onSave={async (settings) => {
-        const shouldUpdate = !isEqual(omit(settings, 'allowDarkMode'), omit($mapSettings, 'allowDarkMode'));
-        showSettingsModal = false;
-        $mapSettings = settings;
-
-        if (shouldUpdate) {
-          mapMarkers = await loadMapMarkers();
-        }
-      }}
-    />
-  {/if}
 {/if}