mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 14:33:34 +00:00
[ENG-1741] Improve date header (#2330)
improve date lookup and include placeholder
This commit is contained in:
parent
73cb692218
commit
a59c496ae0
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) => (
|
||||||
|
|
|
@ -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;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue