mirror of
https://github.com/immich-app/immich.git
synced 2025-12-14 01:10:38 +03:00
170 lines
5.7 KiB
TypeScript
170 lines
5.7 KiB
TypeScript
import { plainDateTimeCompare, type TimelineYearMonth } from '$lib/utils/timeline-util';
|
|
import { AssetOrder, type AssetResponseDto } from '@immich/sdk';
|
|
import { DateTime } from 'luxon';
|
|
import type { MonthGroup } from '../month-group.svelte';
|
|
import { TimelineManager } from '../timeline-manager.svelte';
|
|
import type { AssetDescriptor, Direction, TimelineAsset } from '../types';
|
|
|
|
export async function getAssetWithOffset(
|
|
timelineManager: TimelineManager,
|
|
assetDescriptor: AssetDescriptor | AssetResponseDto,
|
|
interval: 'asset' | 'day' | 'month' | 'year' = 'asset',
|
|
direction: Direction,
|
|
): Promise<TimelineAsset | undefined> {
|
|
const monthGroup = await timelineManager.findMonthGroupForAsset(assetDescriptor);
|
|
if (!monthGroup) {
|
|
return;
|
|
}
|
|
const asset = monthGroup.findAssetById(assetDescriptor);
|
|
if (!asset) {
|
|
return;
|
|
}
|
|
|
|
switch (interval) {
|
|
case 'asset': {
|
|
return getAssetByAssetOffset(timelineManager, asset, monthGroup, direction);
|
|
}
|
|
case 'day': {
|
|
return getAssetByDayOffset(timelineManager, asset, monthGroup, direction);
|
|
}
|
|
case 'month': {
|
|
return getAssetByMonthOffset(timelineManager, monthGroup, direction);
|
|
}
|
|
case 'year': {
|
|
return getAssetByYearOffset(timelineManager, monthGroup, direction);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function findMonthGroupForAsset(timelineManager: TimelineManager, id: string) {
|
|
for (const month of timelineManager.months) {
|
|
const asset = month.findAssetById({ id });
|
|
if (asset) {
|
|
return { monthGroup: month, asset };
|
|
}
|
|
}
|
|
}
|
|
|
|
export function getMonthGroupByDate(
|
|
timelineManager: TimelineManager,
|
|
targetYearMonth: TimelineYearMonth,
|
|
): MonthGroup | undefined {
|
|
return timelineManager.months.find(
|
|
(month) => month.yearMonth.year === targetYearMonth.year && month.yearMonth.month === targetYearMonth.month,
|
|
);
|
|
}
|
|
|
|
async function getAssetByAssetOffset(
|
|
timelineManager: TimelineManager,
|
|
asset: TimelineAsset,
|
|
monthGroup: MonthGroup,
|
|
direction: Direction,
|
|
) {
|
|
const dayGroup = monthGroup.findDayGroupForAsset(asset);
|
|
for await (const targetAsset of timelineManager.assetsIterator({
|
|
startMonthGroup: monthGroup,
|
|
startDayGroup: dayGroup,
|
|
startAsset: asset,
|
|
direction,
|
|
})) {
|
|
if (asset.id !== targetAsset.id) {
|
|
return targetAsset;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getAssetByDayOffset(
|
|
timelineManager: TimelineManager,
|
|
asset: TimelineAsset,
|
|
monthGroup: MonthGroup,
|
|
direction: Direction,
|
|
) {
|
|
const dayGroup = monthGroup.findDayGroupForAsset(asset);
|
|
for await (const targetAsset of timelineManager.assetsIterator({
|
|
startMonthGroup: monthGroup,
|
|
startDayGroup: dayGroup,
|
|
startAsset: asset,
|
|
direction,
|
|
})) {
|
|
if (targetAsset.localDateTime.day !== asset.localDateTime.day) {
|
|
return targetAsset;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getAssetByMonthOffset(timelineManager: TimelineManager, month: MonthGroup, direction: Direction) {
|
|
for (const targetMonth of timelineManager.monthGroupIterator({ startMonthGroup: month, direction })) {
|
|
if (targetMonth.yearMonth.month !== month.yearMonth.month) {
|
|
const { value, done } = await timelineManager.assetsIterator({ startMonthGroup: targetMonth, direction }).next();
|
|
return done ? undefined : value;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function getAssetByYearOffset(timelineManager: TimelineManager, month: MonthGroup, direction: Direction) {
|
|
for (const targetMonth of timelineManager.monthGroupIterator({ startMonthGroup: month, direction })) {
|
|
if (targetMonth.yearMonth.year !== month.yearMonth.year) {
|
|
const { value, done } = await timelineManager.assetsIterator({ startMonthGroup: targetMonth, direction }).next();
|
|
return done ? undefined : value;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function retrieveRange(timelineManager: TimelineManager, start: AssetDescriptor, end: AssetDescriptor) {
|
|
let { asset: startAsset, monthGroup: startMonthGroup } = findMonthGroupForAsset(timelineManager, start.id) ?? {};
|
|
if (!startMonthGroup || !startAsset) {
|
|
return [];
|
|
}
|
|
let { asset: endAsset, monthGroup: endMonthGroup } = findMonthGroupForAsset(timelineManager, end.id) ?? {};
|
|
if (!endMonthGroup || !endAsset) {
|
|
return [];
|
|
}
|
|
const assetOrder: AssetOrder = timelineManager.getAssetOrder();
|
|
if (plainDateTimeCompare(assetOrder === AssetOrder.Desc, startAsset.localDateTime, endAsset.localDateTime) < 0) {
|
|
[startAsset, endAsset] = [endAsset, startAsset];
|
|
[startMonthGroup, endMonthGroup] = [endMonthGroup, startMonthGroup];
|
|
}
|
|
|
|
const range: TimelineAsset[] = [];
|
|
const startDayGroup = startMonthGroup.findDayGroupForAsset(startAsset);
|
|
for await (const targetAsset of timelineManager.assetsIterator({
|
|
startMonthGroup,
|
|
startDayGroup,
|
|
startAsset,
|
|
})) {
|
|
range.push(targetAsset);
|
|
if (targetAsset.id === endAsset.id) {
|
|
break;
|
|
}
|
|
}
|
|
return range;
|
|
}
|
|
|
|
export function findMonthGroupForDate(timelineManager: TimelineManager, targetYearMonth: TimelineYearMonth) {
|
|
for (const month of timelineManager.months) {
|
|
const { year, month: monthNum } = month.yearMonth;
|
|
if (monthNum === targetYearMonth.month && year === targetYearMonth.year) {
|
|
return month;
|
|
}
|
|
}
|
|
}
|
|
|
|
export function findClosestGroupForDate(months: MonthGroup[], targetYearMonth: TimelineYearMonth) {
|
|
const targetDate = DateTime.fromObject({ year: targetYearMonth.year, month: targetYearMonth.month });
|
|
|
|
let closestMonth: MonthGroup | undefined;
|
|
let minDifference = Number.MAX_SAFE_INTEGER;
|
|
|
|
for (const month of months) {
|
|
const monthDate = DateTime.fromObject({ year: month.yearMonth.year, month: month.yearMonth.month });
|
|
const totalDiff = Math.abs(monthDate.diff(targetDate, 'months').months);
|
|
|
|
if (totalDiff < minDifference) {
|
|
minDifference = totalDiff;
|
|
closestMonth = month;
|
|
}
|
|
}
|
|
|
|
return closestMonth;
|
|
}
|