diff --git a/Cargo.lock b/Cargo.lock index 128980377..6fa48998f 100644 Binary files a/Cargo.lock and b/Cargo.lock differ diff --git a/core/src/custom_uri.rs b/core/src/custom_uri.rs index ed6c1f895..183e839cd 100644 --- a/core/src/custom_uri.rs +++ b/core/src/custom_uri.rs @@ -174,8 +174,6 @@ pub fn router(node: Arc) -> Router<()> { lru_entry }; - println!("Serving from: {:?}", serve_from); // TODO - match serve_from { ServeFrom::Local => { let metadata = file_path_full_path.metadata().map_err(internal_server_error)?; diff --git a/interface/app/$libraryId/Explorer/Inspector/MediaData.tsx b/interface/app/$libraryId/Explorer/Inspector/MediaData.tsx new file mode 100644 index 000000000..29640c971 --- /dev/null +++ b/interface/app/$libraryId/Explorer/Inspector/MediaData.tsx @@ -0,0 +1,58 @@ +import { MediaLocation, MediaMetadata, MediaTime } from '@sd/client'; +import Accordion from '~/components/Accordion'; +import { MetaData } from './index'; + +interface Props { + data: MediaMetadata; +} + +function formatMediaTime(loc: MediaTime): string | null { + if (loc === 'Undefined') return null; + if ('Utc' in loc) return loc.Utc; + if ('Naive' in loc) return loc.Naive; + return null; +} + +function formatLocation(loc: MediaLocation): string { + // Stackoverflow says the `+` strips the trailing zeros or something so it's important, I think + return `${+loc.latitude.toFixed(2)}, ${+loc.longitude.toFixed(2)}`; +} + +function MediaData({ data }: Props) { + return data.type === 'Image' ? ( +
+ + + + + + {data.dimensions.width} x {data.dimensions.height} + + } + /> + + + + + + + + + + +
+ ) : null; +} + +export default MediaData; diff --git a/interface/app/$libraryId/Explorer/Inspector/index.tsx b/interface/app/$libraryId/Explorer/Inspector/index.tsx index 884152da8..13409e51f 100644 --- a/interface/app/$libraryId/Explorer/Inspector/index.tsx +++ b/interface/app/$libraryId/Explorer/Inspector/index.tsx @@ -26,10 +26,12 @@ import { } from 'react'; import { type ExplorerItem, + ObjectKindEnum, byteSize, getExplorerItemData, getItemFilePath, getItemObject, + useBridgeQuery, useItemsAsObjects, useLibraryQuery } from '@sd/client'; @@ -42,6 +44,7 @@ import { FileThumb } from '../FilePath/Thumb'; import { useExplorerStore } from '../store'; import { uniqueId, useExplorerItemData } from '../util'; import FavoriteButton from './FavoriteButton'; +import MediaData from './MediaData'; import Note from './Note'; export const InfoPill = tw.span`inline border border-transparent px-1 text-[11px] font-medium shadow shadow-app-shade/5 bg-app-selected rounded-md text-ink-dull`; @@ -156,16 +159,26 @@ const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => { enabled: !!objectData && readyToFetch }); - let { data: fileFullPath } = useLibraryQuery(['files.getPath', objectData?.id ?? -1], { + const filePath = useLibraryQuery(['files.getPath', objectData?.id ?? -1], { enabled: !!objectData && readyToFetch }); - if (fileFullPath == null) { - switch (item.type) { - case 'Location': - case 'NonIndexedPath': - fileFullPath = item.item.path; + //Images are only supported currently - kind = 5 + const filesMediaData = useLibraryQuery(['files.getMediaData', objectData?.id ?? -1], { + enabled: objectData?.kind === ObjectKindEnum.Image && !isNonIndexed && readyToFetch + }); + + const ephemeralLocationMediaData = useBridgeQuery( + ['files.getEphemeralMediaData', isNonIndexed ? item.item.path : ''], + { + enabled: isNonIndexed && item.item.kind === 5 && readyToFetch } + ); + + const mediaData = filesMediaData ?? ephemeralLocationMediaData ?? null; + + if (filePath.data == null && item.type === 'NonIndexedPath') { + filePath.data = item.item.path; } const { name, isDir, kind, size, casId, dateCreated, dateAccessed, dateModified, dateIndexed } = @@ -173,10 +186,11 @@ const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => { const pubId = object?.data ? uniqueId(object?.data) : null; - let extension, integrityChecksum; const filePathItem = getItemFilePath(item); + let extension, integrityChecksum; + if (filePathItem) { - extension = 'extension' in filePathItem ? filePathItem.extension : null; + extension = filePathItem.extension; integrityChecksum = 'integrity_checksum' in filePathItem ? filePathItem.integrity_checksum : null; } @@ -227,20 +241,15 @@ const SingleItemMetadata = ({ item }: { item: ExplorerItem }) => { { // TODO: Add toast notification - fileFullPath && navigator.clipboard.writeText(fileFullPath); + filePath.data && navigator.clipboard.writeText(filePath.data); }} /> - - - { - // TODO: Call `files.getMediaData` for indexed locations when we have media data UI - // TODO: Call `files.getEphemeralMediaData` for ephemeral locations when we have media data UI - } + {mediaData.data && } {isDir ? 'Folder' : kind} @@ -436,19 +445,19 @@ const MultiItemMetadata = ({ items }: { items: ExplorerItem[] }) => { }; interface MetaDataProps { - icon: Icon; + icon?: Icon; label: string; value: ReactNode; onClick?: () => void; } -const MetaData = ({ icon: Icon, label, value, onClick }: MetaDataProps) => { +export const MetaData = ({ icon: Icon, label, value, onClick }: MetaDataProps) => { return (
- + {Icon && } {label} - {value || '--'} + {value ?? '--'}
); diff --git a/interface/components/Accordion.tsx b/interface/components/Accordion.tsx index 897c0c0cb..38a1ab984 100644 --- a/interface/components/Accordion.tsx +++ b/interface/components/Accordion.tsx @@ -1,30 +1,41 @@ import clsx from 'clsx'; import { CaretDown } from 'phosphor-react'; -import { useState } from 'react'; +import { PropsWithChildren, useState } from 'react'; interface Props { - children: React.ReactNode; className?: string; title: string; + titleClassName?: string; + containerClassName?: string; + caretSize?: number; } -const Accordion = ({ title, className, children }: Props) => { +const Accordion = (props: PropsWithChildren) => { const [toggle, setToggle] = useState(false); return ( -
+
setToggle((t) => !t)} - className="flex items-center justify-between px-3 py-2" + className={clsx( + 'flex flex-row items-center justify-between px-3 py-2', + props.titleClassName + )} > -

{title}

+

{props.title}

{toggle && ( -
- {children} +
+ {props.children}
)}