[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; export const DATE_HEADER_HEIGHT = 140;
// million-ignore // million-ignore
export const DateHeader = ({ date }: { date: string }) => { export const DateHeader = ({ date }: { date?: string }) => {
const isDark = useIsDark(); const isDark = useIsDark();
const explorer = useExplorerContext(); const explorer = useExplorerContext();
@ -52,7 +52,9 @@ export const DateHeader = ({ date }: { date: string }) => {
isSticky ? 'opacity-100' : 'opacity-0' 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> </div>
); );
}; };

View file

@ -1,6 +1,6 @@
import { LoadMoreTrigger, useGrid, useScrollMargin, useVirtualizer } from '@virtual-grid/react'; import { LoadMoreTrigger, useGrid, useScrollMargin, useVirtualizer } from '@virtual-grid/react';
import React, { useCallback, useEffect, useMemo, useRef } from '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 { useExplorerContext } from '../../Context';
import { getItemData, getItemId, uniqueId } from '../../util'; import { getItemData, getItemId, uniqueId } from '../../util';
@ -10,15 +10,15 @@ import { GridItem } from '../Grid/Item';
import { useKeySelection } from '../Grid/useKeySelection'; import { useKeySelection } from '../Grid/useKeySelection';
import { DATE_HEADER_HEIGHT, DateHeader } from './DateHeader'; import { DATE_HEADER_HEIGHT, DateHeader } from './DateHeader';
import { MediaViewItem } from './Item'; import { MediaViewItem } from './Item';
import { formatDate } from './util'; import { formatDate, getDate } from './util';
const SORT_BY_DATE_KEYS = [ const SORT_BY_DATE: Partial<Record<OrderingKey, boolean>> = {
'dateCreated', 'dateCreated': true,
'dateIndexed', 'dateIndexed': true,
'dateModified', 'dateModified': true,
'object.dateAccessed', 'object.dateAccessed': true,
'object.mediaData.epochTime' 'object.mediaData.epochTime': true
]; };
export const MediaView = () => { export const MediaView = () => {
const explorer = useExplorerContext(); const explorer = useExplorerContext();
@ -30,7 +30,7 @@ export const MediaView = () => {
const orderBy = explorerSettings.order && orderingKey(explorerSettings.order); const orderBy = explorerSettings.order && orderingKey(explorerSettings.order);
const orderDirection = explorerSettings.order && getOrderingDirection(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({ const grid = useGrid({
scrollRef: explorer.scrollRef, scrollRef: explorer.scrollRef,
@ -73,6 +73,10 @@ export const MediaView = () => {
const date = useMemo(() => { const date = useMemo(() => {
if (!isSortingByDate || !orderBy || !orderDirection) return; 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 firstRowIndex: number | undefined = undefined;
let lastRowIndex: number | undefined = undefined; let lastRowIndex: number | undefined = undefined;
@ -96,53 +100,38 @@ export const MediaView = () => {
if (firstRowIndex === undefined || lastRowIndex === undefined) return; 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; let lastItemIndex = lastRowIndex * grid.columnCount + grid.columnCount;
// Exclude any total count indexes
if (lastItemIndex > grid.options.count - 1) lastItemIndex = grid.options.count - 1; 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 firstFilePathDate: string | null = null;
let lastFilePathDate: string | null = null; let lastFilePathDate: string | null = null;
switch (orderBy) { // Look for the first date
case 'dateCreated': { for (let i = firstItemIndex; i < lastItemIndex; i++) {
firstFilePathDate = firstFilePath.dateCreated; const item = explorer.items[i];
lastFilePathDate = lastFilePath.dateCreated; const date = item && getDate(item, orderBy);
break;
if (!date) {
if (i !== lastItemIndex - 1) firstItemIndex++;
continue;
} }
case 'dateIndexed': { firstFilePathDate = date;
firstFilePathDate = firstFilePath.dateIndexed; break;
lastFilePathDate = lastFilePath.dateIndexed; }
break;
}
case 'dateModified': { // Look for the last date up to where the first lookup ended
firstFilePathDate = firstFilePath.dateModified; for (let i = lastItemIndex; i > firstItemIndex; i--) {
lastFilePathDate = lastFilePath.dateModified; const item = explorer.items[i];
break; const date = item && getDate(item, orderBy);
}
case 'object.dateAccessed': { if (!date) continue;
firstFilePathDate = firstFilePath.dateAccessed;
lastFilePathDate = lastFilePath.dateAccessed;
break;
}
// TODO: Uncomment when we add sorting by date taken lastFilePathDate = date;
// case 'object.mediaData.epochTime': { break;
// firstFilePathDate = firstFilePath.dateTaken;
// lastFilePathDate = lastFilePath.dateTaken;
// break;
// }
} }
const firstDate = firstFilePathDate const firstDate = firstFilePathDate
@ -153,16 +142,20 @@ export const MediaView = () => {
? new Date(new Date(lastFilePathDate).setHours(0, 0, 0, 0)) ? new Date(new Date(lastFilePathDate).setHours(0, 0, 0, 0))
: undefined; : 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({ return formatDate({
from: orderDirection === 'Asc' ? firstDate : lastDate, from: orderDirection === 'Asc' ? firstDate : lastDate,
to: orderDirection === 'Asc' ? lastDate : firstDate to: orderDirection === 'Asc' ? lastDate : firstDate
}); });
} }
return formatDate(firstDate);
}, [ }, [
explorer.items, explorer.items,
grid.columnCount, grid.columnCount,
@ -186,7 +179,7 @@ export const MediaView = () => {
width: '100%' width: '100%'
}} }}
> >
{isSortingByDate && <DateHeader date={date ?? ''} />} {isSortingByDate && <DateHeader date={date} />}
<DragSelect grid={grid} onActiveItemChange={updateActiveItem}> <DragSelect grid={grid} onActiveItemChange={updateActiveItem}>
{virtualRows.map((virtualRow) => ( {virtualRows.map((virtualRow) => (

View file

@ -1,4 +1,5 @@
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { ExplorerItem, getExplorerItemData, OrderingKey } from '@sd/client';
const DATE_FORMAT = 'D MMM YYYY'; 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)}`; 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;
// }
}
}