mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-18 21:36:56 -04:00
Switch to ts-client types from root package
This commit is contained in:
@@ -19,3 +19,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -21,19 +21,13 @@ use uuid::Uuid;
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Type)]
|
||||
pub enum EntryKind {
|
||||
/// Regular file
|
||||
File {
|
||||
/// File extension (without dot)
|
||||
extension: Option<String>,
|
||||
},
|
||||
File,
|
||||
|
||||
/// Directory
|
||||
Directory,
|
||||
|
||||
/// Symbolic link
|
||||
Symlink {
|
||||
/// Target path
|
||||
target: String,
|
||||
},
|
||||
Symlink,
|
||||
}
|
||||
|
||||
/// Represents a file within the Spacedrive VDFS.
|
||||
@@ -49,9 +43,15 @@ pub struct File {
|
||||
/// The universal path to the file in Spacedrive's VDFS
|
||||
pub sd_path: SdPath,
|
||||
|
||||
/// The file kind (file, directory, symlink)
|
||||
pub kind: EntryKind,
|
||||
|
||||
/// The name of the file, including the extension
|
||||
pub name: String,
|
||||
|
||||
/// The file extension (without dot)
|
||||
pub extension: Option<String>,
|
||||
|
||||
/// The size of the file in bytes
|
||||
pub size: u64,
|
||||
|
||||
@@ -78,10 +78,8 @@ pub struct File {
|
||||
pub accessed_at: Option<DateTime<Utc>>,
|
||||
|
||||
/// Additional computed fields
|
||||
pub content_kind: ContentKind,
|
||||
pub extension: Option<String>,
|
||||
pub kind: EntryKind,
|
||||
pub is_local: bool,
|
||||
pub content_kind: ContentKind, // This is redundant with ContentIdentity, it lives inside
|
||||
pub is_local: bool, // this is also redundant with SdPath
|
||||
|
||||
/// Video duration (for grid display optimization)
|
||||
pub duration_seconds: Option<f64>,
|
||||
@@ -226,22 +224,13 @@ impl File {
|
||||
|
||||
// Convert entity kind to domain EntryKind
|
||||
let kind = match model.kind {
|
||||
0 => EntryKind::File {
|
||||
extension: model.extension.clone(),
|
||||
},
|
||||
0 => EntryKind::File,
|
||||
1 => EntryKind::Directory,
|
||||
2 => EntryKind::Symlink {
|
||||
target: String::new(),
|
||||
},
|
||||
_ => EntryKind::File {
|
||||
extension: model.extension.clone(),
|
||||
},
|
||||
2 => EntryKind::Symlink,
|
||||
_ => EntryKind::File,
|
||||
};
|
||||
|
||||
let extension = match &kind {
|
||||
EntryKind::File { extension } => extension.clone(),
|
||||
_ => None,
|
||||
};
|
||||
let extension = model.extension.clone();
|
||||
|
||||
// Generate UUID from id if uuid is None
|
||||
let id = model.uuid.unwrap_or_else(|| {
|
||||
|
||||
@@ -69,3 +69,4 @@ enum VideoMediaData {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -48,3 +48,4 @@ enum Entries {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,3 +9,4 @@ pub use input::LibraryOpenInput;
|
||||
pub use output::LibraryOpenOutput;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -123,3 +123,4 @@ mod tests {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -15,3 +15,4 @@ pub struct VolumeTrackInput {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@ pub struct VolumeUntrackInput {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
1
crates/log-analyzer/.gitignore
vendored
1
crates/log-analyzer/.gitignore
vendored
@@ -6,3 +6,4 @@ analysis.md
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -40,3 +40,4 @@ required-features = ["cli"]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -51,3 +51,4 @@ fn main() -> Result<()> {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,3 +18,4 @@ pub fn export_json(templates: &[Template], groups: &[LogGroup]) -> Result<String
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -240,3 +240,4 @@ mod tests {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -105,3 +105,4 @@ mod tests {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { QuickPreviewModal } from "./components/QuickPreview";
|
||||
import { createExplorerRouter } from "./router";
|
||||
import { useNormalizedCache } from "./context";
|
||||
import { usePlatform } from "./platform";
|
||||
import type { LocationInfo } from "@sd/ts-client/generated/types";
|
||||
import type { LocationInfo } from "@sd/ts-client";
|
||||
|
||||
interface AppProps {
|
||||
client: SpacedriveClient;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ArrowSquareOut } from "@phosphor-icons/react";
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import type { File, LocationInfo } from "@sd/ts-client/generated/types";
|
||||
import type { File, LocationInfo } from "@sd/ts-client";
|
||||
import { useLibraryQuery, useNormalizedCache } from "./context";
|
||||
import { usePlatform } from "./platform";
|
||||
import { useSelection } from "./components/Explorer/SelectionContext";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import type { File as FileType } from "@sd/ts-client/generated/types";
|
||||
import type { File as FileType } from "@sd/ts-client";
|
||||
import { Thumb } from "./Thumb";
|
||||
import { Title } from "./Title";
|
||||
import { Metadata } from "./Metadata";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { formatBytes, formatRelativeTime } from "../utils";
|
||||
|
||||
interface MetadataProps {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { useState, memo, useEffect } from "react";
|
||||
import clsx from "clsx";
|
||||
import { getIcon } from "@sd/assets/util";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { ThumbstripScrubber } from "./ThumbstripScrubber";
|
||||
|
||||
interface ThumbProps {
|
||||
file: File;
|
||||
size?: number;
|
||||
className?: string;
|
||||
frameClassName?: string; // Custom frame styling (border, radius, bg)
|
||||
iconScale?: number; // Scale factor for fallback icon (0-1, default 1)
|
||||
squareMode?: boolean; // Whether thumbnail is cropped to square (media view) or maintains aspect ratio
|
||||
file: File;
|
||||
size?: number;
|
||||
className?: string;
|
||||
frameClassName?: string; // Custom frame styling (border, radius, bg)
|
||||
iconScale?: number; // Scale factor for fallback icon (0-1, default 1)
|
||||
squareMode?: boolean; // Whether thumbnail is cropped to square (media view) or maintains aspect ratio
|
||||
}
|
||||
|
||||
// Global cache for thumbnail loaded states (survives component unmount/remount)
|
||||
@@ -18,197 +18,197 @@ const thumbLoadedCache = new Map<string, boolean>();
|
||||
const thumbErrorCache = new Map<string, boolean>();
|
||||
|
||||
export const Thumb = memo(function Thumb({
|
||||
file,
|
||||
size = 100,
|
||||
className,
|
||||
frameClassName,
|
||||
iconScale = 1,
|
||||
squareMode = false,
|
||||
file,
|
||||
size = 100,
|
||||
className,
|
||||
frameClassName,
|
||||
iconScale = 1,
|
||||
squareMode = false,
|
||||
}: ThumbProps) {
|
||||
const cacheKey = `${file.id}-${size}`;
|
||||
const cacheKey = `${file.id}-${size}`;
|
||||
|
||||
const [thumbLoaded, setThumbLoaded] = useState(
|
||||
() => thumbLoadedCache.get(cacheKey) || false,
|
||||
);
|
||||
const [thumbError, setThumbError] = useState(
|
||||
() => thumbErrorCache.get(cacheKey) || false,
|
||||
);
|
||||
const [thumbLoaded, setThumbLoaded] = useState(
|
||||
() => thumbLoadedCache.get(cacheKey) || false,
|
||||
);
|
||||
const [thumbError, setThumbError] = useState(
|
||||
() => thumbErrorCache.get(cacheKey) || false,
|
||||
);
|
||||
|
||||
// Update cache when state changes
|
||||
useEffect(() => {
|
||||
if (thumbLoaded) thumbLoadedCache.set(cacheKey, true);
|
||||
}, [thumbLoaded, cacheKey]);
|
||||
// Update cache when state changes
|
||||
useEffect(() => {
|
||||
if (thumbLoaded) thumbLoadedCache.set(cacheKey, true);
|
||||
}, [thumbLoaded, cacheKey]);
|
||||
|
||||
useEffect(() => {
|
||||
if (thumbError) thumbErrorCache.set(cacheKey, true);
|
||||
}, [thumbError, cacheKey]);
|
||||
useEffect(() => {
|
||||
if (thumbError) thumbErrorCache.set(cacheKey, true);
|
||||
}, [thumbError, cacheKey]);
|
||||
|
||||
const iconSize = size * iconScale;
|
||||
const iconSize = size * iconScale;
|
||||
|
||||
// Check if this is a video with thumbstrip sidecar
|
||||
const isVideo = file.content_identity?.kind === "video";
|
||||
const hasThumbstrip = file.sidecars?.some((s) => s.kind === "thumbstrip");
|
||||
// Check if this is a video with thumbstrip sidecar
|
||||
const isVideo = file.content_identity?.kind === "video";
|
||||
const hasThumbstrip = file.sidecars?.some((s) => s.kind === "thumbstrip");
|
||||
|
||||
// Get appropriate thumbnail URL from sidecars based on size
|
||||
const getThumbnailUrl = (targetSize: number) => {
|
||||
const serverUrl = (window as any).__SPACEDRIVE_SERVER_URL__;
|
||||
const libraryId = (window as any).__SPACEDRIVE_LIBRARY_ID__;
|
||||
// Get appropriate thumbnail URL from sidecars based on size
|
||||
const getThumbnailUrl = (targetSize: number) => {
|
||||
const serverUrl = (window as any).__SPACEDRIVE_SERVER_URL__;
|
||||
const libraryId = (window as any).__SPACEDRIVE_LIBRARY_ID__;
|
||||
|
||||
if (!serverUrl || !libraryId) {
|
||||
return null;
|
||||
}
|
||||
if (!serverUrl || !libraryId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Need content_identity to build sidecar URL
|
||||
if (!file.content_identity?.uuid) {
|
||||
return null;
|
||||
}
|
||||
// Need content_identity to build sidecar URL
|
||||
if (!file.content_identity?.uuid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find thumbnail sidecar closest to requested size
|
||||
const thumbnails = file.sidecars.filter((s) => s.kind === "thumb");
|
||||
// Find thumbnail sidecar closest to requested size
|
||||
const thumbnails = file.sidecars.filter((s) => s.kind === "thumb");
|
||||
|
||||
if (thumbnails.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (thumbnails.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Prefer 1x (lower resolution) variants for better performance
|
||||
// Only use higher resolution for very large sizes (>400px)
|
||||
const preferredSize = targetSize <= 400 ? targetSize * 0.6 : targetSize;
|
||||
// Prefer 1x (lower resolution) variants for better performance
|
||||
// Only use higher resolution for very large sizes (>400px)
|
||||
const preferredSize = targetSize <= 400 ? targetSize * 0.6 : targetSize;
|
||||
|
||||
const thumbnail = thumbnails.sort((a, b) => {
|
||||
// Parse variant (e.g., "grid@1x", "detail@1x") to get size and scale
|
||||
const aSize = parseInt(
|
||||
a.variant.split("x")[0]?.replace(/\D/g, "") || "0",
|
||||
);
|
||||
const bSize = parseInt(
|
||||
b.variant.split("x")[0]?.replace(/\D/g, "") || "0",
|
||||
);
|
||||
const thumbnail = thumbnails.sort((a, b) => {
|
||||
// Parse variant (e.g., "grid@1x", "detail@1x") to get size and scale
|
||||
const aSize = parseInt(
|
||||
a.variant.split("x")[0]?.replace(/\D/g, "") || "0",
|
||||
);
|
||||
const bSize = parseInt(
|
||||
b.variant.split("x")[0]?.replace(/\D/g, "") || "0",
|
||||
);
|
||||
|
||||
// Extract scale factor (1x, 2x, 3x) from variants like "grid@1x" or "detail@2x"
|
||||
const aScaleMatch = a.variant.match(/@(\d+)x/);
|
||||
const bScaleMatch = b.variant.match(/@(\d+)x/);
|
||||
const aScale = aScaleMatch ? parseInt(aScaleMatch[1]) : 1;
|
||||
const bScale = bScaleMatch ? parseInt(bScaleMatch[1]) : 1;
|
||||
// Extract scale factor (1x, 2x, 3x) from variants like "grid@1x" or "detail@2x"
|
||||
const aScaleMatch = a.variant.match(/@(\d+)x/);
|
||||
const bScaleMatch = b.variant.match(/@(\d+)x/);
|
||||
const aScale = aScaleMatch ? parseInt(aScaleMatch[1]) : 1;
|
||||
const bScale = bScaleMatch ? parseInt(bScaleMatch[1]) : 1;
|
||||
|
||||
// Strongly prefer 1x variants (add penalty for higher scales)
|
||||
const aPenalty = (aScale - 1) * 100;
|
||||
const bPenalty = (bScale - 1) * 100;
|
||||
// Strongly prefer 1x variants (add penalty for higher scales)
|
||||
const aPenalty = (aScale - 1) * 100;
|
||||
const bPenalty = (bScale - 1) * 100;
|
||||
|
||||
// Find closest match to preferred size, with scale penalty
|
||||
return (
|
||||
Math.abs(aSize - preferredSize) +
|
||||
aPenalty -
|
||||
(Math.abs(bSize - preferredSize) + bPenalty)
|
||||
);
|
||||
})[0];
|
||||
// Find closest match to preferred size, with scale penalty
|
||||
return (
|
||||
Math.abs(aSize - preferredSize) +
|
||||
aPenalty -
|
||||
(Math.abs(bSize - preferredSize) + bPenalty)
|
||||
);
|
||||
})[0];
|
||||
|
||||
const contentUuid = file.content_identity.uuid;
|
||||
const url = `${serverUrl}/sidecar/${libraryId}/${contentUuid}/${thumbnail.kind}/${thumbnail.variant}.${thumbnail.format}`;
|
||||
const contentUuid = file.content_identity.uuid;
|
||||
const url = `${serverUrl}/sidecar/${libraryId}/${contentUuid}/${thumbnail.kind}/${thumbnail.variant}.${thumbnail.format}`;
|
||||
|
||||
return url;
|
||||
};
|
||||
return url;
|
||||
};
|
||||
|
||||
const thumbnailSrc = getThumbnailUrl(size);
|
||||
const thumbnailSrc = getThumbnailUrl(size);
|
||||
|
||||
// Get Spacedrive asset icon (dark theme)
|
||||
const kindCapitalized = file.content_identity?.kind
|
||||
? file.content_identity.kind.charAt(0).toUpperCase() +
|
||||
file.content_identity.kind.slice(1)
|
||||
: "Document";
|
||||
// This is jank and has to be done in several places. Ideally a util function.
|
||||
const fileKind =
|
||||
file?.content_identity?.kind && file.content_identity.kind !== "unknown"
|
||||
? file.content_identity.kind
|
||||
: file.kind === "File"
|
||||
? file.extension || "File"
|
||||
: file.kind;
|
||||
// this too
|
||||
const kindCapitalized = fileKind.charAt(0).toUpperCase() + fileKind.slice(1);
|
||||
|
||||
const icon = getIcon(
|
||||
kindCapitalized,
|
||||
true, // Dark theme
|
||||
file.extension,
|
||||
file.kind === "Directory",
|
||||
);
|
||||
const icon = getIcon(
|
||||
kindCapitalized,
|
||||
true, // Dark theme
|
||||
file.extension,
|
||||
file.kind === "Directory",
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"relative flex shrink-0 grow-0 items-center justify-center",
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
minWidth: size,
|
||||
minHeight: size,
|
||||
maxWidth: size,
|
||||
maxHeight: size,
|
||||
}}
|
||||
>
|
||||
{/* Always show icon first (instant), then thumbnail loads over it */}
|
||||
<img
|
||||
src={icon}
|
||||
alt=""
|
||||
className={clsx(
|
||||
"object-contain transition-opacity",
|
||||
thumbLoaded && "opacity-0",
|
||||
)}
|
||||
style={{
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
maxWidth: "100%",
|
||||
maxHeight: "100%",
|
||||
}}
|
||||
/>
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"relative flex shrink-0 grow-0 items-center justify-center",
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
width: size,
|
||||
height: size,
|
||||
minWidth: size,
|
||||
minHeight: size,
|
||||
maxWidth: size,
|
||||
maxHeight: size,
|
||||
}}
|
||||
>
|
||||
{/* Always show icon first (instant), then thumbnail loads over it */}
|
||||
<img
|
||||
src={icon}
|
||||
alt=""
|
||||
className={clsx(
|
||||
"object-contain transition-opacity",
|
||||
thumbLoaded && "opacity-0",
|
||||
)}
|
||||
style={{
|
||||
width: iconSize,
|
||||
height: iconSize,
|
||||
maxWidth: "100%",
|
||||
maxHeight: "100%",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Load thumbnail if available */}
|
||||
{thumbnailSrc && !thumbError && (
|
||||
<img
|
||||
src={thumbnailSrc}
|
||||
alt={file.name}
|
||||
className={clsx(
|
||||
"absolute inset-0 m-auto max-h-full max-w-full object-contain transition-opacity",
|
||||
// Default frame styling (can be overridden)
|
||||
frameClassName ||
|
||||
"rounded-lg border border-app-line/50 bg-app-box/30",
|
||||
!thumbLoaded && "opacity-0",
|
||||
)}
|
||||
onLoad={() => setThumbLoaded(true)}
|
||||
onError={() => setThumbError(true)}
|
||||
/>
|
||||
)}
|
||||
{/* Load thumbnail if available */}
|
||||
{thumbnailSrc && !thumbError && (
|
||||
<img
|
||||
src={thumbnailSrc}
|
||||
alt={file.name}
|
||||
className={clsx(
|
||||
"absolute inset-0 m-auto max-h-full max-w-full object-contain transition-opacity",
|
||||
// Default frame styling (can be overridden)
|
||||
frameClassName ||
|
||||
"rounded-lg border border-app-line/50 bg-app-box/30",
|
||||
!thumbLoaded && "opacity-0",
|
||||
)}
|
||||
onLoad={() => setThumbLoaded(true)}
|
||||
onError={() => setThumbError(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Thumbstrip scrubber overlay (for videos with thumbstrips) */}
|
||||
{isVideo && hasThumbstrip && thumbLoaded && (
|
||||
<ThumbstripScrubber
|
||||
file={file}
|
||||
size={size}
|
||||
squareMode={squareMode}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
{/* Thumbstrip scrubber overlay (for videos with thumbstrips) */}
|
||||
{isVideo && hasThumbstrip && thumbLoaded && (
|
||||
<ThumbstripScrubber file={file} size={size} squareMode={squareMode} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export function Icon({
|
||||
file,
|
||||
size = 24,
|
||||
className,
|
||||
file,
|
||||
size = 24,
|
||||
className,
|
||||
}: {
|
||||
file: File;
|
||||
size?: number;
|
||||
className?: string;
|
||||
file: File;
|
||||
size?: number;
|
||||
className?: string;
|
||||
}) {
|
||||
const kindCapitalized = file.content_identity?.kind
|
||||
? file.content_identity.kind.charAt(0).toUpperCase() +
|
||||
file.content_identity.kind.slice(1)
|
||||
: "Document";
|
||||
const kindCapitalized = file.content_identity?.kind
|
||||
? file.content_identity.kind.charAt(0).toUpperCase() +
|
||||
file.content_identity.kind.slice(1)
|
||||
: "Document";
|
||||
|
||||
const icon = getIcon(
|
||||
kindCapitalized,
|
||||
true, // Dark theme
|
||||
file.extension,
|
||||
file.kind === "Directory",
|
||||
);
|
||||
const icon = getIcon(
|
||||
kindCapitalized,
|
||||
true, // Dark theme
|
||||
file.kind.type === "File" ? file.kind.data?.extension : undefined,
|
||||
file.kind.type === "Directory",
|
||||
);
|
||||
|
||||
return (
|
||||
<img
|
||||
src={icon}
|
||||
alt=""
|
||||
className={className}
|
||||
style={{ width: size, height: size }}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<img
|
||||
src={icon}
|
||||
alt=""
|
||||
className={className}
|
||||
style={{ width: size, height: size }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useRef, useEffect, memo } from "react";
|
||||
import clsx from "clsx";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
|
||||
interface ThumbstripScrubberProps {
|
||||
file: File;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import clsx from "clsx";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
|
||||
interface TitleProps {
|
||||
file: File;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createContext, useContext, useState, useCallback, useMemo, useEffect, type ReactNode } from "react";
|
||||
import { usePlatform } from "../../platform";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
|
||||
interface SelectionContextValue {
|
||||
selectedFiles: File[];
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
import { TopBarButton } from "@sd/ui";
|
||||
import type { DirectorySortBy, MediaSortBy } from "@sd/ts-client/generated/types";
|
||||
import type { DirectorySortBy, MediaSortBy } from "@sd/ts-client";
|
||||
|
||||
interface SortMenuProps {
|
||||
sortBy: DirectorySortBy | MediaSortBy;
|
||||
|
||||
@@ -15,7 +15,7 @@ import * as Tabs from "@sd/ui/Tabs";
|
||||
import type {
|
||||
IndexMode,
|
||||
LocationAddInput,
|
||||
} from "@sd/ts-client/generated/types";
|
||||
} from "@sd/ts-client";
|
||||
import { useLibraryMutation, useLibraryQuery } from "../../../context";
|
||||
import { usePlatform } from "../../../platform";
|
||||
import { NewLocation } from "@sd/assets/icons";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import type { SdPath } from "@sd/ts-client/generated/types";
|
||||
import type { SdPath } from "@sd/ts-client";
|
||||
|
||||
interface BreadcrumbProps {
|
||||
path: SdPath;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useRef, useEffect } from "react";
|
||||
import { Plus } from "@phosphor-icons/react";
|
||||
import type { LocationInfo } from "@sd/ts-client/generated/types";
|
||||
import type { LocationInfo } from "@sd/ts-client";
|
||||
import { useNormalizedCache } from "../../../context";
|
||||
import { Section } from "./Section";
|
||||
import { SidebarItem } from "./SidebarItem";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState, useEffect } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import clsx from "clsx";
|
||||
import { CaretRight } from "@phosphor-icons/react";
|
||||
import type { SdPath, LibraryDeviceInfo } from "@sd/ts-client/generated/types";
|
||||
import type { SdPath, LibraryDeviceInfo } from "@sd/ts-client";
|
||||
import { getDeviceIconBySlug } from "@sd/ts-client";
|
||||
import { sdPathToUri } from "../utils";
|
||||
import LaptopIcon from "@sd/assets/icons/Laptop.png";
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
LibraryDeviceInfo,
|
||||
DirectorySortBy,
|
||||
MediaSortBy,
|
||||
} from "@sd/ts-client/generated/types";
|
||||
} from "@sd/ts-client";
|
||||
|
||||
interface ViewSettings {
|
||||
gridSize: number; // 80-400px
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect } from "react";
|
||||
import { useExplorer } from "../context";
|
||||
import { useSelection } from "../SelectionContext";
|
||||
import { useNormalizedCache } from "../../../context";
|
||||
import type { DirectorySortBy } from "@sd/ts-client/generated/types";
|
||||
import type { DirectorySortBy } from "@sd/ts-client";
|
||||
|
||||
export function useExplorerKeyboard() {
|
||||
const { currentPath, sortBy, setCurrentPath, viewMode, viewSettings, sidebarVisible, inspectorVisible, openQuickPreview } = useExplorer();
|
||||
@@ -85,7 +85,7 @@ export function useExplorerKeyboard() {
|
||||
// Enter: Navigate into directory (for column view)
|
||||
if (e.key === "Enter" && selectedFiles.length === 1) {
|
||||
const selected = selectedFiles[0];
|
||||
if (selected.kind === "Directory") {
|
||||
if (selected.kind.type === "Directory") {
|
||||
e.preventDefault();
|
||||
setCurrentPath(selected.sd_path);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import LaptopIcon from "@sd/assets/icons/Laptop.png";
|
||||
import MobileIcon from "@sd/assets/icons/Mobile.png";
|
||||
import ServerIcon from "@sd/assets/icons/Server.png";
|
||||
import PCIcon from "@sd/assets/icons/PC.png";
|
||||
import type { SdPath } from "@sd/ts-client/generated/types";
|
||||
import type { SdPath } from "@sd/ts-client";
|
||||
|
||||
export function formatBytes(bytes: number): string {
|
||||
if (bytes === 0) return "0 B";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useRef, useMemo } from "react";
|
||||
import { useVirtualizer } from "@tanstack/react-virtual";
|
||||
import clsx from "clsx";
|
||||
import type { File, SdPath } from "@sd/ts-client/generated/types";
|
||||
import type { File, SdPath } from "@sd/ts-client";
|
||||
import { useNormalizedCache } from "../../../../context";
|
||||
import { ColumnItem } from "./ColumnItem";
|
||||
import { useExplorer } from "../../context";
|
||||
@@ -67,7 +67,7 @@ export function Column({ path, isActive, onNavigate }: ColumnProps) {
|
||||
icon: FolderOpen,
|
||||
label: "Open",
|
||||
onClick: (file: File) => {
|
||||
if (file.kind === "Directory") {
|
||||
if (file.kind.type === "Directory") {
|
||||
onNavigate(file.sd_path);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { File as FileComponent } from "../../File";
|
||||
|
||||
interface ColumnItemProps {
|
||||
@@ -40,7 +40,7 @@ export function ColumnItem({
|
||||
>
|
||||
<FileComponent.Thumb file={file} size={20} />
|
||||
<span className="text-sm truncate flex-1">{file.name}</span>
|
||||
{file.kind === "Directory" && (
|
||||
{file.kind.type === "Directory" && (
|
||||
<svg
|
||||
className="size-3 text-ink-dull"
|
||||
fill="none"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import type { SdPath } from "@sd/ts-client/generated/types";
|
||||
import type { SdPath } from "@sd/ts-client";
|
||||
import { useExplorer } from "../../context";
|
||||
import { useSelection } from "../../SelectionContext";
|
||||
import { Column } from "./Column";
|
||||
@@ -19,7 +19,7 @@ export function ColumnView() {
|
||||
|
||||
// Add a column when a directory is selected
|
||||
useEffect(() => {
|
||||
if (selectedFiles.length === 1 && selectedFiles[0].kind === "Directory") {
|
||||
if (selectedFiles.length === 1 && selectedFiles[0].kind.type === "Directory") {
|
||||
const selectedDir = selectedFiles[0];
|
||||
const selectedPath = selectedDir.sd_path;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
Crop,
|
||||
FileVideo,
|
||||
} from "@phosphor-icons/react";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { File as FileComponent } from "../../File";
|
||||
import { useExplorer } from "../../context";
|
||||
import { useSelection } from "../../SelectionContext";
|
||||
@@ -70,7 +70,7 @@ export const FileCard = memo(function FileCard({ file, fileIndex, allFiles, sele
|
||||
icon: FolderOpen,
|
||||
label: "Open",
|
||||
onClick: () => {
|
||||
if (file.kind === "Directory") {
|
||||
if (file.kind.type === "Directory") {
|
||||
setCurrentPath(file.sd_path);
|
||||
} else {
|
||||
console.log("Open file:", file.name);
|
||||
@@ -78,7 +78,7 @@ export const FileCard = memo(function FileCard({ file, fileIndex, allFiles, sele
|
||||
}
|
||||
},
|
||||
keybind: "⌘O",
|
||||
condition: () => file.kind === "Directory" || file.kind === "File",
|
||||
condition: () => file.kind.type === "Directory" || file.kind.type === "File",
|
||||
},
|
||||
{
|
||||
icon: MagnifyingGlass,
|
||||
@@ -308,7 +308,7 @@ export const FileCard = memo(function FileCard({ file, fileIndex, allFiles, sele
|
||||
type: "submenu",
|
||||
icon: FileText,
|
||||
label: "Document Processing",
|
||||
condition: () => ["pdf", "doc", "docx"].includes(file.extension || ""),
|
||||
condition: () => ["pdf", "doc", "docx"].includes(file.kind.type === "File" ? file.kind.data?.extension || "" : ""),
|
||||
submenu: [
|
||||
{
|
||||
icon: TextAa,
|
||||
@@ -425,7 +425,7 @@ export const FileCard = memo(function FileCard({ file, fileIndex, allFiles, sele
|
||||
};
|
||||
|
||||
const handleDoubleClick = () => {
|
||||
if (file.kind === "Directory") {
|
||||
if (file.kind.type === "Directory") {
|
||||
setCurrentPath(file.sd_path);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useExplorer } from "../../context";
|
||||
import { useSelection } from "../../SelectionContext";
|
||||
import { useNormalizedCache } from "../../../../context";
|
||||
import { FileCard } from "./FileCard";
|
||||
import type { DirectorySortBy } from "@sd/ts-client/generated/types";
|
||||
import type { DirectorySortBy } from "@sd/ts-client";
|
||||
|
||||
export function GridView() {
|
||||
const { currentPath, sortBy, viewSettings } = useExplorer();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { File as FileComponent } from "../../File";
|
||||
import { useExplorer } from "../../context";
|
||||
import { useSelection } from "../../SelectionContext";
|
||||
@@ -24,7 +24,7 @@ export function FileRow({ file, fileIndex, allFiles }: FileRowProps) {
|
||||
};
|
||||
|
||||
const handleDoubleClick = () => {
|
||||
if (file.kind === "Directory") {
|
||||
if (file.kind.type === "Directory") {
|
||||
setCurrentPath(file.sd_path);
|
||||
}
|
||||
};
|
||||
@@ -60,7 +60,7 @@ export function FileRow({ file, fileIndex, allFiles }: FileRowProps) {
|
||||
{formatRelativeTime(file.modified_at)}
|
||||
</div>
|
||||
<div className="w-24 text-sm text-ink-dull">
|
||||
{file.extension || "Folder"}
|
||||
{file.kind.type === "File" ? file.kind.data?.extension || "—" : "Folder"}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useExplorer } from "../../context";
|
||||
import { useNormalizedCache } from "../../../../context";
|
||||
import { FileRow } from "./FileRow";
|
||||
import type { DirectorySortBy } from "@sd/ts-client/generated/types";
|
||||
import type { DirectorySortBy } from "@sd/ts-client";
|
||||
|
||||
export function ListView() {
|
||||
const { currentPath, sortBy } = useExplorer();
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
Crop,
|
||||
FileVideo,
|
||||
} from "@phosphor-icons/react";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { File as FileComponent } from "../../File";
|
||||
import { useExplorer } from "../../context";
|
||||
import { useSelection } from "../../SelectionContext";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
|
||||
export function formatDate(
|
||||
date: Date | { from: Date; to: Date },
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { formatBytes } from "../../utils";
|
||||
|
||||
interface SizeCircleProps {
|
||||
@@ -11,7 +11,7 @@ interface SizeCircleProps {
|
||||
|
||||
// Get file extension or type
|
||||
function getFileType(file: File): string {
|
||||
if (file.kind === "Directory") return "Folder";
|
||||
if (file.kind.type === "Directory") return "Folder";
|
||||
|
||||
const name = file.name;
|
||||
const lastDot = name.lastIndexOf(".");
|
||||
@@ -22,7 +22,7 @@ function getFileType(file: File): string {
|
||||
|
||||
// Get color based on file type
|
||||
function getFileColor(file: File): string {
|
||||
if (file.kind === "Directory") return "bg-blue-500";
|
||||
if (file.kind.type === "Directory") return "bg-blue-500";
|
||||
|
||||
const ext = file.name.split(".").pop()?.toLowerCase() || "";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useMemo, useState } from "react";
|
||||
import * as d3 from "d3";
|
||||
import type { File, DirectorySortBy } from "@sd/ts-client/generated/types";
|
||||
import type { File, DirectorySortBy } from "@sd/ts-client";
|
||||
import { useExplorer } from "../../context";
|
||||
import { useSelection } from "../../SelectionContext";
|
||||
import { useNormalizedCache } from "../../../../context";
|
||||
@@ -29,7 +29,7 @@ function getTailwindColor(className: string): string {
|
||||
}
|
||||
|
||||
function getFileColorClass(file: File): string {
|
||||
if (file.kind === "Directory") return "bg-accent";
|
||||
if (file.kind.type === "Directory") return "bg-accent";
|
||||
|
||||
const ext = file.name.split(".").pop()?.toLowerCase() || "";
|
||||
|
||||
@@ -71,7 +71,7 @@ function getFileColor(file: File): string {
|
||||
}
|
||||
|
||||
function getFileType(file: File): string {
|
||||
if (file.kind === "Directory") return "Folder";
|
||||
if (file.kind.type === "Directory") return "Folder";
|
||||
|
||||
const name = file.name;
|
||||
const lastDot = name.lastIndexOf(".");
|
||||
@@ -348,7 +348,7 @@ export function SizeView() {
|
||||
}
|
||||
|
||||
// Navigate if directory
|
||||
if (d.data.file.kind === "Directory") {
|
||||
if (d.data.file.kind.type === "Directory") {
|
||||
setCurrentPathRef.current(d.data.file.sd_path);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { JobStatus } from "@sd/ts-client/generated/types";
|
||||
import type { JobStatus } from "@sd/ts-client";
|
||||
import { JOB_STATUS_COLORS, PROGRESS_BAR_HEIGHT } from "../types";
|
||||
|
||||
interface JobProgressBarProps {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { JobStatus } from "@sd/ts-client/generated/types";
|
||||
import type { JobStatus } from "@sd/ts-client";
|
||||
import {
|
||||
MagnifyingGlass,
|
||||
Image,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { JobStatus, JobListItem as GeneratedJobListItem, JsonValue, SdPath } from "@sd/ts-client/generated/types";
|
||||
import type { JobStatus, JobListItem as GeneratedJobListItem, JsonValue, SdPath } from "@sd/ts-client";
|
||||
|
||||
// Extend the generated type with runtime fields from JobProgress events
|
||||
export type JobListItem = GeneratedJobListItem & {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
SkipForward,
|
||||
} from "@phosphor-icons/react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { File as FileComponent } from "../Explorer/File";
|
||||
import { formatBytes } from "../Explorer/utils";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { File, ContentKind } from "@sd/ts-client/generated/types";
|
||||
import type { File, ContentKind } from "@sd/ts-client";
|
||||
import { File as FileComponent } from "../Explorer/File";
|
||||
import { formatBytes } from "../Explorer/utils";
|
||||
import { usePlatform } from "../../platform";
|
||||
@@ -295,7 +295,7 @@ function DefaultRenderer({ file }: ContentRendererProps) {
|
||||
|
||||
export function ContentRenderer({ file }: ContentRendererProps) {
|
||||
// Handle directories first
|
||||
if (file.kind === "Directory") {
|
||||
if (file.kind.type === "Directory") {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full text-ink-dull">
|
||||
<img src={Folder} alt="Folder Icon" className="w-16 h-16 mb-4" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useLibraryQuery } from "../../context";
|
||||
import { usePlatform } from "../../platform";
|
||||
import type { File } from "@sd/ts-client/generated/types";
|
||||
import type { File } from "@sd/ts-client";
|
||||
import { useEffect, useState } from "react";
|
||||
import { formatBytes } from "../Explorer/utils";
|
||||
import { X } from "@phosphor-icons/react";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { X, ArrowLeft, ArrowRight } from '@phosphor-icons/react';
|
||||
import { useEffect } from 'react';
|
||||
import type { File } from '@sd/ts-client/generated/types';
|
||||
import type { File } from '@sd/ts-client';
|
||||
import { useLibraryQuery } from '../../context';
|
||||
import { Inspector } from '../../Inspector';
|
||||
import { ContentRenderer } from './ContentRenderer';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import type { File } from '@sd/ts-client/generated/types';
|
||||
import type { File } from '@sd/ts-client';
|
||||
|
||||
interface SubtitleCue {
|
||||
index: number;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { memo } from 'react';
|
||||
import type { File } from '@sd/ts-client/generated/types';
|
||||
import type { File } from '@sd/ts-client';
|
||||
|
||||
interface TimelineScrubberProps {
|
||||
file: File;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Play, Pause, SpeakerHigh, SpeakerSlash, ArrowsOut, ClosedCaptioning, MagnifyingGlassPlus, MagnifyingGlassMinus, ArrowCounterClockwise, Gear } from '@phosphor-icons/react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import type { File } from '@sd/ts-client/generated/types';
|
||||
import type { File } from '@sd/ts-client';
|
||||
import { Subtitles, type SubtitleSettings } from './Subtitles';
|
||||
import { SubtitleSettingsMenu } from './SubtitleSettingsMenu';
|
||||
import { useZoomPan } from './useZoomPan';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState } from 'react';
|
||||
import { Input, Label, dialogManager, useDialog, Dialog } from '@sd/ui';
|
||||
import { useLibraryMutation } from '@sd/ts-client';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import type { GroupType } from '@sd/ts-client/generated/types';
|
||||
import type { GroupType } from '@sd/ts-client';
|
||||
|
||||
interface FormData {
|
||||
groupName: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CaretRight, Desktop } from '@phosphor-icons/react';
|
||||
import clsx from 'clsx';
|
||||
import type { SpaceItem as SpaceItemType } from '@sd/ts-client/generated/types';
|
||||
import type { SpaceItem as SpaceItemType } from '@sd/ts-client';
|
||||
import { SpaceItem } from './SpaceItem';
|
||||
|
||||
interface DeviceGroupProps {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
SpaceGroup as SpaceGroupType,
|
||||
SpaceItem as SpaceItemType,
|
||||
GroupType,
|
||||
} from '@sd/ts-client/generated/types';
|
||||
} from '@sd/ts-client';
|
||||
import { useSidebarStore } from '@sd/ts-client/stores/sidebar';
|
||||
import { SpaceItem } from './SpaceItem';
|
||||
import { DeviceGroup } from './DeviceGroup';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Location } from "@sd/assets/icons";
|
||||
import type {
|
||||
SpaceItem as SpaceItemType,
|
||||
ItemType,
|
||||
} from "@sd/ts-client/generated/types";
|
||||
} from "@sd/ts-client";
|
||||
|
||||
interface SpaceItemProps {
|
||||
item: SpaceItemType;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import clsx from 'clsx';
|
||||
import { CaretDown, Plus, GearSix } from '@phosphor-icons/react';
|
||||
import { DropdownMenu } from '@sd/ui';
|
||||
import type { Space } from '@sd/ts-client/generated/types';
|
||||
import type { Space } from '@sd/ts-client';
|
||||
import { useCreateSpaceDialog } from './CreateSpaceModal';
|
||||
|
||||
interface SpaceSwitcherProps {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CaretRight } from "@phosphor-icons/react";
|
||||
import clsx from "clsx";
|
||||
import { useNormalizedCache } from "@sd/ts-client";
|
||||
import { SpaceItem } from "./SpaceItem";
|
||||
import type { VolumeItem } from "@sd/ts-client/generated/types";
|
||||
import type { VolumeItem } from "@sd/ts-client";
|
||||
|
||||
interface VolumesGroupProps {
|
||||
isCollapsed: boolean;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
Share,
|
||||
SignIn
|
||||
} from '@phosphor-icons/react';
|
||||
import type { LibrarySyncAction, PairedDeviceInfo, RemoteLibraryInfo } from '@sd/ts-client/generated/types';
|
||||
import type { LibrarySyncAction, PairedDeviceInfo, RemoteLibraryInfo } from '@sd/ts-client';
|
||||
import { Button, Dialog, dialogManager, useDialog } from '@sd/ui';
|
||||
import { useCoreQuery, useCoreMutation, useSpacedriveClient } from '../context';
|
||||
|
||||
|
||||
@@ -28,4 +28,4 @@ export type {
|
||||
LocationInfo,
|
||||
LocationsListOutput,
|
||||
LibraryInfo,
|
||||
} from "@sd/ts-client/generated/types";
|
||||
} from "@sd/ts-client";
|
||||
@@ -58,3 +58,4 @@ export function useJobDispatch() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@ import {
|
||||
TabContent,
|
||||
} from "../components/Inspector";
|
||||
import clsx from "clsx";
|
||||
import type { LocationInfo } from "@sd/ts-client/generated/types";
|
||||
import type { LocationInfo } from "@sd/ts-client";
|
||||
import { useLibraryMutation } from "../context";
|
||||
import LocationIcon from "@sd/assets/icons/Location.png";
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
VolumeItem,
|
||||
LibraryDeviceInfo,
|
||||
ListLibraryDevicesInput,
|
||||
} from "@sd/ts-client/generated/types";
|
||||
} from "@sd/ts-client";
|
||||
|
||||
function formatBytes(bytes: number): string {
|
||||
if (bytes === 0) return "0 B";
|
||||
|
||||
@@ -11,7 +11,7 @@ import { DevicesPanel } from "./DevicesPanel";
|
||||
import { ContentBreakdown } from "./ContentBreakdown";
|
||||
import { OverviewTopBar } from "./OverviewTopBar";
|
||||
import { useNormalizedCache } from "../../context";
|
||||
import type { LibraryInfoOutput } from "@sd/ts-client/generated/types";
|
||||
import type { LibraryInfoOutput } from "@sd/ts-client";
|
||||
|
||||
export function Overview() {
|
||||
// Fetch library info with statistics using normalizedCache
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
"description": "Type-safe TypeScript client for Spacedrive daemon",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./generated/types": {
|
||||
"types": "./dist/generated/types.d.ts",
|
||||
"default": "./dist/generated/types.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import type { LibraryDeviceInfo } from "./generated/types";
|
||||
import Laptop from "@sd/assets/icons/Laptop.png";
|
||||
import Mobile from "@sd/assets/icons/Mobile.png";
|
||||
|
||||
@@ -88,6 +88,5 @@ export const DEFAULT_EVENT_SUBSCRIPTION: EventVariant[] = [
|
||||
* Noisy events that are excluded from the default subscription
|
||||
*/
|
||||
export const NOISY_EVENTS: EventVariant[] = [
|
||||
"LogMessage",
|
||||
"IndexingProgress",
|
||||
];
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// This file has been generated by Specta. DO NOT EDIT.
|
||||
|
||||
export type Empty = Record<string, never>;
|
||||
|
||||
export type ActionContextInfo = { action_type: string; initiated_at: string; initiated_by: string | null; action_input: JsonValue; context: JsonValue };
|
||||
|
||||
export type AddGroupInput = { space_id: string; name: string; group_type: GroupType };
|
||||
@@ -390,11 +392,7 @@ export type EntryKind =
|
||||
/**
|
||||
* Regular file
|
||||
*/
|
||||
{ File: {
|
||||
/**
|
||||
* File extension (without dot)
|
||||
*/
|
||||
extension: string | null } } |
|
||||
"File" |
|
||||
/**
|
||||
* Directory
|
||||
*/
|
||||
@@ -402,11 +400,7 @@ extension: string | null } } |
|
||||
/**
|
||||
* Symbolic link
|
||||
*/
|
||||
{ Symlink: {
|
||||
/**
|
||||
* Target path
|
||||
*/
|
||||
target: string } };
|
||||
"Symlink";
|
||||
|
||||
/**
|
||||
* Error event for tracking recent errors
|
||||
@@ -511,10 +505,18 @@ id: string;
|
||||
* The universal path to the file in Spacedrive's VDFS
|
||||
*/
|
||||
sd_path: SdPath;
|
||||
/**
|
||||
* The file kind (file, directory, symlink)
|
||||
*/
|
||||
kind: EntryKind;
|
||||
/**
|
||||
* The name of the file, including the extension
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The file extension (without dot)
|
||||
*/
|
||||
extension: string | null;
|
||||
/**
|
||||
* The size of the file in bytes
|
||||
*/
|
||||
@@ -546,7 +548,7 @@ created_at: string; modified_at: string; accessed_at: string | null;
|
||||
/**
|
||||
* Additional computed fields
|
||||
*/
|
||||
content_kind: ContentKind; extension: string | null; kind: EntryKind; is_local: boolean;
|
||||
content_kind: ContentKind; is_local: boolean;
|
||||
/**
|
||||
* Video duration (for grid display optimization)
|
||||
*/
|
||||
@@ -3177,185 +3179,185 @@ success: boolean };
|
||||
// ===== API Type Unions =====
|
||||
|
||||
export type CoreAction =
|
||||
{ type: 'network.start'; input: NetworkStartInput; output: NetworkStartOutput }
|
||||
| { type: 'network.device.revoke'; input: DeviceRevokeInput; output: DeviceRevokeOutput }
|
||||
| { type: 'network.pair.cancel'; input: PairCancelInput; output: PairCancelOutput }
|
||||
| { type: 'network.stop'; input: NetworkStopInput; output: NetworkStopOutput }
|
||||
| { type: 'network.sync_setup'; input: LibrarySyncSetupInput; output: LibrarySyncSetupOutput }
|
||||
{ type: 'network.stop'; input: NetworkStopInput; output: NetworkStopOutput }
|
||||
| { type: 'network.start'; input: NetworkStartInput; output: NetworkStartOutput }
|
||||
| { type: 'network.pair.join'; input: PairJoinInput; output: PairJoinOutput }
|
||||
| { type: 'network.pair.generate'; input: PairGenerateInput; output: PairGenerateOutput }
|
||||
| { type: 'libraries.open'; input: LibraryOpenInput; output: LibraryOpenOutput }
|
||||
| { type: 'network.spacedrop.send'; input: SpacedropSendInput; output: SpacedropSendOutput }
|
||||
| { type: 'libraries.delete'; input: LibraryDeleteInput; output: LibraryDeleteOutput }
|
||||
| { type: 'libraries.create'; input: LibraryCreateInput; output: LibraryCreateOutput }
|
||||
| { type: 'models.whisper.delete'; input: DeleteWhisperModelInput; output: DeleteWhisperModelOutput }
|
||||
| { type: 'models.whisper.download'; input: DownloadWhisperModelInput; output: DownloadWhisperModelOutput }
|
||||
| { type: 'network.sync_setup'; input: LibrarySyncSetupInput; output: LibrarySyncSetupOutput }
|
||||
| { type: 'network.device.revoke'; input: DeviceRevokeInput; output: DeviceRevokeOutput }
|
||||
| { type: 'libraries.delete'; input: LibraryDeleteInput; output: LibraryDeleteOutput }
|
||||
| { type: 'network.pair.cancel'; input: PairCancelInput; output: PairCancelOutput }
|
||||
| { type: 'network.spacedrop.send'; input: SpacedropSendInput; output: SpacedropSendOutput }
|
||||
;
|
||||
|
||||
export type LibraryAction =
|
||||
{ type: 'volumes.track'; input: VolumeTrackInput; output: VolumeTrackOutput }
|
||||
| { type: 'locations.rescan'; input: LocationRescanInput; output: LocationRescanOutput }
|
||||
| { type: 'volumes.untrack'; input: VolumeUntrackInput; output: VolumeUntrackOutput }
|
||||
| { type: 'volumes.remove_cloud'; input: VolumeRemoveCloudInput; output: VolumeRemoveCloudOutput }
|
||||
| { type: 'media.ocr.extract'; input: ExtractTextInput; output: ExtractTextOutput }
|
||||
| { type: 'spaces.delete_item'; input: DeleteItemInput; output: DeleteItemOutput }
|
||||
| { type: 'libraries.rename'; input: LibraryRenameInput; output: LibraryRenameOutput }
|
||||
| { type: 'indexing.start'; input: IndexInput; output: JobReceipt }
|
||||
| { type: 'volumes.speed_test'; input: VolumeSpeedTestInput; output: VolumeSpeedTestOutput }
|
||||
| { type: 'spaces.delete'; input: SpaceDeleteInput; output: SpaceDeleteOutput }
|
||||
| { type: 'media.proxy.generate'; input: GenerateProxyInput; output: GenerateProxyOutput }
|
||||
| { type: 'volumes.add_cloud'; input: VolumeAddCloudInput; output: VolumeAddCloudOutput }
|
||||
| { type: 'indexing.verify'; input: IndexVerifyInput; output: IndexVerifyOutput }
|
||||
| { type: 'jobs.resume'; input: JobResumeInput; output: JobResumeOutput }
|
||||
| { type: 'files.copy'; input: FileCopyInput; output: JobReceipt }
|
||||
| { type: 'spaces.delete_group'; input: DeleteGroupInput; output: DeleteGroupOutput }
|
||||
| { type: 'spaces.update_group'; input: UpdateGroupInput; output: UpdateGroupOutput }
|
||||
| { type: 'media.speech.transcribe'; input: TranscribeAudioInput; output: TranscribeAudioOutput }
|
||||
| { type: 'locations.remove'; input: LocationRemoveInput; output: LocationRemoveOutput }
|
||||
| { type: 'spaces.reorder_items'; input: ReorderItemsInput; output: ReorderOutput }
|
||||
| { type: 'spaces.reorder_groups'; input: ReorderGroupsInput; output: ReorderOutput }
|
||||
| { type: 'tags.apply'; input: ApplyTagsInput; output: ApplyTagsOutput }
|
||||
| { type: 'volumes.refresh'; input: VolumeRefreshInput; output: VolumeRefreshOutput }
|
||||
{ type: 'jobs.resume'; input: JobResumeInput; output: JobResumeOutput }
|
||||
| { type: 'media.thumbnail.regenerate'; input: RegenerateThumbnailInput; output: RegenerateThumbnailOutput }
|
||||
| { type: 'media.thumbnail'; input: ThumbnailInput; output: JobReceipt }
|
||||
| { type: 'media.thumbstrip.generate'; input: GenerateThumbstripInput; output: GenerateThumbstripOutput }
|
||||
| { type: 'spaces.add_item'; input: AddItemInput; output: AddItemOutput }
|
||||
| { type: 'jobs.pause'; input: JobPauseInput; output: JobPauseOutput }
|
||||
| { type: 'locations.update'; input: LocationUpdateInput; output: LocationUpdateOutput }
|
||||
| { type: 'locations.add'; input: LocationAddInput; output: LocationAddOutput }
|
||||
| { type: 'jobs.cancel'; input: JobCancelInput; output: JobCancelOutput }
|
||||
| { type: 'spaces.add_group'; input: AddGroupInput; output: AddGroupOutput }
|
||||
| { type: 'spaces.update'; input: SpaceUpdateInput; output: SpaceUpdateOutput }
|
||||
| { type: 'files.delete'; input: FileDeleteInput; output: JobReceipt }
|
||||
| { type: 'tags.create'; input: CreateTagInput; output: CreateTagOutput }
|
||||
| { type: 'libraries.rename'; input: LibraryRenameInput; output: LibraryRenameOutput }
|
||||
| { type: 'spaces.delete_group'; input: DeleteGroupInput; output: DeleteGroupOutput }
|
||||
| { type: 'tags.apply'; input: ApplyTagsInput; output: ApplyTagsOutput }
|
||||
| { type: 'locations.rescan'; input: LocationRescanInput; output: LocationRescanOutput }
|
||||
| { type: 'volumes.add_cloud'; input: VolumeAddCloudInput; output: VolumeAddCloudOutput }
|
||||
| { type: 'libraries.export'; input: LibraryExportInput; output: LibraryExportOutput }
|
||||
| { type: 'volumes.speed_test'; input: VolumeSpeedTestInput; output: VolumeSpeedTestOutput }
|
||||
| { type: 'spaces.create'; input: SpaceCreateInput; output: SpaceCreateOutput }
|
||||
| { type: 'spaces.delete'; input: SpaceDeleteInput; output: SpaceDeleteOutput }
|
||||
| { type: 'locations.add'; input: LocationAddInput; output: LocationAddOutput }
|
||||
| { type: 'indexing.start'; input: IndexInput; output: JobReceipt }
|
||||
| { type: 'spaces.add_group'; input: AddGroupInput; output: AddGroupOutput }
|
||||
| { type: 'tags.create'; input: CreateTagInput; output: CreateTagOutput }
|
||||
| { type: 'spaces.delete_item'; input: DeleteItemInput; output: DeleteItemOutput }
|
||||
| { type: 'jobs.cancel'; input: JobCancelInput; output: JobCancelOutput }
|
||||
| { type: 'volumes.track'; input: VolumeTrackInput; output: VolumeTrackOutput }
|
||||
| { type: 'spaces.add_item'; input: AddItemInput; output: AddItemOutput }
|
||||
| { type: 'spaces.update'; input: SpaceUpdateInput; output: SpaceUpdateOutput }
|
||||
| { type: 'jobs.pause'; input: JobPauseInput; output: JobPauseOutput }
|
||||
| { type: 'media.proxy.generate'; input: GenerateProxyInput; output: GenerateProxyOutput }
|
||||
| { type: 'volumes.remove_cloud'; input: VolumeRemoveCloudInput; output: VolumeRemoveCloudOutput }
|
||||
| { type: 'media.ocr.extract'; input: ExtractTextInput; output: ExtractTextOutput }
|
||||
| { type: 'volumes.refresh'; input: VolumeRefreshInput; output: VolumeRefreshOutput }
|
||||
| { type: 'volumes.untrack'; input: VolumeUntrackInput; output: VolumeUntrackOutput }
|
||||
| { type: 'locations.update'; input: LocationUpdateInput; output: LocationUpdateOutput }
|
||||
| { type: 'locations.triggerJob'; input: LocationTriggerJobInput; output: LocationTriggerJobOutput }
|
||||
| { type: 'files.copy'; input: FileCopyInput; output: JobReceipt }
|
||||
| { type: 'media.speech.transcribe'; input: TranscribeAudioInput; output: TranscribeAudioOutput }
|
||||
| { type: 'indexing.verify'; input: IndexVerifyInput; output: IndexVerifyOutput }
|
||||
| { type: 'locations.remove'; input: LocationRemoveInput; output: LocationRemoveOutput }
|
||||
| { type: 'files.delete'; input: FileDeleteInput; output: JobReceipt }
|
||||
| { type: 'media.thumbstrip.generate'; input: GenerateThumbstripInput; output: GenerateThumbstripOutput }
|
||||
| { type: 'spaces.update_group'; input: UpdateGroupInput; output: UpdateGroupOutput }
|
||||
| { type: 'spaces.reorder_items'; input: ReorderItemsInput; output: ReorderOutput }
|
||||
| { type: 'spaces.reorder_groups'; input: ReorderGroupsInput; output: ReorderOutput }
|
||||
;
|
||||
|
||||
export type CoreQuery =
|
||||
{ type: 'libraries.list'; input: ListLibrariesInput; output: [LibraryInfo] }
|
||||
| { type: 'core.status'; input: Empty; output: CoreStatus }
|
||||
| { type: 'network.status'; input: NetworkStatusQueryInput; output: NetworkStatus }
|
||||
{ type: 'network.devices.list'; input: ListPairedDevicesInput; output: ListPairedDevicesOutput }
|
||||
| { type: 'models.whisper.list'; input: ListWhisperModelsInput; output: ListWhisperModelsOutput }
|
||||
| { type: 'network.pair.status'; input: PairStatusQueryInput; output: PairStatusOutput }
|
||||
| { type: 'network.sync_setup.discover'; input: DiscoverRemoteLibrariesInput; output: DiscoverRemoteLibrariesOutput }
|
||||
| { type: 'core.events.list'; input: ListEventsInput; output: ListEventsOutput }
|
||||
| { type: 'network.pair.status'; input: PairStatusQueryInput; output: PairStatusOutput }
|
||||
| { type: 'network.devices.list'; input: ListPairedDevicesInput; output: ListPairedDevicesOutput }
|
||||
| { type: 'libraries.list'; input: ListLibrariesInput; output: [LibraryInfo] }
|
||||
| { type: 'core.status'; input: Empty; output: CoreStatus }
|
||||
| { type: 'network.status'; input: NetworkStatusQueryInput; output: NetworkStatus }
|
||||
;
|
||||
|
||||
export type LibraryQuery =
|
||||
{ type: 'files.by_id'; input: FileByIdQuery; output: File }
|
||||
| { type: 'spaces.get_layout'; input: SpaceLayoutQueryInput; output: SpaceLayout }
|
||||
{ type: 'files.media_listing'; input: MediaListingInput; output: MediaListingOutput }
|
||||
| { type: 'tags.search'; input: SearchTagsInput; output: SearchTagsOutput }
|
||||
| { type: 'locations.list'; input: LocationsListQueryInput; output: LocationsListOutput }
|
||||
| { type: 'test.ping'; input: PingInput; output: PingOutput }
|
||||
| { type: 'spaces.list'; input: SpacesListQueryInput; output: SpacesListOutput }
|
||||
| { type: 'sync.metrics'; input: GetSyncMetricsInput; output: GetSyncMetricsOutput }
|
||||
| { type: 'files.media_listing'; input: MediaListingInput; output: MediaListingOutput }
|
||||
| { type: 'jobs.info'; input: JobInfoQueryInput; output: JobInfoOutput }
|
||||
| { type: 'libraries.info'; input: LibraryInfoQueryInput; output: LibraryInfoOutput }
|
||||
| { type: 'files.unique_to_location'; input: UniqueToLocationInput; output: UniqueToLocationOutput }
|
||||
| { type: 'files.by_path'; input: FileByPathQuery; output: File }
|
||||
| { type: 'locations.suggested'; input: SuggestedLocationsQueryInput; output: SuggestedLocationsOutput }
|
||||
| { type: 'search.files'; input: FileSearchInput; output: FileSearchOutput }
|
||||
| { type: 'jobs.list'; input: JobListInput; output: JobListOutput }
|
||||
| { type: 'devices.list'; input: ListLibraryDevicesInput; output: [LibraryDeviceInfo] }
|
||||
| { type: 'volumes.list'; input: VolumeListQueryInput; output: VolumeListOutput }
|
||||
| { type: 'spaces.get'; input: SpaceGetQueryInput; output: SpaceGetOutput }
|
||||
| { type: 'spaces.list'; input: SpacesListQueryInput; output: SpacesListOutput }
|
||||
| { type: 'libraries.info'; input: LibraryInfoQueryInput; output: LibraryInfoOutput }
|
||||
| { type: 'search.files'; input: FileSearchInput; output: FileSearchOutput }
|
||||
| { type: 'sync.metrics'; input: GetSyncMetricsInput; output: GetSyncMetricsOutput }
|
||||
| { type: 'jobs.info'; input: JobInfoQueryInput; output: JobInfoOutput }
|
||||
| { type: 'files.unique_to_location'; input: UniqueToLocationInput; output: UniqueToLocationOutput }
|
||||
| { type: 'jobs.list'; input: JobListInput; output: JobListOutput }
|
||||
| { type: 'volumes.list'; input: VolumeListQueryInput; output: VolumeListOutput }
|
||||
| { type: 'locations.list'; input: LocationsListQueryInput; output: LocationsListOutput }
|
||||
| { type: 'locations.suggested'; input: SuggestedLocationsQueryInput; output: SuggestedLocationsOutput }
|
||||
| { type: 'files.by_path'; input: FileByPathQuery; output: File }
|
||||
| { type: 'files.directory_listing'; input: DirectoryListingInput; output: DirectoryListingOutput }
|
||||
| { type: 'devices.list'; input: ListLibraryDevicesInput; output: [LibraryDeviceInfo] }
|
||||
| { type: 'files.by_id'; input: FileByIdQuery; output: File }
|
||||
| { type: 'test.ping'; input: PingInput; output: PingOutput }
|
||||
| { type: 'spaces.get_layout'; input: SpaceLayoutQueryInput; output: SpaceLayout }
|
||||
;
|
||||
|
||||
// ===== Wire Method Mappings =====
|
||||
|
||||
export const WIRE_METHODS = {
|
||||
coreActions: {
|
||||
'network.start': 'action:network.start.input',
|
||||
'network.device.revoke': 'action:network.device.revoke.input',
|
||||
'network.pair.cancel': 'action:network.pair.cancel.input',
|
||||
'network.stop': 'action:network.stop.input',
|
||||
'network.sync_setup': 'action:network.sync_setup.input',
|
||||
'network.start': 'action:network.start.input',
|
||||
'network.pair.join': 'action:network.pair.join.input',
|
||||
'network.pair.generate': 'action:network.pair.generate.input',
|
||||
'libraries.open': 'action:libraries.open.input',
|
||||
'network.spacedrop.send': 'action:network.spacedrop.send.input',
|
||||
'libraries.delete': 'action:libraries.delete.input',
|
||||
'libraries.create': 'action:libraries.create.input',
|
||||
'models.whisper.delete': 'action:models.whisper.delete.input',
|
||||
'models.whisper.download': 'action:models.whisper.download.input',
|
||||
'network.sync_setup': 'action:network.sync_setup.input',
|
||||
'network.device.revoke': 'action:network.device.revoke.input',
|
||||
'libraries.delete': 'action:libraries.delete.input',
|
||||
'network.pair.cancel': 'action:network.pair.cancel.input',
|
||||
'network.spacedrop.send': 'action:network.spacedrop.send.input',
|
||||
},
|
||||
|
||||
libraryActions: {
|
||||
'volumes.track': 'action:volumes.track.input',
|
||||
'locations.rescan': 'action:locations.rescan.input',
|
||||
'volumes.untrack': 'action:volumes.untrack.input',
|
||||
'volumes.remove_cloud': 'action:volumes.remove_cloud.input',
|
||||
'media.ocr.extract': 'action:media.ocr.extract.input',
|
||||
'spaces.delete_item': 'action:spaces.delete_item.input',
|
||||
'libraries.rename': 'action:libraries.rename.input',
|
||||
'indexing.start': 'action:indexing.start.input',
|
||||
'volumes.speed_test': 'action:volumes.speed_test.input',
|
||||
'spaces.delete': 'action:spaces.delete.input',
|
||||
'media.proxy.generate': 'action:media.proxy.generate.input',
|
||||
'volumes.add_cloud': 'action:volumes.add_cloud.input',
|
||||
'indexing.verify': 'action:indexing.verify.input',
|
||||
'jobs.resume': 'action:jobs.resume.input',
|
||||
'files.copy': 'action:files.copy.input',
|
||||
'spaces.delete_group': 'action:spaces.delete_group.input',
|
||||
'spaces.update_group': 'action:spaces.update_group.input',
|
||||
'media.speech.transcribe': 'action:media.speech.transcribe.input',
|
||||
'locations.remove': 'action:locations.remove.input',
|
||||
'spaces.reorder_items': 'action:spaces.reorder_items.input',
|
||||
'spaces.reorder_groups': 'action:spaces.reorder_groups.input',
|
||||
'tags.apply': 'action:tags.apply.input',
|
||||
'volumes.refresh': 'action:volumes.refresh.input',
|
||||
'media.thumbnail.regenerate': 'action:media.thumbnail.regenerate.input',
|
||||
'media.thumbnail': 'action:media.thumbnail.input',
|
||||
'media.thumbstrip.generate': 'action:media.thumbstrip.generate.input',
|
||||
'spaces.add_item': 'action:spaces.add_item.input',
|
||||
'jobs.pause': 'action:jobs.pause.input',
|
||||
'locations.update': 'action:locations.update.input',
|
||||
'locations.add': 'action:locations.add.input',
|
||||
'jobs.cancel': 'action:jobs.cancel.input',
|
||||
'spaces.add_group': 'action:spaces.add_group.input',
|
||||
'spaces.update': 'action:spaces.update.input',
|
||||
'files.delete': 'action:files.delete.input',
|
||||
'tags.create': 'action:tags.create.input',
|
||||
'libraries.rename': 'action:libraries.rename.input',
|
||||
'spaces.delete_group': 'action:spaces.delete_group.input',
|
||||
'tags.apply': 'action:tags.apply.input',
|
||||
'locations.rescan': 'action:locations.rescan.input',
|
||||
'volumes.add_cloud': 'action:volumes.add_cloud.input',
|
||||
'libraries.export': 'action:libraries.export.input',
|
||||
'volumes.speed_test': 'action:volumes.speed_test.input',
|
||||
'spaces.create': 'action:spaces.create.input',
|
||||
'spaces.delete': 'action:spaces.delete.input',
|
||||
'locations.add': 'action:locations.add.input',
|
||||
'indexing.start': 'action:indexing.start.input',
|
||||
'spaces.add_group': 'action:spaces.add_group.input',
|
||||
'tags.create': 'action:tags.create.input',
|
||||
'spaces.delete_item': 'action:spaces.delete_item.input',
|
||||
'jobs.cancel': 'action:jobs.cancel.input',
|
||||
'volumes.track': 'action:volumes.track.input',
|
||||
'spaces.add_item': 'action:spaces.add_item.input',
|
||||
'spaces.update': 'action:spaces.update.input',
|
||||
'jobs.pause': 'action:jobs.pause.input',
|
||||
'media.proxy.generate': 'action:media.proxy.generate.input',
|
||||
'volumes.remove_cloud': 'action:volumes.remove_cloud.input',
|
||||
'media.ocr.extract': 'action:media.ocr.extract.input',
|
||||
'volumes.refresh': 'action:volumes.refresh.input',
|
||||
'volumes.untrack': 'action:volumes.untrack.input',
|
||||
'locations.update': 'action:locations.update.input',
|
||||
'locations.triggerJob': 'action:locations.triggerJob.input',
|
||||
'files.copy': 'action:files.copy.input',
|
||||
'media.speech.transcribe': 'action:media.speech.transcribe.input',
|
||||
'indexing.verify': 'action:indexing.verify.input',
|
||||
'locations.remove': 'action:locations.remove.input',
|
||||
'files.delete': 'action:files.delete.input',
|
||||
'media.thumbstrip.generate': 'action:media.thumbstrip.generate.input',
|
||||
'spaces.update_group': 'action:spaces.update_group.input',
|
||||
'spaces.reorder_items': 'action:spaces.reorder_items.input',
|
||||
'spaces.reorder_groups': 'action:spaces.reorder_groups.input',
|
||||
},
|
||||
|
||||
coreQueries: {
|
||||
'network.devices.list': 'query:network.devices.list',
|
||||
'models.whisper.list': 'query:models.whisper.list',
|
||||
'network.pair.status': 'query:network.pair.status',
|
||||
'network.sync_setup.discover': 'query:network.sync_setup.discover',
|
||||
'core.events.list': 'query:core.events.list',
|
||||
'libraries.list': 'query:libraries.list',
|
||||
'core.status': 'query:core.status',
|
||||
'network.status': 'query:network.status',
|
||||
'models.whisper.list': 'query:models.whisper.list',
|
||||
'network.sync_setup.discover': 'query:network.sync_setup.discover',
|
||||
'core.events.list': 'query:core.events.list',
|
||||
'network.pair.status': 'query:network.pair.status',
|
||||
'network.devices.list': 'query:network.devices.list',
|
||||
},
|
||||
|
||||
libraryQueries: {
|
||||
'files.by_id': 'query:files.by_id',
|
||||
'spaces.get_layout': 'query:spaces.get_layout',
|
||||
'tags.search': 'query:tags.search',
|
||||
'locations.list': 'query:locations.list',
|
||||
'test.ping': 'query:test.ping',
|
||||
'spaces.list': 'query:spaces.list',
|
||||
'sync.metrics': 'query:sync.metrics',
|
||||
'files.media_listing': 'query:files.media_listing',
|
||||
'jobs.info': 'query:jobs.info',
|
||||
'libraries.info': 'query:libraries.info',
|
||||
'files.unique_to_location': 'query:files.unique_to_location',
|
||||
'files.by_path': 'query:files.by_path',
|
||||
'locations.suggested': 'query:locations.suggested',
|
||||
'search.files': 'query:search.files',
|
||||
'jobs.list': 'query:jobs.list',
|
||||
'devices.list': 'query:devices.list',
|
||||
'volumes.list': 'query:volumes.list',
|
||||
'tags.search': 'query:tags.search',
|
||||
'spaces.get': 'query:spaces.get',
|
||||
'spaces.list': 'query:spaces.list',
|
||||
'libraries.info': 'query:libraries.info',
|
||||
'search.files': 'query:search.files',
|
||||
'sync.metrics': 'query:sync.metrics',
|
||||
'jobs.info': 'query:jobs.info',
|
||||
'files.unique_to_location': 'query:files.unique_to_location',
|
||||
'jobs.list': 'query:jobs.list',
|
||||
'volumes.list': 'query:volumes.list',
|
||||
'locations.list': 'query:locations.list',
|
||||
'locations.suggested': 'query:locations.suggested',
|
||||
'files.by_path': 'query:files.by_path',
|
||||
'files.directory_listing': 'query:files.directory_listing',
|
||||
'devices.list': 'query:devices.list',
|
||||
'files.by_id': 'query:files.by_id',
|
||||
'test.ping': 'query:test.ping',
|
||||
'spaces.get_layout': 'query:spaces.get_layout',
|
||||
},
|
||||
} as const;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import { useMutation, type UseMutationOptions, type UseMutationResult } from "@tanstack/react-query";
|
||||
import { useSpacedriveClient } from "./useClient";
|
||||
import type { CoreAction, LibraryAction } from "../generated/types";
|
||||
|
||||
@@ -205,6 +205,11 @@ export function handleResourceEvent(
|
||||
queryKey: any[],
|
||||
queryClient: QueryClient,
|
||||
) {
|
||||
// Skip string events (like "CoreStarted", "CoreShutdown")
|
||||
if (typeof event === "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Refresh event - invalidate all queries
|
||||
if ("Refresh" in event) {
|
||||
queryClient.invalidateQueries();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import { useQuery, type UseQueryOptions, type UseQueryResult } from "@tanstack/react-query";
|
||||
import { useSpacedriveClient } from "./useClient";
|
||||
import type { CoreQuery, LibraryQuery } from "../generated/types";
|
||||
|
||||
@@ -20,6 +20,7 @@ interface EventFilter {
|
||||
resource_type?: string;
|
||||
path_scope?: any;
|
||||
include_descendants?: boolean;
|
||||
event_types?: string[];
|
||||
}
|
||||
|
||||
interface SubscriptionEntry {
|
||||
|
||||
@@ -19,5 +19,5 @@
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx", "**/__tests__/**"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user