feat(web): lighter timeline buckets (#17719)

* feat(web): lighter timeline buckets

* GalleryViewer

* weird ssr

* Remove generics from AssetInteraction

* ensure keys on getAssetInfo, alt-text

* empty - trigger ci

* re-add alt-text

* test fix

* update tests

* tests

* missing import

* fix: flappy e2e test

* lint

* revert settings

* unneeded cast

* fix after merge

* missing import

* lint

* review

* lint

* avoid abbreviations

* review comment - type safety in test

* merge conflicts

* lint

* lint/abbreviations

* fix: left-over migration

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Min Idzelis 2025-05-17 22:57:08 -04:00 committed by GitHub
parent a65c905621
commit 0bbe70e6a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
53 changed files with 725 additions and 471 deletions

View file

@ -1,4 +1,8 @@
import type { TimelineAsset } from '$lib/stores/assets-store.svelte';
import { locale } from '$lib/stores/preferences.store';
import { getAssetRatio } from '$lib/utils/asset-utils';
import { AssetTypeEnum, type AssetResponseDto } from '@immich/sdk';
import { memoize } from 'lodash-es';
import { DateTime, type LocaleOptions } from 'luxon';
import { get } from 'svelte/store';
@ -56,3 +60,39 @@ export const getDateLocaleString = (date: DateTime, opts?: LocaleOptions): strin
date.toLocaleString(DateTime.DATE_MED_WITH_WEEKDAY, opts);
export const formatDateGroupTitle = memoize(formatGroupTitle);
export const toTimelineAsset = (unknownAsset: AssetResponseDto | TimelineAsset): TimelineAsset => {
if (isTimelineAsset(unknownAsset)) {
return unknownAsset;
}
const assetResponse = unknownAsset as AssetResponseDto;
const { width, height } = getAssetRatio(assetResponse);
const ratio = width / height;
const city = assetResponse.exifInfo?.city;
const country = assetResponse.exifInfo?.country;
const people = assetResponse.people?.map((person) => person.name) || [];
const text = {
city: city || null,
country: country || null,
people,
};
return {
id: assetResponse.id,
ownerId: assetResponse.ownerId,
ratio,
thumbhash: assetResponse.thumbhash,
localDateTime: assetResponse.localDateTime,
isFavorite: assetResponse.isFavorite,
visibility: assetResponse.visibility,
isTrashed: assetResponse.isTrashed,
isVideo: assetResponse.type == AssetTypeEnum.Video,
isImage: assetResponse.type == AssetTypeEnum.Image,
stack: assetResponse.stack || null,
duration: assetResponse.duration || null,
projectionType: assetResponse.exifInfo?.projectionType || null,
livePhotoVideoId: assetResponse.livePhotoVideoId || null,
text,
};
};
export const isTimelineAsset = (asset: AssetResponseDto | TimelineAsset): asset is TimelineAsset =>
(asset as TimelineAsset).ratio !== undefined;