From a59c496ae061c94a90db8e74db7138acf94f3618 Mon Sep 17 00:00:00 2001 From: nikec <43032218+niikeec@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:26:17 +0200 Subject: [PATCH] [ENG-1741] Improve date header (#2330) improve date lookup and include placeholder --- .../Explorer/View/MediaView/DateHeader.tsx | 6 +- .../Explorer/View/MediaView/index.tsx | 95 +++++++++---------- .../Explorer/View/MediaView/util.ts | 30 ++++++ 3 files changed, 78 insertions(+), 53 deletions(-) diff --git a/interface/app/$libraryId/Explorer/View/MediaView/DateHeader.tsx b/interface/app/$libraryId/Explorer/View/MediaView/DateHeader.tsx index e609d0f8f..9d16ca8ed 100644 --- a/interface/app/$libraryId/Explorer/View/MediaView/DateHeader.tsx +++ b/interface/app/$libraryId/Explorer/View/MediaView/DateHeader.tsx @@ -8,7 +8,7 @@ import { useExplorerViewContext } from '../Context'; export const DATE_HEADER_HEIGHT = 140; // million-ignore -export const DateHeader = ({ date }: { date: string }) => { +export const DateHeader = ({ date }: { date?: string }) => { const isDark = useIsDark(); const explorer = useExplorerContext(); @@ -52,7 +52,9 @@ export const DateHeader = ({ date }: { date: string }) => { isSticky ? 'opacity-100' : 'opacity-0' )} /> -
{date}
+
+ {date ?? 'No date'} +
); }; diff --git a/interface/app/$libraryId/Explorer/View/MediaView/index.tsx b/interface/app/$libraryId/Explorer/View/MediaView/index.tsx index cdf62f257..f70c2b81c 100644 --- a/interface/app/$libraryId/Explorer/View/MediaView/index.tsx +++ b/interface/app/$libraryId/Explorer/View/MediaView/index.tsx @@ -1,6 +1,6 @@ import { LoadMoreTrigger, useGrid, useScrollMargin, useVirtualizer } from '@virtual-grid/react'; import React, { useCallback, useEffect, useMemo, useRef } from 'react'; -import { getExplorerItemData, getOrderingDirection, orderingKey } from '@sd/client'; +import { getOrderingDirection, OrderingKey, orderingKey } from '@sd/client'; import { useExplorerContext } from '../../Context'; import { getItemData, getItemId, uniqueId } from '../../util'; @@ -10,15 +10,15 @@ import { GridItem } from '../Grid/Item'; import { useKeySelection } from '../Grid/useKeySelection'; import { DATE_HEADER_HEIGHT, DateHeader } from './DateHeader'; import { MediaViewItem } from './Item'; -import { formatDate } from './util'; +import { formatDate, getDate } from './util'; -const SORT_BY_DATE_KEYS = [ - 'dateCreated', - 'dateIndexed', - 'dateModified', - 'object.dateAccessed', - 'object.mediaData.epochTime' -]; +const SORT_BY_DATE: Partial> = { + 'dateCreated': true, + 'dateIndexed': true, + 'dateModified': true, + 'object.dateAccessed': true, + 'object.mediaData.epochTime': true +}; export const MediaView = () => { const explorer = useExplorerContext(); @@ -30,7 +30,7 @@ export const MediaView = () => { const orderBy = explorerSettings.order && orderingKey(explorerSettings.order); const orderDirection = explorerSettings.order && getOrderingDirection(explorerSettings.order); - const isSortingByDate = orderBy && SORT_BY_DATE_KEYS.includes(orderBy); + const isSortingByDate = orderBy && SORT_BY_DATE[orderBy]; const grid = useGrid({ scrollRef: explorer.scrollRef, @@ -73,6 +73,10 @@ export const MediaView = () => { const date = useMemo(() => { if (!isSortingByDate || !orderBy || !orderDirection) return; + // Prevent date placeholder from showing when + // items are still fetching + if (explorer.items === null) return ''; + let firstRowIndex: number | undefined = undefined; let lastRowIndex: number | undefined = undefined; @@ -96,53 +100,38 @@ export const MediaView = () => { if (firstRowIndex === undefined || lastRowIndex === undefined) return; - // Get the index of the last item and exclude any total count indexes + let firstItemIndex = firstRowIndex * grid.columnCount; let lastItemIndex = lastRowIndex * grid.columnCount + grid.columnCount; + + // Exclude any total count indexes if (lastItemIndex > grid.options.count - 1) lastItemIndex = grid.options.count - 1; - const firstExplorerItem = explorer.items?.[firstRowIndex * grid.columnCount]; - const lastExplorerItem = explorer.items?.[lastItemIndex]; - - const firstFilePath = firstExplorerItem && getExplorerItemData(firstExplorerItem); - if (!firstFilePath) return; - - const lastFilePath = lastExplorerItem && getExplorerItemData(lastExplorerItem); - if (!lastFilePath) return; - let firstFilePathDate: string | null = null; let lastFilePathDate: string | null = null; - switch (orderBy) { - case 'dateCreated': { - firstFilePathDate = firstFilePath.dateCreated; - lastFilePathDate = lastFilePath.dateCreated; - break; + // Look for the first date + for (let i = firstItemIndex; i < lastItemIndex; i++) { + const item = explorer.items[i]; + const date = item && getDate(item, orderBy); + + if (!date) { + if (i !== lastItemIndex - 1) firstItemIndex++; + continue; } - case 'dateIndexed': { - firstFilePathDate = firstFilePath.dateIndexed; - lastFilePathDate = lastFilePath.dateIndexed; - break; - } + firstFilePathDate = date; + break; + } - case 'dateModified': { - firstFilePathDate = firstFilePath.dateModified; - lastFilePathDate = lastFilePath.dateModified; - break; - } + // Look for the last date up to where the first lookup ended + for (let i = lastItemIndex; i > firstItemIndex; i--) { + const item = explorer.items[i]; + const date = item && getDate(item, orderBy); - case 'object.dateAccessed': { - firstFilePathDate = firstFilePath.dateAccessed; - lastFilePathDate = lastFilePath.dateAccessed; - break; - } + if (!date) continue; - // TODO: Uncomment when we add sorting by date taken - // case 'object.mediaData.epochTime': { - // firstFilePathDate = firstFilePath.dateTaken; - // lastFilePathDate = lastFilePath.dateTaken; - // break; - // } + lastFilePathDate = date; + break; } const firstDate = firstFilePathDate @@ -153,16 +142,20 @@ export const MediaView = () => { ? new Date(new Date(lastFilePathDate).setHours(0, 0, 0, 0)) : undefined; - if (!firstDate || !lastDate) return; + if (firstDate && !lastDate) return formatDate(firstDate); + + if (!firstDate && lastDate) return formatDate(lastDate); + + if (firstDate && lastDate) { + if (firstDate.getTime() === lastDate.getTime()) { + return formatDate(firstDate); + } - if (firstDate.getTime() !== lastDate.getTime()) { return formatDate({ from: orderDirection === 'Asc' ? firstDate : lastDate, to: orderDirection === 'Asc' ? lastDate : firstDate }); } - - return formatDate(firstDate); }, [ explorer.items, grid.columnCount, @@ -186,7 +179,7 @@ export const MediaView = () => { width: '100%' }} > - {isSortingByDate && } + {isSortingByDate && } {virtualRows.map((virtualRow) => ( diff --git a/interface/app/$libraryId/Explorer/View/MediaView/util.ts b/interface/app/$libraryId/Explorer/View/MediaView/util.ts index 42302b441..f2140e487 100644 --- a/interface/app/$libraryId/Explorer/View/MediaView/util.ts +++ b/interface/app/$libraryId/Explorer/View/MediaView/util.ts @@ -1,4 +1,5 @@ import dayjs from 'dayjs'; +import { ExplorerItem, getExplorerItemData, OrderingKey } from '@sd/client'; const DATE_FORMAT = 'D MMM YYYY'; @@ -14,3 +15,32 @@ export const formatDate = (date: Date | { from: Date; to: Date }) => { return `${dayjs(date.from).format(fromDateFormat)} - ${dayjs(date.to).format(DATE_FORMAT)}`; }; + +export function getDate(item: ExplorerItem, orderBy: OrderingKey) { + const filePath = getExplorerItemData(item); + + switch (orderBy) { + case 'dateCreated': { + return filePath.dateCreated; + } + + case 'dateIndexed': { + return filePath.dateIndexed; + } + + case 'dateModified': { + return filePath.dateModified; + } + + case 'object.dateAccessed': { + return filePath.dateAccessed; + } + + // TODO: Uncomment when we add sorting by date taken + // case 'object.mediaData.epochTime': { + // firstFilePathDate = firstFilePath.dateTaken; + // lastFilePathDate = lastFilePath.dateTaken; + // break; + // } + } +}