[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:
Brendan Allan
2023-08-25 05:04:50 +08:00
committed by GitHub
parent 7a7d01307e
commit f387f2f076
4 changed files with 77 additions and 43 deletions

View File

@@ -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")]

View File

@@ -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')
]);

View File

@@ -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,

View File

@@ -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.
*/