mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-04-24 00:17:47 -04:00
* initial ffprobe commit * Working slim down version ffprobe * Auto format ffprobe and deps source * Remove show_pixel_formats logic - Fix do_bitexact incorrect check in main after last changes - Fix some clangd warning * Remove show_* and print_format options and their respective logic * Rework ffprobe into simple_ffprobe - Simplify ffprobe logic into a simple program that gather and print a media file metadata * Reduce the amount of ffmpeg log messages while generating thumbnails * Fix completly wrong comments * mend * Start modeling ffmpeg extracted metadata on schema - Start porting ffprobe code to rust - Rename some references to media_data to exif_data * Finish modeling media info data - Add MediaProgram, MediaStream, MediaCodec, MediaVideoProps, MediaAudioProps, MediaSubtitleProps to Schema - Fix simple_ffproble to use its custom print_codec, instead of ffmpeg's impl * Add relation between MediaInfo and FilePath - Remove shared properties from MediaInfo and related structs - Implement Iterator for FFmpegDict * Fix and update schema * Data models and start populating MediaInfo in rust * Finish populating media info, chapters and program * Improve FFmpegFormatContext data raw pointer access - Implement stream data gathering * Impl FFmpegCodecContext, retrieve codec information - Improve some unsafe pointer uses - Impl from FFmpegFormatContext to MediaInfo conversion * Fix FFmpegDict Drop * Fix some crago warnings * Impl retrieval of video props - Fix C char* to Rust String convertion * Impl retrieval of audio and subtitle props - Fill props for MediaCodec * Remove simple_ffprobe now that the Rust impl is done * Fix schema to match actually retrieved media info - Fix import some FFmpeg constants instead of directly using values * Rework movie_decoder - Re-implement create_scale_string and add support anamorphic video - Improve C pointer access for FFmpegFormatContext and FFmpegCodecContext - Use newer FFmpeg abstractions in movie_decoder * Fix incorrect props when initializing MovieDecoder * Remove unecessary lifetimes * Added more native wrappers for some FFmpeg native objects used in movie_decoder * Remove FFmpegPacket - Some more improvements to movie_decoder * WIP * Some small fixes * More fixes Rename movie_decoder to frame_decoder Remove more references to film_strips * fmt * Fix duplicate migration for job error changes * fix rebase * Solving segfaults, fuck C lang Co-authored-by: Vítor Vasconcellos <HeavenVolkoff@users.noreply.github.com> * Update rust to version 1.77 - Pin rust version with rust-toolchain.toml - Change from dtolnay/rust-toolchain to IronCoreLabs/rust-toolchain for rust-toolchain support - Remove unused function and imports - Replace most CString uses with new c literal string * More segfault solving and other minor fixes Co-authored-by: Vítor Vasconcellos <HeavenVolkoff@users.noreply.github.com> * Fix ffmpeg rotation filter breaking portrait video thumbnails #2150 - Plus some other misc fixes * Auto format * Retrieve video/audio metadata on frontend * Auto format * First draft on ffmpeg data save on db Co-authored-by: Vítor Vasconcellos <HeavenVolkoff@users.noreply.github.com> * Fix some incorrect changes to prisma schema * Some fixes for the FFmpegData schema - Expand logic to save FFmpegData to db * A ton of things Co-authored-by: Vítor Vasconcellos <HeavenVolkoff@users.noreply.github.com> * Integrating ffmpeg media data in jobs and API * Rspc can't BigInt * 🙄 * Add initial ffmpeg metadata entries to Inspector - Fix ephemeral metadata api to match the files metadata api call * Fix Inspector not showing ffmpeg metadata * Add bitrate, start time and chapters video metadata to Inspector - Fix backend BigInt conversion incorrectly using i32 instead of u32 - Change FFmpegFormatContext/FFmpegMetaData bit_rate to i64 - Rename byteSize to humanizeSize - Expand humanizeSize logic to allow handling bits and Binary units - Move capitalize to @sd/client utils * Solving some issues * Fix ffmpeg probe getting incorrect stream id and breaking database unique constraint - Fix humanizeSize breaking when receiving floating numbers - Fix incorrect equality in StatCard - Fix unhandled error in Dialog when trying to remove an unknown dialog * fmt * small improvements - Remove some unecessary recursion_limit directive - Remove unused app_image releated functions - Fix metadata query enabled flag * Add migration for ffmpeg media data * Fix cypress test * Requested changes * Implement feedback - Update locale keys for all languages - Add pnpm command to update all language keys * Fix thumb reactivity in non indexed locations --------- Co-authored-by: Ericson Soares <ericson.ds999@gmail.com> Co-authored-by: Vítor Vasconcellos <HeavenVolkoff@users.noreply.github.com>
118 lines
3.3 KiB
TypeScript
118 lines
3.3 KiB
TypeScript
import { Info } from '@phosphor-icons/react';
|
|
import clsx from 'clsx';
|
|
import { useEffect, useState } from 'react';
|
|
import { humanizeSize, Statistics, useLibraryContext, useLibraryQuery } from '@sd/client';
|
|
import { Tooltip } from '@sd/ui';
|
|
import { useCounter, useLocale } from '~/hooks';
|
|
|
|
interface StatItemProps {
|
|
title: string;
|
|
bytes: bigint;
|
|
isLoading: boolean;
|
|
info?: string;
|
|
}
|
|
|
|
let mounted = false;
|
|
|
|
const StatItem = (props: StatItemProps) => {
|
|
const { title, bytes, isLoading } = props;
|
|
|
|
// This is important to the counter working.
|
|
// On first render of the counter this will potentially be `false` which means the counter should the count up.
|
|
// but in a `useEffect` `mounted` will be set to `true` so that subsequent renders of the counter will not run the count up.
|
|
// The acts as a cache of the value of `mounted` on the first render of this `StateItem`.
|
|
const [isMounted] = useState(mounted);
|
|
|
|
const size = humanizeSize(bytes);
|
|
const count = useCounter({
|
|
name: title,
|
|
end: size.value,
|
|
duration: isMounted ? 0 : 1,
|
|
saveState: false
|
|
});
|
|
|
|
return (
|
|
<div
|
|
className={clsx(
|
|
'group/stat flex w-32 shrink-0 flex-col duration-75',
|
|
!bytes && 'hidden'
|
|
)}
|
|
>
|
|
<span className="whitespace-nowrap text-sm font-medium text-ink-faint">
|
|
{title}
|
|
{props.info && (
|
|
<Tooltip label={props.info}>
|
|
<Info
|
|
weight="fill"
|
|
className="-mt-0.5 ml-1 inline size-3 text-ink-faint opacity-0 transition-opacity group-hover/stat:opacity-70"
|
|
/>
|
|
</Tooltip>
|
|
)}
|
|
</span>
|
|
|
|
<span className="text-2xl">
|
|
<div
|
|
className={clsx({
|
|
hidden: isLoading
|
|
})}
|
|
>
|
|
<span className="font-black tabular-nums">{count}</span>
|
|
<span className="ml-1 text-[16px] font-medium text-ink-faint">{size.unit}</span>
|
|
</div>
|
|
</span>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const LibraryStats = () => {
|
|
const { library } = useLibraryContext();
|
|
|
|
const stats = useLibraryQuery(['library.statistics']);
|
|
|
|
useEffect(() => {
|
|
if (!stats.isLoading) mounted = true;
|
|
});
|
|
|
|
const { t } = useLocale();
|
|
|
|
const StatItemNames: Partial<Record<keyof Statistics, string>> = {
|
|
total_bytes_capacity: t('total_bytes_capacity'),
|
|
preview_media_bytes: t('preview_media_bytes'),
|
|
library_db_size: t('library_db_size'),
|
|
total_bytes_free: t('total_bytes_free'),
|
|
total_bytes_used: t('total_bytes_used')
|
|
};
|
|
|
|
const StatDescriptions: Partial<Record<keyof Statistics, string>> = {
|
|
total_bytes_capacity: t('total_bytes_capacity_description'),
|
|
preview_media_bytes: t('preview_media_bytes_description'),
|
|
library_db_size: t('library_db_size_description'),
|
|
total_bytes_free: t('total_bytes_free_description'),
|
|
total_bytes_used: t('total_bytes_used_description')
|
|
};
|
|
|
|
const displayableStatItems = Object.keys(
|
|
StatItemNames
|
|
) as unknown as keyof typeof StatItemNames;
|
|
return (
|
|
<div className="flex w-full">
|
|
<div className="flex gap-3 overflow-hidden">
|
|
{Object.entries(stats?.data?.statistics || []).map(([key, value]) => {
|
|
if (!displayableStatItems.includes(key)) return null;
|
|
return (
|
|
<StatItem
|
|
key={`${library.uuid} ${key}`}
|
|
title={StatItemNames[key as keyof Statistics]!}
|
|
bytes={BigInt(value)}
|
|
isLoading={stats.isLoading}
|
|
info={StatDescriptions[key as keyof Statistics]}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default LibraryStats;
|