mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-19 05:45:01 -04:00
[ENG-992] Add search.pathsCount route (#1244)
search.pathsCount route Co-authored-by: Vítor Vasconcellos <vasconcellos.dev@gmail.com>
This commit is contained in:
@@ -19,7 +19,6 @@ use prisma_client_rust::{operator, or};
|
||||
use rspc::{alpha::AlphaRouter, ErrorCode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use tracing::trace;
|
||||
|
||||
use super::{Ctx, R};
|
||||
|
||||
@@ -275,14 +274,23 @@ impl ObjectFilterArgs {
|
||||
|
||||
pub fn mount() -> AlphaRouter<Ctx> {
|
||||
R.router()
|
||||
.procedure("ephemeral-paths", {
|
||||
.procedure("ephemeralPaths", {
|
||||
#[derive(Serialize, Deserialize, Type, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase", tag = "field", content = "value")]
|
||||
enum NonIndexedPathOrdering {
|
||||
Name(SortOrder),
|
||||
SizeInBytes(SortOrder),
|
||||
DateCreated(SortOrder),
|
||||
DateModified(SortOrder),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Type, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct NonIndexedPath {
|
||||
path: PathBuf,
|
||||
with_hidden_files: bool,
|
||||
#[specta(optional)]
|
||||
order: Option<FilePathSearchOrdering>,
|
||||
order: Option<NonIndexedPathOrdering>,
|
||||
}
|
||||
|
||||
R.with2(library()).query(
|
||||
@@ -297,54 +305,50 @@ pub fn mount() -> AlphaRouter<Ctx> {
|
||||
|
||||
if let Some(order) = order {
|
||||
match order {
|
||||
FilePathSearchOrdering::Name(order) => {
|
||||
NonIndexedPathOrdering::Name(order) => {
|
||||
paths.entries.sort_unstable_by(|path1, path2| {
|
||||
if let SortOrder::Desc = order {
|
||||
path2
|
||||
.name()
|
||||
.to_lowercase()
|
||||
.cmp(&path1.name().to_lowercase())
|
||||
} else {
|
||||
path1
|
||||
.name()
|
||||
.to_lowercase()
|
||||
.cmp(&path2.name().to_lowercase())
|
||||
let one = path1.name().to_lowercase();
|
||||
let two = path2.name().to_lowercase();
|
||||
|
||||
match order {
|
||||
SortOrder::Desc => two.cmp(&one),
|
||||
SortOrder::Asc => one.cmp(&two),
|
||||
}
|
||||
});
|
||||
}
|
||||
FilePathSearchOrdering::SizeInBytes(order) => {
|
||||
NonIndexedPathOrdering::SizeInBytes(order) => {
|
||||
paths.entries.sort_unstable_by(|path1, path2| {
|
||||
if let SortOrder::Desc = order {
|
||||
path2.size_in_bytes().cmp(&path1.size_in_bytes())
|
||||
} else {
|
||||
path1.size_in_bytes().cmp(&path2.size_in_bytes())
|
||||
let one = path1.size_in_bytes();
|
||||
let two = path2.size_in_bytes();
|
||||
|
||||
match order {
|
||||
SortOrder::Desc => two.cmp(&one),
|
||||
SortOrder::Asc => one.cmp(&two),
|
||||
}
|
||||
});
|
||||
}
|
||||
FilePathSearchOrdering::DateCreated(order) => {
|
||||
NonIndexedPathOrdering::DateCreated(order) => {
|
||||
paths.entries.sort_unstable_by(|path1, path2| {
|
||||
if let SortOrder::Desc = order {
|
||||
path2.date_created().cmp(&path1.date_created())
|
||||
} else {
|
||||
path1.date_created().cmp(&path2.date_created())
|
||||
let one = path1.date_created();
|
||||
let two = path2.date_created();
|
||||
|
||||
match order {
|
||||
SortOrder::Desc => two.cmp(&one),
|
||||
SortOrder::Asc => one.cmp(&two),
|
||||
}
|
||||
});
|
||||
}
|
||||
FilePathSearchOrdering::DateModified(order) => {
|
||||
NonIndexedPathOrdering::DateModified(order) => {
|
||||
paths.entries.sort_unstable_by(|path1, path2| {
|
||||
if let SortOrder::Desc = order {
|
||||
path2.date_modified().cmp(&path1.date_modified())
|
||||
} else {
|
||||
path1.date_modified().cmp(&path2.date_modified())
|
||||
let one = path1.date_modified();
|
||||
let two = path2.date_modified();
|
||||
|
||||
match order {
|
||||
SortOrder::Desc => two.cmp(&one),
|
||||
SortOrder::Asc => one.cmp(&two),
|
||||
}
|
||||
});
|
||||
}
|
||||
FilePathSearchOrdering::DateIndexed(_) => {
|
||||
trace!("Can't order by indexed date on ephemeral paths route, ignoring...")
|
||||
}
|
||||
FilePathSearchOrdering::Object(_) => {
|
||||
trace!("Receive an Object sort ordeding at ephemeral paths route, ignoring...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,6 +445,26 @@ pub fn mount() -> AlphaRouter<Ctx> {
|
||||
},
|
||||
)
|
||||
})
|
||||
.procedure("pathsCount", {
|
||||
#[derive(Deserialize, Type, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[specta(inline)]
|
||||
struct Args {
|
||||
#[serde(default)]
|
||||
filter: FilePathFilterArgs,
|
||||
}
|
||||
|
||||
R.with2(library())
|
||||
.query(|(_, library), Args { filter }| async move {
|
||||
let Library { db, .. } = library.as_ref();
|
||||
|
||||
Ok(db
|
||||
.file_path()
|
||||
.count(filter.into_params(db).await?)
|
||||
.exec()
|
||||
.await? as u32)
|
||||
})
|
||||
})
|
||||
.procedure("objects", {
|
||||
#[derive(Deserialize, Type, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
||||
@@ -159,3 +159,10 @@ export const objectOrderingKeysSchema = z.union([
|
||||
z.literal('dateAccessed').describe('Date Accessed'),
|
||||
z.literal('kind').describe('Kind')
|
||||
]);
|
||||
|
||||
export const nonIndexedPathOrderingSchema = z.union([
|
||||
z.literal('name').describe('Name'),
|
||||
z.literal('sizeInBytes').describe('Size'),
|
||||
z.literal('dateCreated').describe('Date Created'),
|
||||
z.literal('dateModified').describe('Date Modified')
|
||||
]);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Suspense, memo, useDeferredValue, useMemo } from 'react';
|
||||
import { type FilePathSearchOrdering, getExplorerItemData, useLibraryQuery } from '@sd/client';
|
||||
import { type NonIndexedPathOrdering, getExplorerItemData, useLibraryQuery } from '@sd/client';
|
||||
import { Tooltip } from '@sd/ui';
|
||||
import { type PathParams, PathParamsSchema } from '~/app/route-schemas';
|
||||
import { useOperatingSystem, useZodSearchParams } from '~/hooks';
|
||||
@@ -8,8 +8,8 @@ import { ExplorerContextProvider } from './Explorer/Context';
|
||||
import { DefaultTopBarOptions } from './Explorer/TopBarOptions';
|
||||
import {
|
||||
createDefaultExplorerSettings,
|
||||
filePathOrderingKeysSchema,
|
||||
getExplorerStore
|
||||
getExplorerStore,
|
||||
nonIndexedPathOrderingSchema
|
||||
} from './Explorer/store';
|
||||
import { useExplorer, useExplorerSettings } from './Explorer/useExplorer';
|
||||
import { TopBarPortal } from './TopBar/Portal';
|
||||
@@ -22,7 +22,7 @@ const EphemeralExplorer = memo((props: { args: PathParams }) => {
|
||||
const explorerSettings = useExplorerSettings({
|
||||
settings: useMemo(
|
||||
() =>
|
||||
createDefaultExplorerSettings<FilePathSearchOrdering>({
|
||||
createDefaultExplorerSettings<NonIndexedPathOrdering>({
|
||||
order: {
|
||||
field: 'name',
|
||||
value: 'Asc'
|
||||
@@ -30,14 +30,14 @@ const EphemeralExplorer = memo((props: { args: PathParams }) => {
|
||||
}),
|
||||
[]
|
||||
),
|
||||
orderingKeys: filePathOrderingKeysSchema
|
||||
orderingKeys: nonIndexedPathOrderingSchema
|
||||
});
|
||||
|
||||
const settingsSnapshot = explorerSettings.useSettingsSnapshot();
|
||||
|
||||
const query = useLibraryQuery(
|
||||
[
|
||||
'search.ephemeral-paths',
|
||||
'search.ephemeralPaths',
|
||||
{
|
||||
path: path ?? (os === 'windows' ? 'C:\\' : '/'),
|
||||
withHiddenFiles: true,
|
||||
|
||||
@@ -25,9 +25,10 @@ export type Procedures = {
|
||||
{ key: "notifications.dismissAll", input: never, result: null } |
|
||||
{ key: "notifications.get", input: never, result: Notification[] } |
|
||||
{ key: "preferences.get", input: LibraryArgs<null>, result: LibraryPreferences } |
|
||||
{ key: "search.ephemeral-paths", input: LibraryArgs<NonIndexedPath>, result: NonIndexedFileSystemEntries } |
|
||||
{ key: "search.ephemeralPaths", input: LibraryArgs<NonIndexedPath>, result: NonIndexedFileSystemEntries } |
|
||||
{ key: "search.objects", input: LibraryArgs<ObjectSearchArgs>, result: SearchData<ExplorerItem> } |
|
||||
{ key: "search.paths", input: LibraryArgs<FilePathSearchArgs>, result: SearchData<ExplorerItem> } |
|
||||
{ key: "search.pathsCount", input: LibraryArgs<{ filter?: FilePathFilterArgs }>, result: number } |
|
||||
{ key: "sync.messages", input: LibraryArgs<null>, result: CRDTOperation[] } |
|
||||
{ key: "tags.get", input: LibraryArgs<number>, result: Tag | null } |
|
||||
{ key: "tags.getForObject", input: LibraryArgs<number>, result: Tag[] } |
|
||||
@@ -236,10 +237,12 @@ export type NodeState = ({ id: string; name: string; p2p_port: number | null; p2
|
||||
|
||||
export type NonIndexedFileSystemEntries = { entries: ExplorerItem[]; errors: Error[] }
|
||||
|
||||
export type NonIndexedPath = { path: string; withHiddenFiles: boolean; order?: FilePathSearchOrdering | null }
|
||||
export type NonIndexedPath = { path: string; withHiddenFiles: boolean; order?: NonIndexedPathOrdering | null }
|
||||
|
||||
export type NonIndexedPathItem = { path: string; name: string; extension: string; kind: number; is_dir: boolean; date_created: string; date_modified: string; size_in_bytes_bytes: number[] }
|
||||
|
||||
export type NonIndexedPathOrdering = { field: "name"; value: SortOrder } | { field: "sizeInBytes"; value: SortOrder } | { field: "dateCreated"; value: SortOrder } | { field: "dateModified"; value: SortOrder }
|
||||
|
||||
/**
|
||||
* Represents a single notification.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user