mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-06 23:43:32 +00:00
storage bar changes/file kinds loader
This commit is contained in:
parent
4735adcb66
commit
45e54f33ee
|
@ -5,7 +5,7 @@ import { motion } from 'framer-motion';
|
|||
import React, { MouseEventHandler, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { KindStatistic, uint32ArrayToBigInt, useLibraryQuery } from '@sd/client';
|
||||
import { Card, Tooltip } from '@sd/ui';
|
||||
import { Card, Loader, Tooltip } from '@sd/ui';
|
||||
import { useIsDark, useLocale } from '~/hooks';
|
||||
|
||||
const INFO_ICON_CLASSLIST =
|
||||
|
@ -71,7 +71,7 @@ const FileKindStats: React.FC<FileKindStatsProps> = () => {
|
|||
const isDark = useIsDark();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useLocale();
|
||||
const { data } = useLibraryQuery(['library.kindStatistics']);
|
||||
const { data, isLoading } = useLibraryQuery(['library.kindStatistics']);
|
||||
const [fileKinds, setFileKinds] = useState<FileKind[]>([]);
|
||||
const [cardWidth, setCardWidth] = useState<number>(0);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
@ -182,90 +182,110 @@ const FileKindStats: React.FC<FileKindStatsProps> = () => {
|
|||
ref={containerRef}
|
||||
className="max-w-1/2 group mx-1 flex h-[220px] w-full min-w-[400px] shrink-0 flex-col gap-2 bg-app-box/50"
|
||||
>
|
||||
<div className={TOTAL_FILES_CLASSLIST}>
|
||||
<Tooltip className="flex items-center" label={t('bar_graph_info')}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={clsx(
|
||||
'text-xl font-black',
|
||||
isDark ? 'text-white' : 'text-black'
|
||||
)}
|
||||
>
|
||||
{data?.total_identified_files
|
||||
? formatNumberWithCommas(data.total_identified_files)
|
||||
: '0'}{' '}
|
||||
</span>
|
||||
<div className="flex items-center">
|
||||
{t('total_files')}
|
||||
<Info weight="fill" className={INFO_ICON_CLASSLIST} />
|
||||
{isLoading ? (
|
||||
<>
|
||||
<div className="m-auto flex flex-col items-center justify-center gap-5">
|
||||
<Loader />
|
||||
<p className="text-m font-medium text-ink-faint">
|
||||
Calculating file kinds...
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className={TOTAL_FILES_CLASSLIST}>
|
||||
<Tooltip className="flex items-center" label={t('bar_graph_info')}>
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={clsx(
|
||||
'text-xl font-black',
|
||||
isDark ? 'text-white' : 'text-black'
|
||||
)}
|
||||
>
|
||||
{data?.total_identified_files
|
||||
? formatNumberWithCommas(data.total_identified_files)
|
||||
: '0'}{' '}
|
||||
</span>
|
||||
<div className="flex items-center">
|
||||
{t('total_files')}
|
||||
<Info weight="fill" className={INFO_ICON_CLASSLIST} />
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={UNIDENTIFIED_FILES_CLASSLIST}>
|
||||
<Tooltip label={t('unidentified_files_info')}>
|
||||
<span>
|
||||
{data?.total_unidentified_files
|
||||
? formatNumberWithCommas(data.total_unidentified_files)
|
||||
: '0'}{' '}
|
||||
unidentified files
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={UNIDENTIFIED_FILES_CLASSLIST}>
|
||||
<Tooltip label={t('unidentified_files_info')}>
|
||||
<span>
|
||||
{data?.total_unidentified_files
|
||||
? formatNumberWithCommas(data.total_unidentified_files)
|
||||
: '0'}{' '}
|
||||
unidentified files
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className={BARS_CONTAINER_CLASSLIST}>
|
||||
{sortedFileKinds.map((fileKind, index) => {
|
||||
const iconImage = iconsRef.current[fileKind.kind];
|
||||
const barColor = interpolateHexColor(
|
||||
BAR_COLOR_START,
|
||||
BAR_COLOR_END,
|
||||
index / (barCount - 1)
|
||||
);
|
||||
<div className={BARS_CONTAINER_CLASSLIST}>
|
||||
{sortedFileKinds.map((fileKind, index) => {
|
||||
const iconImage = iconsRef.current[fileKind.kind];
|
||||
const barColor = interpolateHexColor(
|
||||
BAR_COLOR_START,
|
||||
BAR_COLOR_END,
|
||||
index / (barCount - 1)
|
||||
);
|
||||
|
||||
const barHeight =
|
||||
mapFractionalValue(fileKind.count, maxFileCount, BAR_MAX_HEIGHT) + 'px';
|
||||
return (
|
||||
<>
|
||||
<Tooltip
|
||||
asChild
|
||||
key={fileKind.kind}
|
||||
label={
|
||||
formatNumberWithCommas(fileKind.count) +
|
||||
' ' +
|
||||
fileKind.kind +
|
||||
's'
|
||||
}
|
||||
position="left"
|
||||
>
|
||||
<div
|
||||
className="relative flex w-full min-w-8 max-w-10 grow cursor-pointer flex-col items-center"
|
||||
onDoubleClick={makeBarClickHandler(fileKind)}
|
||||
>
|
||||
{iconImage && (
|
||||
<img
|
||||
src={iconImage.src}
|
||||
alt={fileKind.kind}
|
||||
className="relative mb-1 size-4 duration-500"
|
||||
/>
|
||||
)}
|
||||
<motion.div
|
||||
className="flex w-full flex-col items-center rounded transition-all duration-500"
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: barHeight }}
|
||||
transition={{ duration: 0.4, ease: [0.42, 0, 0.58, 1] }}
|
||||
style={{
|
||||
height: barHeight,
|
||||
backgroundColor: barColor
|
||||
}}
|
||||
></motion.div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className="sm col-span-1 row-start-2 row-end-auto text-center text-[10px] font-medium text-ink-faint">
|
||||
{formatCount(fileKind.count)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
const barHeight =
|
||||
mapFractionalValue(
|
||||
fileKind.count,
|
||||
maxFileCount,
|
||||
BAR_MAX_HEIGHT
|
||||
) + 'px';
|
||||
return (
|
||||
<>
|
||||
<Tooltip
|
||||
asChild
|
||||
key={fileKind.kind}
|
||||
label={
|
||||
formatNumberWithCommas(fileKind.count) +
|
||||
' ' +
|
||||
fileKind.kind +
|
||||
's'
|
||||
}
|
||||
position="left"
|
||||
>
|
||||
<div
|
||||
className="relative flex w-full min-w-8 max-w-10 grow cursor-pointer flex-col items-center"
|
||||
onDoubleClick={makeBarClickHandler(fileKind)}
|
||||
>
|
||||
{iconImage && (
|
||||
<img
|
||||
src={iconImage.src}
|
||||
alt={fileKind.kind}
|
||||
className="relative mb-1 size-4 duration-500"
|
||||
/>
|
||||
)}
|
||||
<motion.div
|
||||
className="flex w-full flex-col items-center rounded transition-all duration-500"
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: barHeight }}
|
||||
transition={{
|
||||
duration: 0.4,
|
||||
ease: [0.42, 0, 0.58, 1]
|
||||
}}
|
||||
style={{
|
||||
height: barHeight,
|
||||
backgroundColor: barColor
|
||||
}}
|
||||
></motion.div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className="sm col-span-1 row-start-2 row-end-auto text-center text-[10px] font-medium text-ink-faint">
|
||||
{formatCount(fileKind.count)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -86,18 +86,18 @@ const LibraryStats = () => {
|
|||
|
||||
const StatItemNames: Partial<Record<keyof Statistics, string>> = {
|
||||
total_library_bytes: t('library_bytes'),
|
||||
total_local_bytes_capacity: t('total_bytes_capacity'),
|
||||
total_local_bytes_free: t('total_bytes_free'),
|
||||
library_db_size: t('library_db_size'),
|
||||
total_library_preview_media_bytes: t('preview_media_bytes')
|
||||
total_library_preview_media_bytes: t('preview_media_bytes'),
|
||||
total_local_bytes_capacity: t('total_bytes_capacity'),
|
||||
total_local_bytes_free: t('total_bytes_free')
|
||||
};
|
||||
|
||||
const StatDescriptions: Partial<Record<keyof Statistics, string>> = {
|
||||
total_library_bytes: t('library_bytes_description'),
|
||||
total_local_bytes_capacity: t('total_bytes_capacity_description'),
|
||||
total_local_bytes_free: t('total_bytes_free_description'),
|
||||
library_db_size: t('library_db_size_description'),
|
||||
total_library_preview_media_bytes: t('preview_media_bytes_description')
|
||||
total_library_preview_media_bytes: t('preview_media_bytes_description'),
|
||||
total_local_bytes_capacity: t('total_bytes_capacity_description'),
|
||||
total_local_bytes_free: t('total_bytes_free_description')
|
||||
};
|
||||
|
||||
const displayableStatItems = Object.keys(
|
||||
|
@ -113,6 +113,7 @@ const LibraryStats = () => {
|
|||
const totalUsedSpace = Number(statistics.total_local_bytes_used);
|
||||
|
||||
// Define the major categories and aggregate the "Other" category
|
||||
// TODO: edit to use library size as total capacity and split bar into major categories without system data
|
||||
const majorCategories = ['Document', 'Text', 'Image', 'Video'];
|
||||
const aggregatedData = (storageBarData ?? []).reduce(
|
||||
(acc, curr) => {
|
||||
|
@ -165,7 +166,7 @@ const LibraryStats = () => {
|
|||
|
||||
return (
|
||||
<Card className="flex h-[220px] w-[750px] shrink-0 flex-col bg-app-box/50">
|
||||
<div className="mb-1 flex overflow-hidden p-4">
|
||||
<div className="flex overflow-hidden p-4">
|
||||
{Object.entries(statistics)
|
||||
.sort(
|
||||
([a], [b]) =>
|
||||
|
|
|
@ -3,7 +3,7 @@ import { humanizeSize } from '@sd/client';
|
|||
import { Tooltip } from '@sd/ui';
|
||||
import { useIsDark } from '~/hooks';
|
||||
|
||||
const BARWIDTH = 700;
|
||||
const BARWIDTH = 750;
|
||||
|
||||
const lightenColor = (color: string, percent: number) => {
|
||||
const num = parseInt(color.replace('#', ''), 16);
|
||||
|
@ -109,7 +109,7 @@ const StorageBar: React.FC<StorageBarProps> = ({ sections, totalSpace }) => {
|
|||
{sections.map((section, index) => (
|
||||
<Tooltip key={index} label={section.tooltip} position="top">
|
||||
<div
|
||||
className="mb-2 mr-6 flex items-center"
|
||||
className="mb-2 mr-8 flex items-center"
|
||||
onMouseEnter={() => setHoveredSectionIndex(index)}
|
||||
onMouseLeave={() => setHoveredSectionIndex(null)}
|
||||
>
|
||||
|
|
|
@ -715,7 +715,7 @@
|
|||
"toggle_sidebar": "تبديل الشريط الجانبي",
|
||||
"tools": "أدوات",
|
||||
"total_bytes_capacity": "Total capacity",
|
||||
"total_bytes_capacity_description": "The total capacity of all nodes connected to the library. May show incorrect values during alpha.",
|
||||
"total_bytes_capacity_description": "The total capacity of the current nodes connected to the library. May show incorrect values during alpha.",
|
||||
"total_bytes_free": "Free space",
|
||||
"total_bytes_free_description": "Free space available on all nodes connected to the library.",
|
||||
"total_bytes_used": "Total used space",
|
||||
|
|
|
@ -707,10 +707,10 @@
|
|||
"toggle_quick_preview": "Toggle quick preview",
|
||||
"toggle_sidebar": "Toggle sidebar",
|
||||
"tools": "Tools",
|
||||
"total_bytes_capacity": "Total capacity",
|
||||
"total_bytes_capacity_description": "The total capacity of all nodes connected to the library. May show incorrect values during alpha.",
|
||||
"total_bytes_free": "Free space",
|
||||
"total_bytes_free_description": "Free space available on all nodes connected to the library.",
|
||||
"total_bytes_capacity": "Total local capacity",
|
||||
"total_bytes_capacity_description": "The total capacity the current node. May show incorrect values during alpha.",
|
||||
"total_bytes_free": "Free local space",
|
||||
"total_bytes_free_description": "Free space available on the current node.",
|
||||
"total_bytes_used": "Total used space",
|
||||
"total_bytes_used_description": "Total space used on all nodes connected to the library.",
|
||||
"total_files": "Total files",
|
||||
|
|
Loading…
Reference in a new issue