mirror of
https://github.com/colanode/colanode.git
synced 2025-12-16 11:47:47 +01:00
Use tanstackdb for file nodes
This commit is contained in:
@@ -1,105 +0,0 @@
|
|||||||
import { WorkspaceQueryHandlerBase } from '@colanode/client/handlers/queries/workspace-query-handler-base';
|
|
||||||
import { mapNode } from '@colanode/client/lib/mappers';
|
|
||||||
import { ChangeCheckResult, QueryHandler } from '@colanode/client/lib/types';
|
|
||||||
import { FileListQueryInput } from '@colanode/client/queries/files/file-list';
|
|
||||||
import { Event } from '@colanode/client/types/events';
|
|
||||||
import { LocalFileNode } from '@colanode/client/types/nodes';
|
|
||||||
|
|
||||||
export class FileListQueryHandler
|
|
||||||
extends WorkspaceQueryHandlerBase
|
|
||||||
implements QueryHandler<FileListQueryInput>
|
|
||||||
{
|
|
||||||
public async handleQuery(
|
|
||||||
input: FileListQueryInput
|
|
||||||
): Promise<LocalFileNode[]> {
|
|
||||||
return await this.fetchFiles(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async checkForChanges(
|
|
||||||
event: Event,
|
|
||||||
input: FileListQueryInput,
|
|
||||||
output: LocalFileNode[]
|
|
||||||
): Promise<ChangeCheckResult<FileListQueryInput>> {
|
|
||||||
if (
|
|
||||||
event.type === 'workspace.deleted' &&
|
|
||||||
event.workspace.userId === input.userId
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
hasChanges: true,
|
|
||||||
result: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
event.type === 'node.created' &&
|
|
||||||
event.workspace.userId === input.userId &&
|
|
||||||
event.node.parentId === input.parentId
|
|
||||||
) {
|
|
||||||
const output = await this.handleQuery(input);
|
|
||||||
return {
|
|
||||||
hasChanges: true,
|
|
||||||
result: output,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
event.type === 'node.updated' &&
|
|
||||||
event.workspace.userId === input.userId &&
|
|
||||||
event.node.parentId === input.parentId
|
|
||||||
) {
|
|
||||||
const file = output.find((file) => file.id === event.node.id);
|
|
||||||
if (file) {
|
|
||||||
const newResult = output.map((file) => {
|
|
||||||
if (file.id === event.node.id && event.node.type === 'file') {
|
|
||||||
return event.node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return file;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
hasChanges: true,
|
|
||||||
result: newResult,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
event.type === 'node.deleted' &&
|
|
||||||
event.workspace.userId === input.userId &&
|
|
||||||
event.node.parentId === input.parentId
|
|
||||||
) {
|
|
||||||
const file = output.find((file) => file.id === event.node.id);
|
|
||||||
if (file) {
|
|
||||||
const output = await this.handleQuery(input);
|
|
||||||
return {
|
|
||||||
hasChanges: true,
|
|
||||||
result: output,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
hasChanges: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private async fetchFiles(
|
|
||||||
input: FileListQueryInput
|
|
||||||
): Promise<LocalFileNode[]> {
|
|
||||||
const workspace = this.getWorkspace(input.userId);
|
|
||||||
|
|
||||||
const offset = (input.page - 1) * input.count;
|
|
||||||
const files = await workspace.database
|
|
||||||
.selectFrom('nodes')
|
|
||||||
.selectAll()
|
|
||||||
.where('type', '=', 'file')
|
|
||||||
.where('parent_id', '=', input.parentId)
|
|
||||||
.orderBy('id', 'asc')
|
|
||||||
.limit(input.count)
|
|
||||||
.offset(offset)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
return files.map(mapNode) as LocalFileNode[];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,6 @@ import { EmojiSearchQueryHandler } from './emojis/emoji-search';
|
|||||||
import { EmojiSvgGetQueryHandler } from './emojis/emoji-svg-get';
|
import { EmojiSvgGetQueryHandler } from './emojis/emoji-svg-get';
|
||||||
import { DownloadListQueryHandler } from './files/download-list';
|
import { DownloadListQueryHandler } from './files/download-list';
|
||||||
import { FileDownloadRequestGetQueryHandler } from './files/file-download-request-get';
|
import { FileDownloadRequestGetQueryHandler } from './files/file-download-request-get';
|
||||||
import { FileListQueryHandler } from './files/file-list';
|
|
||||||
import { LocalFileGetQueryHandler } from './files/local-file-get';
|
import { LocalFileGetQueryHandler } from './files/local-file-get';
|
||||||
import { TempFileListQueryHandler } from './files/temp-file-list';
|
import { TempFileListQueryHandler } from './files/temp-file-list';
|
||||||
import { UploadListQueryHandler } from './files/upload-list';
|
import { UploadListQueryHandler } from './files/upload-list';
|
||||||
@@ -63,7 +62,6 @@ export const buildQueryHandlerMap = (app: AppService): QueryHandlerMap => {
|
|||||||
'user.search': new UserSearchQueryHandler(app),
|
'user.search': new UserSearchQueryHandler(app),
|
||||||
'workspace.list': new WorkspaceListQueryHandler(app),
|
'workspace.list': new WorkspaceListQueryHandler(app),
|
||||||
'user.list': new UserListQueryHandler(app),
|
'user.list': new UserListQueryHandler(app),
|
||||||
'file.list': new FileListQueryHandler(app),
|
|
||||||
'emoji.list': new EmojiListQueryHandler(app),
|
'emoji.list': new EmojiListQueryHandler(app),
|
||||||
'emoji.get': new EmojiGetQueryHandler(app),
|
'emoji.get': new EmojiGetQueryHandler(app),
|
||||||
'emoji.get.by.skin.id': new EmojiGetBySkinIdQueryHandler(app),
|
'emoji.get.by.skin.id': new EmojiGetBySkinIdQueryHandler(app),
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import { LocalFileNode } from '@colanode/client/types/nodes';
|
|
||||||
|
|
||||||
export type FileListQueryInput = {
|
|
||||||
type: 'file.list';
|
|
||||||
parentId: string;
|
|
||||||
page: number;
|
|
||||||
count: number;
|
|
||||||
userId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
declare module '@colanode/client/queries' {
|
|
||||||
interface QueryMap {
|
|
||||||
'file.list': {
|
|
||||||
input: FileListQueryInput;
|
|
||||||
output: LocalFileNode[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,6 @@ export * from './emojis/emoji-get-by-skin-id';
|
|||||||
export * from './emojis/emoji-get';
|
export * from './emojis/emoji-get';
|
||||||
export * from './emojis/emoji-list';
|
export * from './emojis/emoji-list';
|
||||||
export * from './emojis/emoji-search';
|
export * from './emojis/emoji-search';
|
||||||
export * from './files/file-list';
|
|
||||||
export * from './files/local-file-get';
|
export * from './files/local-file-get';
|
||||||
export * from './files/file-download-request-get';
|
export * from './files/file-download-request-get';
|
||||||
export * from './icons/icon-category-list';
|
export * from './icons/icon-category-list';
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
|
import { eq, useLiveQuery } from '@tanstack/react-db';
|
||||||
import { useNavigate } from '@tanstack/react-router';
|
import { useNavigate } from '@tanstack/react-router';
|
||||||
import { useState } from 'react';
|
|
||||||
import { match } from 'ts-pattern';
|
import { match } from 'ts-pattern';
|
||||||
|
|
||||||
import { FileListQueryInput } from '@colanode/client/queries';
|
import { FolderLayoutType, LocalFileNode } from '@colanode/client/types';
|
||||||
import { FolderLayoutType } from '@colanode/client/types';
|
|
||||||
import { GalleryLayout } from '@colanode/ui/components/folders/galleries/gallery-layout';
|
import { GalleryLayout } from '@colanode/ui/components/folders/galleries/gallery-layout';
|
||||||
import { GridLayout } from '@colanode/ui/components/folders/grids/grid-layout';
|
import { GridLayout } from '@colanode/ui/components/folders/grids/grid-layout';
|
||||||
import { ListLayout } from '@colanode/ui/components/folders/lists/list-layout';
|
import { ListLayout } from '@colanode/ui/components/folders/lists/list-layout';
|
||||||
import { FolderContext } from '@colanode/ui/contexts/folder';
|
import { FolderContext } from '@colanode/ui/contexts/folder';
|
||||||
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
import { useWorkspace } from '@colanode/ui/contexts/workspace';
|
||||||
import { useLiveQueries } from '@colanode/ui/hooks/use-live-queries';
|
import { database } from '@colanode/ui/data';
|
||||||
|
|
||||||
const FILES_PER_PAGE = 100;
|
|
||||||
|
|
||||||
interface FolderFilesProps {
|
interface FolderFilesProps {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -27,19 +24,15 @@ export const FolderFiles = ({
|
|||||||
const workspace = useWorkspace();
|
const workspace = useWorkspace();
|
||||||
const navigate = useNavigate({ from: '/workspace/$userId' });
|
const navigate = useNavigate({ from: '/workspace/$userId' });
|
||||||
|
|
||||||
const [lastPage] = useState<number>(1);
|
const viewListQuery = useLiveQuery((q) =>
|
||||||
const inputs: FileListQueryInput[] = Array.from({
|
q
|
||||||
length: lastPage,
|
.from({ nodes: database.workspace(workspace.userId).nodes })
|
||||||
}).map((_, i) => ({
|
.where(({ nodes }) => eq(nodes.type, 'file'))
|
||||||
type: 'file.list',
|
.where(({ nodes }) => eq(nodes.parentId, id))
|
||||||
userId: workspace.userId,
|
.orderBy(({ nodes }) => nodes.id, 'asc')
|
||||||
parentId: id,
|
);
|
||||||
count: FILES_PER_PAGE,
|
|
||||||
page: i + 1,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const result = useLiveQueries(inputs);
|
const files = viewListQuery.data.map((node) => node as LocalFileNode) ?? [];
|
||||||
const files = result.flatMap((data) => data.data ?? []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FolderContext.Provider
|
<FolderContext.Provider
|
||||||
|
|||||||
Reference in New Issue
Block a user