mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-10-15 21:48:43 -04:00
* Attempt at fixing stats * Fix macOS disk stats retrieve logic - Ignore mounted dmgs when calculation disk total/free size - Only take into account disk mounted by macOS * macos only import * Fix Linux * Replace byte-size with a custom implementation that supports BigInt * Fix NaN in Statistics * clippy * fmt * Move linux get_volumes to a specilized function - Fix ZFS handling - Improve handling of disk symlinks and multiple mounts * Fix macOS
103 lines
3.1 KiB
TypeScript
103 lines
3.1 KiB
TypeScript
import clsx from 'clsx';
|
|
import { memo } from 'react';
|
|
import { ExplorerItem, byteSize, getItemFilePath, getItemLocation } from '@sd/client';
|
|
import { GridList } from '~/components';
|
|
import { ViewItem } from '.';
|
|
import FileThumb from '../FilePath/Thumb';
|
|
import { useExplorerViewContext } from '../ViewContext';
|
|
import { isCut, useExplorerStore } from '../store';
|
|
import RenamableItemText from './RenamableItemText';
|
|
|
|
interface GridViewItemProps {
|
|
data: ExplorerItem;
|
|
selected: boolean;
|
|
index: number;
|
|
cut: boolean;
|
|
}
|
|
|
|
const GridViewItem = memo(({ data, selected, index, cut, ...props }: GridViewItemProps) => {
|
|
const filePathData = getItemFilePath(data);
|
|
const location = getItemLocation(data);
|
|
const explorerStore = useExplorerStore();
|
|
const explorerView = useExplorerViewContext();
|
|
|
|
const showSize =
|
|
!filePathData?.is_dir &&
|
|
!location &&
|
|
explorerStore.showBytesInGridView &&
|
|
(!explorerView.isRenaming || (explorerView.isRenaming && !selected));
|
|
|
|
return (
|
|
<ViewItem data={data} className="h-full w-full" {...props}>
|
|
<div className={clsx('mb-1 rounded-lg ', selected && 'bg-app-selectedItem')}>
|
|
<FileThumb
|
|
data={data}
|
|
size={explorerStore.gridItemSize}
|
|
className={clsx('mx-auto', cut && 'opacity-60')}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-col justify-center">
|
|
<RenamableItemText
|
|
item={data}
|
|
selected={selected}
|
|
style={{ maxHeight: explorerStore.gridItemSize / 3 }}
|
|
/>
|
|
{showSize && filePathData?.size_in_bytes_bytes && (
|
|
<span
|
|
className={clsx(
|
|
'cursor-default truncate rounded-md px-1.5 py-[1px] text-center text-tiny text-ink-dull '
|
|
)}
|
|
>
|
|
{`${byteSize(filePathData.size_in_bytes_bytes)}`}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</ViewItem>
|
|
);
|
|
});
|
|
|
|
export default () => {
|
|
const explorerStore = useExplorerStore();
|
|
const explorerView = useExplorerViewContext();
|
|
|
|
const itemDetailsHeight =
|
|
explorerStore.gridItemSize / 4 + (explorerStore.showBytesInGridView ? 20 : 0);
|
|
const itemHeight = explorerStore.gridItemSize + itemDetailsHeight;
|
|
|
|
return (
|
|
<GridList
|
|
scrollRef={explorerView.scrollRef}
|
|
count={explorerView.items?.length || 100}
|
|
size={{ width: explorerStore.gridItemSize, height: itemHeight }}
|
|
padding={12}
|
|
selectable={!!explorerView.items}
|
|
selected={explorerView.selected}
|
|
onSelectedChange={explorerView.onSelectedChange}
|
|
overscan={explorerView.overscan}
|
|
onLoadMore={explorerView.onLoadMore}
|
|
rowsBeforeLoadMore={explorerView.rowsBeforeLoadMore}
|
|
top={explorerView.top}
|
|
preventSelection={explorerView.isRenaming || !explorerView.selectable}
|
|
preventContextMenuSelection={explorerView.contextMenu === undefined}
|
|
>
|
|
{({ index, item: Item }) => {
|
|
const item = explorerView.items?.[index];
|
|
if (!item) return null;
|
|
|
|
const isSelected = Array.isArray(explorerView.selected)
|
|
? explorerView.selected.includes(item.item.id)
|
|
: explorerView.selected === item.item.id;
|
|
|
|
const cut = isCut(item.item.id);
|
|
|
|
return (
|
|
<Item selected={isSelected} id={item.item.id}>
|
|
<GridViewItem data={item} selected={isSelected} index={index} cut={cut} />
|
|
</Item>
|
|
);
|
|
}}
|
|
</GridList>
|
|
);
|
|
};
|