[ENG-1741] Improve date header (#2330)

improve date lookup and include placeholder
This commit is contained in:
nikec 2024-04-15 14:26:17 +02:00 committed by GitHub
parent 73cb692218
commit a59c496ae0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 78 additions and 53 deletions

View file

@ -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'
)}
/>
<div className="relative text-xl font-semibold">{date}</div>
<div className={clsx('relative text-xl font-semibold', !date && 'opacity-75')}>
{date ?? 'No date'}
</div>
</div>
);
};

View file

@ -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<Record<OrderingKey, boolean>> = {
'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 && <DateHeader date={date ?? ''} />}
{isSortingByDate && <DateHeader date={date} />}
<DragSelect grid={grid} onActiveItemChange={updateActiveItem}>
{virtualRows.map((virtualRow) => (

View file

@ -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;
// }
}
}