|
1 | 1 | <script lang="ts">
|
| 2 | + import { goto } from '$app/navigation'; |
| 3 | + import DetailPanelDescription from '$lib/components/asset-viewer/detail-panel-description.svelte'; |
2 | 4 | import DetailPanelLocation from '$lib/components/asset-viewer/detail-panel-location.svelte';
|
| 5 | + import DetailPanelRating from '$lib/components/asset-viewer/detail-panel-star-rating.svelte'; |
| 6 | + import DetailPanelTags from '$lib/components/asset-viewer/detail-panel-tags.svelte'; |
3 | 7 | import Icon from '$lib/components/elements/icon.svelte';
|
4 | 8 | import ChangeDate from '$lib/components/shared-components/change-date.svelte';
|
5 | 9 | import { AppRoute, QueryParameter, timeToLoadTheMap } from '$lib/constants';
|
|
9 | 13 | import { preferences, user } from '$lib/stores/user.store';
|
10 | 14 | import { getAssetThumbnailUrl, getPeopleThumbnailUrl, handlePromiseError, isSharedLink } from '$lib/utils';
|
11 | 15 | import { delay, isFlipped } from '$lib/utils/asset-utils';
|
| 16 | + import { getByteUnitString } from '$lib/utils/byte-units'; |
| 17 | + import { handleError } from '$lib/utils/handle-error'; |
| 18 | + import { fromDateTimeOriginal, fromLocalDateTime } from '$lib/utils/timeline-util'; |
12 | 19 | import {
|
13 | 20 | AssetMediaSize,
|
14 | 21 | getAssetInfo,
|
|
18 | 25 | type ExifResponseDto,
|
19 | 26 | } from '@immich/sdk';
|
20 | 27 | import {
|
| 28 | + mdiAccountOff, |
21 | 29 | mdiCalendar,
|
22 | 30 | mdiCameraIris,
|
23 | 31 | mdiClose,
|
|
26 | 34 | mdiImageOutline,
|
27 | 35 | mdiInformationOutline,
|
28 | 36 | mdiPencil,
|
29 |
| - mdiAccountOff, |
30 | 37 | } from '@mdi/js';
|
31 | 38 | import { DateTime } from 'luxon';
|
32 | 39 | import { createEventDispatcher } from 'svelte';
|
| 40 | + import { t } from 'svelte-i18n'; |
33 | 41 | import { slide } from 'svelte/transition';
|
34 |
| - import { getByteUnitString } from '$lib/utils/byte-units'; |
35 |
| - import { handleError } from '$lib/utils/handle-error'; |
36 | 42 | import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
37 | 43 | import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
38 | 44 | import PersonSidePanel from '../faces-page/person-side-panel.svelte';
|
39 |
| - import UserAvatar from '../shared-components/user-avatar.svelte'; |
40 | 45 | import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
| 46 | + import UserAvatar from '../shared-components/user-avatar.svelte'; |
41 | 47 | import AlbumListItemDetails from './album-list-item-details.svelte';
|
42 |
| - import DetailPanelDescription from '$lib/components/asset-viewer/detail-panel-description.svelte'; |
43 |
| - import DetailPanelRating from '$lib/components/asset-viewer/detail-panel-star-rating.svelte'; |
44 |
| - import { t } from 'svelte-i18n'; |
45 |
| - import { goto } from '$app/navigation'; |
46 |
| - import DetailPanelTags from '$lib/components/asset-viewer/detail-panel-tags.svelte'; |
47 | 48 |
|
48 | 49 | export let asset: AssetResponseDto;
|
49 | 50 | export let albums: AlbumResponseDto[] = [];
|
|
99 | 100 |
|
100 | 101 | $: unassignedFaces = asset.unassignedFaces || [];
|
101 | 102 |
|
| 103 | + $: timeZone = asset.exifInfo?.timeZone; |
| 104 | + $: dateTime = |
| 105 | + timeZone && asset.exifInfo?.dateTimeOriginal |
| 106 | + ? fromDateTimeOriginal(asset.exifInfo.dateTimeOriginal, timeZone) |
| 107 | + : fromLocalDateTime(asset.localDateTime); |
| 108 | +
|
102 | 109 | const dispatch = createEventDispatcher<{
|
103 | 110 | close: void;
|
104 | 111 | }>();
|
|
261 | 268 | <p class="text-sm">{$t('no_exif_info_available').toUpperCase()}</p>
|
262 | 269 | {/if}
|
263 | 270 |
|
264 |
| - {#if asset.exifInfo?.dateTimeOriginal} |
265 |
| - {@const assetDateTimeOriginal = DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { |
266 |
| - zone: asset.exifInfo.timeZone ?? undefined, |
267 |
| - })} |
| 271 | + {#if dateTime} |
268 | 272 | <button
|
269 | 273 | type="button"
|
270 | 274 | class="flex w-full text-left justify-between place-items-start gap-4 py-4"
|
|
280 | 284 |
|
281 | 285 | <div>
|
282 | 286 | <p>
|
283 |
| - {assetDateTimeOriginal.toLocaleString( |
| 287 | + {dateTime.toLocaleString( |
284 | 288 | {
|
285 | 289 | month: 'short',
|
286 | 290 | day: 'numeric',
|
|
291 | 295 | </p>
|
292 | 296 | <div class="flex gap-2 text-sm">
|
293 | 297 | <p>
|
294 |
| - {assetDateTimeOriginal.toLocaleString( |
| 298 | + {dateTime.toLocaleString( |
295 | 299 | {
|
296 | 300 | weekday: 'short',
|
297 | 301 | hour: 'numeric',
|
298 | 302 | minute: '2-digit',
|
299 |
| - timeZoneName: 'longOffset', |
| 303 | + timeZoneName: timeZone ? 'longOffset' : undefined, |
300 | 304 | },
|
301 | 305 | { locale: $locale },
|
302 | 306 | )}
|
|
325 | 329 | {/if}
|
326 | 330 |
|
327 | 331 | {#if isShowChangeDate}
|
328 |
| - {@const assetDateTimeOriginal = asset.exifInfo?.dateTimeOriginal |
329 |
| - ? DateTime.fromISO(asset.exifInfo.dateTimeOriginal, { |
330 |
| - zone: asset.exifInfo.timeZone ?? undefined, |
331 |
| - locale: $locale, |
332 |
| - }) |
333 |
| - : DateTime.now()} |
334 |
| - {@const assetTimeZoneOriginal = asset.exifInfo?.timeZone ?? ''} |
335 | 332 | <ChangeDate
|
336 |
| - initialDate={assetDateTimeOriginal} |
337 |
| - initialTimeZone={assetTimeZoneOriginal} |
| 333 | + initialDate={dateTime} |
| 334 | + initialTimeZone={timeZone ?? ''} |
338 | 335 | on:confirm={({ detail: date }) => handleConfirmChangeDate(date)}
|
339 | 336 | on:cancel={() => (isShowChangeDate = false)}
|
340 | 337 | />
|
|
0 commit comments