diff --git a/apps/mobile/src/types/bindings.ts b/apps/mobile/src/types/bindings.ts index 65d2b34a4..c5d75d903 100644 --- a/apps/mobile/src/types/bindings.ts +++ b/apps/mobile/src/types/bindings.ts @@ -2,136 +2,136 @@ export type Operations = { queries: - { key: ["library.getStatistics", LibraryArgs], result: Statistics } | - { key: ["volumes.get"], result: Array } | + { key: ["tags.get", LibraryArgs], result: Tag | null } | { key: ["tags.getForFile", LibraryArgs], result: Array } | - { key: ["tags.getExplorerData", LibraryArgs], result: ExplorerData } | + { key: ["locations.getById", LibraryArgs], result: Location | null } | { key: ["locations.indexer_rulesget", LibraryArgs], result: IndexerRule } | { key: ["files.readMetadata", LibraryArgs], result: null } | - { key: ["jobs.getHistory", LibraryArgs], result: Array } | - { key: ["locations.getById", LibraryArgs], result: Location | null } | - { key: ["locations.getExplorerData", LibraryArgs], result: ExplorerData } | - { key: ["getNode"], result: NodeState } | - { key: ["locations.get", LibraryArgs], result: Array } | - { key: ["tags.get", LibraryArgs], result: Tag | null } | - { key: ["locations.indexer_ruleslist", LibraryArgs], result: Array } | - { key: ["library.get"], result: Array } | { key: ["tags.getAll", LibraryArgs], result: Array } | + { key: ["jobs.getHistory", LibraryArgs], result: Array } | + { key: ["getNode"], result: NodeState } | + { key: ["library.getStatistics", LibraryArgs], result: Statistics } | + { key: ["version"], result: string } | { key: ["jobs.getRunning", LibraryArgs], result: Array } | - { key: ["version"], result: string }, + { key: ["library.get"], result: Array } | + { key: ["locations.get", LibraryArgs], result: Array } | + { key: ["volumes.get"], result: Array } | + { key: ["locations.indexer_ruleslist", LibraryArgs], result: Array } | + { key: ["locations.getExplorerData", LibraryArgs], result: ExplorerData } | + { key: ["tags.getExplorerData", LibraryArgs], result: ExplorerData }, mutations: - { key: ["locations.create", LibraryArgs], result: Location } | - { key: ["locations.fullRescan", LibraryArgs], result: null } | - { key: ["locations.quickRescan", LibraryArgs], result: null } | - { key: ["files.setFavorite", LibraryArgs], result: null } | - { key: ["jobs.generateThumbsForLocation", LibraryArgs], result: null } | - { key: ["locations.update", LibraryArgs], result: null } | - { key: ["tags.update", LibraryArgs], result: null } | - { key: ["library.create", string], result: null } | - { key: ["files.delete", LibraryArgs], result: null } | - { key: ["tags.create", LibraryArgs], result: Tag } | - { key: ["tags.delete", LibraryArgs], result: null } | - { key: ["tags.assign", LibraryArgs], result: null } | - { key: ["library.edit", EditLibraryArgs], result: null } | - { key: ["locations.indexer_rulescreate", LibraryArgs], result: IndexerRule } | - { key: ["files.setNote", LibraryArgs], result: null } | - { key: ["jobs.identifyUniqueFiles", LibraryArgs], result: null } | - { key: ["library.delete", string], result: null } | { key: ["locations.indexer_rulesdelete", LibraryArgs], result: null } | + { key: ["library.create", string], result: null } | + { key: ["locations.quickRescan", LibraryArgs], result: null } | + { key: ["locations.update", LibraryArgs], result: null } | + { key: ["tags.assign", LibraryArgs], result: null } | + { key: ["locations.fullRescan", LibraryArgs], result: null } | + { key: ["files.delete", LibraryArgs], result: null } | + { key: ["files.setFavorite", LibraryArgs], result: null } | + { key: ["files.setNote", LibraryArgs], result: null } | + { key: ["tags.delete", LibraryArgs], result: null } | + { key: ["tags.update", LibraryArgs], result: null } | + { key: ["locations.indexer_rulescreate", LibraryArgs], result: IndexerRule } | + { key: ["locations.create", LibraryArgs], result: Location } | + { key: ["jobs.generateThumbsForLocation", LibraryArgs], result: null } | + { key: ["library.edit", EditLibraryArgs], result: null } | + { key: ["library.delete", string], result: null } | + { key: ["jobs.identifyUniqueFiles", LibraryArgs], result: null } | + { key: ["tags.create", LibraryArgs], result: Tag } | { key: ["locations.delete", LibraryArgs], result: null }, subscriptions: { key: ["invalidateQuery"], result: InvalidateOperationEvent } | { key: ["jobs.newThumbnail", LibraryArgs], result: string } }; -export interface InvalidateOperationEvent { key: string, arg: any } - -export interface LocationExplorerArgs { location_id: number, path: string, limit: number, cursor: string | null } - -export interface LibraryConfig { version: string | null, name: string, description: string } - -export interface FileInSpace { date_created: string, space_id: number, space: Space | null, file_id: number, file: File | null } - -export interface LabelOnFile { date_created: string, label_id: number, label: Label | null, file_id: number, file: File | null } - -export interface JobReport { id: string, name: string, data: Array | null, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: number } - -export type ExplorerItem = { type: "Path" } & FilePath | { type: "Object" } & File - -export interface NodeConfig { version: string | null, id: string, name: string, p2p_port: number | null } - -export interface LibraryConfigWrapped { uuid: string, config: LibraryConfig } - -export interface ConfigMetadata { version: string | null } - -export interface MediaData { id: number, pixel_width: number | null, pixel_height: number | null, longitude: number | null, latitude: number | null, fps: number | null, capture_device_make: string | null, capture_device_model: string | null, capture_device_software: string | null, duration_seconds: number | null, codecs: string | null, streams: number | null, files: File | null | null } - -export interface Space { id: number, pub_id: Array, name: string | null, description: string | null, date_created: string, date_modified: string, files: Array | null } - -export interface Label { id: number, pub_id: Array, name: string | null, date_created: string, date_modified: string, label_files: Array | null } - -export interface Volume { name: string, mount_point: string, total_capacity: bigint, available_capacity: bigint, is_removable: boolean, disk_type: string | null, file_system: string | null, is_root_filesystem: boolean } - -export interface ExplorerData { context: ExplorerContext, items: Array } - -export interface LibraryArgs { library_id: string, arg: T } - -export interface TagUpdateArgs { id: number, name: string | null, color: string | null } - -export interface LocationCreateArgs { path: string, indexer_rules_ids: Array } - -export interface FileInAlbum { date_created: string, album_id: number, album: Album | null, file_id: number, file: File | null } - -export interface TagOnFile { date_created: string, tag_id: number, tag: Tag | null, file_id: number, file: File | null } - -export interface Tag { id: number, pub_id: Array, name: string | null, color: string | null, total_files: number | null, redundancy_goal: number | null, date_created: string, date_modified: string, tag_files: Array | null } - -export interface IndexerRule { id: number, kind: number, name: string, parameters: Array, date_created: string, date_modified: string, locations: Array | null } - -export interface Location { id: number, pub_id: Array, node_id: number | null, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string, node: Node | null | null, file_paths: Array | null, indexer_rules: Array | null } - -export interface TagCreateArgs { name: string, color: string } - -export interface Statistics { id: number, date_captured: string, total_file_count: number, library_db_size: string, total_bytes_used: string, total_bytes_capacity: string, total_unique_bytes: string, total_bytes_free: string, preview_media_bytes: string } - -export interface Comment { id: number, pub_id: Array, content: string, date_created: string, date_modified: string, file_id: number | null, file: File | null | null } - export interface Node { id: number, pub_id: Array, name: string, platform: number, version: string | null, last_seen: string, timezone: string | null, date_created: string, sync_events: Array | null, jobs: Array | null, Location: Array | null } -export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, file_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string, file: File | null | null, location: Location | null | null, key: Key | null | null } - -export interface LocationUpdateArgs { id: number, name: string | null, indexer_rules_ids: Array } - -export interface IndexerRuleCreateArgs { kind: RuleKind, name: string, parameters: Array } - export interface Job { id: Array, name: string, node_id: number, action: number, status: number, data: Array | null, task_count: number, completed_task_count: number, date_created: string, date_modified: string, seconds_elapsed: number, nodes: Node | null } +export interface IndexerRuleCreateArgs { kind: RuleKind, name: string, parameters: Array } + +export interface LibraryConfig { version: string | null, name: string, description: string } + +export interface LocationUpdateArgs { id: number, name: string | null, indexer_rules_ids: Array } + +export type RuleKind = "AcceptFilesByGlob" | "RejectFilesByGlob" | "AcceptIfChildrenDirectoriesArePresent" | "RejectIfChildrenDirectoriesArePresent" + +export interface TagCreateArgs { name: string, color: string } + +export interface EditLibraryArgs { id: string, name: string | null, description: string | null } + +export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed" | "Paused" + +export interface GenerateThumbsForLocationArgs { id: number, path: string } + +export interface IndexerRule { id: number, kind: number, name: string, parameters: Array, date_created: string, date_modified: string, locations: Array | null } + +export interface JobReport { id: string, name: string, data: Array | null, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: number } + +export interface Location { id: number, pub_id: Array, node_id: number | null, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string, node: Node | null | null, file_paths: Array | null, indexer_rules: Array | null } + +export interface TagUpdateArgs { id: number, name: string | null, color: string | null } + +export interface Tag { id: number, pub_id: Array, name: string | null, color: string | null, total_files: number | null, redundancy_goal: number | null, date_created: string, date_modified: string, tag_files: Array | null } + +export interface Key { id: number, checksum: string, name: string | null, date_created: string | null, algorithm: number | null, files: Array | null, file_paths: Array | null } + +export interface File { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string, tags: Array | null, labels: Array | null, albums: Array | null, spaces: Array | null, paths: Array | null, comments: Array | null, media_data: MediaData | null | null, key: Key | null | null } + +export interface LibraryArgs { library_id: string, arg: T } + +export interface InvalidateOperationEvent { key: string, arg: any } + +export interface FileInSpace { date_created: string, space_id: number, space: Space | null, file_id: number, file: File | null } + +export interface TagOnFile { date_created: string, tag_id: number, tag: Tag | null, file_id: number, file: File | null } + +export interface Space { id: number, pub_id: Array, name: string | null, description: string | null, date_created: string, date_modified: string, files: Array | null } + +export interface Comment { id: number, pub_id: Array, content: string, date_created: string, date_modified: string, file_id: number | null, file: File | null | null } + +export interface IdentifyUniqueFilesArgs { id: number, path: string } + +export interface MediaData { id: number, pixel_width: number | null, pixel_height: number | null, longitude: number | null, latitude: number | null, fps: number | null, capture_device_make: string | null, capture_device_model: string | null, capture_device_software: string | null, duration_seconds: number | null, codecs: string | null, streams: number | null, files: File | null | null } + +export type ExplorerContext = { type: "Location" } & Location | { type: "Tag" } & Tag + +export interface NodeConfig { version: string | null, id: string, name: string, p2p_port: number | null } + +export interface LabelOnFile { date_created: string, label_id: number, label: Label | null, file_id: number, file: File | null } + export interface SetFavoriteArgs { id: number, favorite: boolean } +export interface Volume { name: string, mount_point: string, total_capacity: bigint, available_capacity: bigint, is_removable: boolean, disk_type: string | null, file_system: string | null, is_root_filesystem: boolean } + +export interface SetNoteArgs { id: number, note: string | null } + +export interface LocationCreateArgs { path: string, indexer_rules_ids: Array } + +export interface LibraryConfigWrapped { uuid: string, config: LibraryConfig } + +export interface Label { id: number, pub_id: Array, name: string | null, date_created: string, date_modified: string, label_files: Array | null } + +export interface Album { id: number, pub_id: Array, name: string, is_hidden: boolean, date_created: string, date_modified: string, files: Array | null } + +export interface SyncEvent { id: number, node_id: number, timestamp: string, record_id: Array, kind: number, column: string | null, value: string, node: Node | null } + +export interface FileInAlbum { date_created: string, album_id: number, album: Album | null, file_id: number, file: File | null } + +export type ExplorerItem = { type: "Path" } & FilePath | { type: "Object" } & File + +export interface LocationExplorerArgs { location_id: number, path: string, limit: number, cursor: string | null } + +export interface Statistics { id: number, date_captured: string, total_file_count: number, library_db_size: string, total_bytes_used: string, total_bytes_capacity: string, total_unique_bytes: string, total_bytes_free: string, preview_media_bytes: string } + export interface IndexerRulesInLocation { date_created: string, location_id: number, location: Location | null, indexer_rule_id: number, indexer_rule: IndexerRule | null } export interface NodeState { version: string | null, id: string, name: string, p2p_port: number | null, data_path: string } -export type RuleKind = "AcceptFilesByGlob" | "RejectFilesByGlob" | "AcceptIfChildrenDirectoriesArePresent" | "RejectIfChildrenDirectoriesArePresent" +export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, file_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string, file: File | null | null, location: Location | null | null, key: Key | null | null } -export interface Album { id: number, pub_id: Array, name: string, is_hidden: boolean, date_created: string, date_modified: string, files: Array | null } +export interface ConfigMetadata { version: string | null } export interface TagAssignArgs { file_id: number, tag_id: number, unassign: boolean } -export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed" | "Paused" - -export interface EditLibraryArgs { id: string, name: string | null, description: string | null } - -export interface GenerateThumbsForLocationArgs { id: number, path: string } - -export interface IdentifyUniqueFilesArgs { id: number, path: string } - -export type ExplorerContext = { type: "Location" } & Location | { type: "Tag" } & Tag - -export interface Key { id: number, checksum: string, name: string | null, date_created: string | null, algorithm: number | null, files: Array | null, file_paths: Array | null } - -export interface SyncEvent { id: number, node_id: number, timestamp: string, record_id: Array, kind: number, column: string | null, value: string, node: Node | null } - -export interface SetNoteArgs { id: number, note: string | null } - -export interface File { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string, tags: Array | null, labels: Array | null, albums: Array | null, spaces: Array | null, paths: Array | null, comments: Array | null, media_data: MediaData | null | null, key: Key | null | null } +export interface ExplorerData { context: ExplorerContext, items: Array } diff --git a/core/index.ts b/core/index.ts index 65d2b34a4..c5d75d903 100644 --- a/core/index.ts +++ b/core/index.ts @@ -2,136 +2,136 @@ export type Operations = { queries: - { key: ["library.getStatistics", LibraryArgs], result: Statistics } | - { key: ["volumes.get"], result: Array } | + { key: ["tags.get", LibraryArgs], result: Tag | null } | { key: ["tags.getForFile", LibraryArgs], result: Array } | - { key: ["tags.getExplorerData", LibraryArgs], result: ExplorerData } | + { key: ["locations.getById", LibraryArgs], result: Location | null } | { key: ["locations.indexer_rulesget", LibraryArgs], result: IndexerRule } | { key: ["files.readMetadata", LibraryArgs], result: null } | - { key: ["jobs.getHistory", LibraryArgs], result: Array } | - { key: ["locations.getById", LibraryArgs], result: Location | null } | - { key: ["locations.getExplorerData", LibraryArgs], result: ExplorerData } | - { key: ["getNode"], result: NodeState } | - { key: ["locations.get", LibraryArgs], result: Array } | - { key: ["tags.get", LibraryArgs], result: Tag | null } | - { key: ["locations.indexer_ruleslist", LibraryArgs], result: Array } | - { key: ["library.get"], result: Array } | { key: ["tags.getAll", LibraryArgs], result: Array } | + { key: ["jobs.getHistory", LibraryArgs], result: Array } | + { key: ["getNode"], result: NodeState } | + { key: ["library.getStatistics", LibraryArgs], result: Statistics } | + { key: ["version"], result: string } | { key: ["jobs.getRunning", LibraryArgs], result: Array } | - { key: ["version"], result: string }, + { key: ["library.get"], result: Array } | + { key: ["locations.get", LibraryArgs], result: Array } | + { key: ["volumes.get"], result: Array } | + { key: ["locations.indexer_ruleslist", LibraryArgs], result: Array } | + { key: ["locations.getExplorerData", LibraryArgs], result: ExplorerData } | + { key: ["tags.getExplorerData", LibraryArgs], result: ExplorerData }, mutations: - { key: ["locations.create", LibraryArgs], result: Location } | - { key: ["locations.fullRescan", LibraryArgs], result: null } | - { key: ["locations.quickRescan", LibraryArgs], result: null } | - { key: ["files.setFavorite", LibraryArgs], result: null } | - { key: ["jobs.generateThumbsForLocation", LibraryArgs], result: null } | - { key: ["locations.update", LibraryArgs], result: null } | - { key: ["tags.update", LibraryArgs], result: null } | - { key: ["library.create", string], result: null } | - { key: ["files.delete", LibraryArgs], result: null } | - { key: ["tags.create", LibraryArgs], result: Tag } | - { key: ["tags.delete", LibraryArgs], result: null } | - { key: ["tags.assign", LibraryArgs], result: null } | - { key: ["library.edit", EditLibraryArgs], result: null } | - { key: ["locations.indexer_rulescreate", LibraryArgs], result: IndexerRule } | - { key: ["files.setNote", LibraryArgs], result: null } | - { key: ["jobs.identifyUniqueFiles", LibraryArgs], result: null } | - { key: ["library.delete", string], result: null } | { key: ["locations.indexer_rulesdelete", LibraryArgs], result: null } | + { key: ["library.create", string], result: null } | + { key: ["locations.quickRescan", LibraryArgs], result: null } | + { key: ["locations.update", LibraryArgs], result: null } | + { key: ["tags.assign", LibraryArgs], result: null } | + { key: ["locations.fullRescan", LibraryArgs], result: null } | + { key: ["files.delete", LibraryArgs], result: null } | + { key: ["files.setFavorite", LibraryArgs], result: null } | + { key: ["files.setNote", LibraryArgs], result: null } | + { key: ["tags.delete", LibraryArgs], result: null } | + { key: ["tags.update", LibraryArgs], result: null } | + { key: ["locations.indexer_rulescreate", LibraryArgs], result: IndexerRule } | + { key: ["locations.create", LibraryArgs], result: Location } | + { key: ["jobs.generateThumbsForLocation", LibraryArgs], result: null } | + { key: ["library.edit", EditLibraryArgs], result: null } | + { key: ["library.delete", string], result: null } | + { key: ["jobs.identifyUniqueFiles", LibraryArgs], result: null } | + { key: ["tags.create", LibraryArgs], result: Tag } | { key: ["locations.delete", LibraryArgs], result: null }, subscriptions: { key: ["invalidateQuery"], result: InvalidateOperationEvent } | { key: ["jobs.newThumbnail", LibraryArgs], result: string } }; -export interface InvalidateOperationEvent { key: string, arg: any } - -export interface LocationExplorerArgs { location_id: number, path: string, limit: number, cursor: string | null } - -export interface LibraryConfig { version: string | null, name: string, description: string } - -export interface FileInSpace { date_created: string, space_id: number, space: Space | null, file_id: number, file: File | null } - -export interface LabelOnFile { date_created: string, label_id: number, label: Label | null, file_id: number, file: File | null } - -export interface JobReport { id: string, name: string, data: Array | null, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: number } - -export type ExplorerItem = { type: "Path" } & FilePath | { type: "Object" } & File - -export interface NodeConfig { version: string | null, id: string, name: string, p2p_port: number | null } - -export interface LibraryConfigWrapped { uuid: string, config: LibraryConfig } - -export interface ConfigMetadata { version: string | null } - -export interface MediaData { id: number, pixel_width: number | null, pixel_height: number | null, longitude: number | null, latitude: number | null, fps: number | null, capture_device_make: string | null, capture_device_model: string | null, capture_device_software: string | null, duration_seconds: number | null, codecs: string | null, streams: number | null, files: File | null | null } - -export interface Space { id: number, pub_id: Array, name: string | null, description: string | null, date_created: string, date_modified: string, files: Array | null } - -export interface Label { id: number, pub_id: Array, name: string | null, date_created: string, date_modified: string, label_files: Array | null } - -export interface Volume { name: string, mount_point: string, total_capacity: bigint, available_capacity: bigint, is_removable: boolean, disk_type: string | null, file_system: string | null, is_root_filesystem: boolean } - -export interface ExplorerData { context: ExplorerContext, items: Array } - -export interface LibraryArgs { library_id: string, arg: T } - -export interface TagUpdateArgs { id: number, name: string | null, color: string | null } - -export interface LocationCreateArgs { path: string, indexer_rules_ids: Array } - -export interface FileInAlbum { date_created: string, album_id: number, album: Album | null, file_id: number, file: File | null } - -export interface TagOnFile { date_created: string, tag_id: number, tag: Tag | null, file_id: number, file: File | null } - -export interface Tag { id: number, pub_id: Array, name: string | null, color: string | null, total_files: number | null, redundancy_goal: number | null, date_created: string, date_modified: string, tag_files: Array | null } - -export interface IndexerRule { id: number, kind: number, name: string, parameters: Array, date_created: string, date_modified: string, locations: Array | null } - -export interface Location { id: number, pub_id: Array, node_id: number | null, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string, node: Node | null | null, file_paths: Array | null, indexer_rules: Array | null } - -export interface TagCreateArgs { name: string, color: string } - -export interface Statistics { id: number, date_captured: string, total_file_count: number, library_db_size: string, total_bytes_used: string, total_bytes_capacity: string, total_unique_bytes: string, total_bytes_free: string, preview_media_bytes: string } - -export interface Comment { id: number, pub_id: Array, content: string, date_created: string, date_modified: string, file_id: number | null, file: File | null | null } - export interface Node { id: number, pub_id: Array, name: string, platform: number, version: string | null, last_seen: string, timezone: string | null, date_created: string, sync_events: Array | null, jobs: Array | null, Location: Array | null } -export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, file_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string, file: File | null | null, location: Location | null | null, key: Key | null | null } - -export interface LocationUpdateArgs { id: number, name: string | null, indexer_rules_ids: Array } - -export interface IndexerRuleCreateArgs { kind: RuleKind, name: string, parameters: Array } - export interface Job { id: Array, name: string, node_id: number, action: number, status: number, data: Array | null, task_count: number, completed_task_count: number, date_created: string, date_modified: string, seconds_elapsed: number, nodes: Node | null } +export interface IndexerRuleCreateArgs { kind: RuleKind, name: string, parameters: Array } + +export interface LibraryConfig { version: string | null, name: string, description: string } + +export interface LocationUpdateArgs { id: number, name: string | null, indexer_rules_ids: Array } + +export type RuleKind = "AcceptFilesByGlob" | "RejectFilesByGlob" | "AcceptIfChildrenDirectoriesArePresent" | "RejectIfChildrenDirectoriesArePresent" + +export interface TagCreateArgs { name: string, color: string } + +export interface EditLibraryArgs { id: string, name: string | null, description: string | null } + +export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed" | "Paused" + +export interface GenerateThumbsForLocationArgs { id: number, path: string } + +export interface IndexerRule { id: number, kind: number, name: string, parameters: Array, date_created: string, date_modified: string, locations: Array | null } + +export interface JobReport { id: string, name: string, data: Array | null, date_created: string, date_modified: string, status: JobStatus, task_count: number, completed_task_count: number, message: string, seconds_elapsed: number } + +export interface Location { id: number, pub_id: Array, node_id: number | null, name: string | null, local_path: string | null, total_capacity: number | null, available_capacity: number | null, filesystem: string | null, disk_type: number | null, is_removable: boolean | null, is_online: boolean, is_archived: boolean, date_created: string, node: Node | null | null, file_paths: Array | null, indexer_rules: Array | null } + +export interface TagUpdateArgs { id: number, name: string | null, color: string | null } + +export interface Tag { id: number, pub_id: Array, name: string | null, color: string | null, total_files: number | null, redundancy_goal: number | null, date_created: string, date_modified: string, tag_files: Array | null } + +export interface Key { id: number, checksum: string, name: string | null, date_created: string | null, algorithm: number | null, files: Array | null, file_paths: Array | null } + +export interface File { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string, tags: Array | null, labels: Array | null, albums: Array | null, spaces: Array | null, paths: Array | null, comments: Array | null, media_data: MediaData | null | null, key: Key | null | null } + +export interface LibraryArgs { library_id: string, arg: T } + +export interface InvalidateOperationEvent { key: string, arg: any } + +export interface FileInSpace { date_created: string, space_id: number, space: Space | null, file_id: number, file: File | null } + +export interface TagOnFile { date_created: string, tag_id: number, tag: Tag | null, file_id: number, file: File | null } + +export interface Space { id: number, pub_id: Array, name: string | null, description: string | null, date_created: string, date_modified: string, files: Array | null } + +export interface Comment { id: number, pub_id: Array, content: string, date_created: string, date_modified: string, file_id: number | null, file: File | null | null } + +export interface IdentifyUniqueFilesArgs { id: number, path: string } + +export interface MediaData { id: number, pixel_width: number | null, pixel_height: number | null, longitude: number | null, latitude: number | null, fps: number | null, capture_device_make: string | null, capture_device_model: string | null, capture_device_software: string | null, duration_seconds: number | null, codecs: string | null, streams: number | null, files: File | null | null } + +export type ExplorerContext = { type: "Location" } & Location | { type: "Tag" } & Tag + +export interface NodeConfig { version: string | null, id: string, name: string, p2p_port: number | null } + +export interface LabelOnFile { date_created: string, label_id: number, label: Label | null, file_id: number, file: File | null } + export interface SetFavoriteArgs { id: number, favorite: boolean } +export interface Volume { name: string, mount_point: string, total_capacity: bigint, available_capacity: bigint, is_removable: boolean, disk_type: string | null, file_system: string | null, is_root_filesystem: boolean } + +export interface SetNoteArgs { id: number, note: string | null } + +export interface LocationCreateArgs { path: string, indexer_rules_ids: Array } + +export interface LibraryConfigWrapped { uuid: string, config: LibraryConfig } + +export interface Label { id: number, pub_id: Array, name: string | null, date_created: string, date_modified: string, label_files: Array | null } + +export interface Album { id: number, pub_id: Array, name: string, is_hidden: boolean, date_created: string, date_modified: string, files: Array | null } + +export interface SyncEvent { id: number, node_id: number, timestamp: string, record_id: Array, kind: number, column: string | null, value: string, node: Node | null } + +export interface FileInAlbum { date_created: string, album_id: number, album: Album | null, file_id: number, file: File | null } + +export type ExplorerItem = { type: "Path" } & FilePath | { type: "Object" } & File + +export interface LocationExplorerArgs { location_id: number, path: string, limit: number, cursor: string | null } + +export interface Statistics { id: number, date_captured: string, total_file_count: number, library_db_size: string, total_bytes_used: string, total_bytes_capacity: string, total_unique_bytes: string, total_bytes_free: string, preview_media_bytes: string } + export interface IndexerRulesInLocation { date_created: string, location_id: number, location: Location | null, indexer_rule_id: number, indexer_rule: IndexerRule | null } export interface NodeState { version: string | null, id: string, name: string, p2p_port: number | null, data_path: string } -export type RuleKind = "AcceptFilesByGlob" | "RejectFilesByGlob" | "AcceptIfChildrenDirectoriesArePresent" | "RejectIfChildrenDirectoriesArePresent" +export interface FilePath { id: number, is_dir: boolean, location_id: number, materialized_path: string, name: string, extension: string | null, file_id: number | null, parent_id: number | null, key_id: number | null, date_created: string, date_modified: string, date_indexed: string, file: File | null | null, location: Location | null | null, key: Key | null | null } -export interface Album { id: number, pub_id: Array, name: string, is_hidden: boolean, date_created: string, date_modified: string, files: Array | null } +export interface ConfigMetadata { version: string | null } export interface TagAssignArgs { file_id: number, tag_id: number, unassign: boolean } -export type JobStatus = "Queued" | "Running" | "Completed" | "Canceled" | "Failed" | "Paused" - -export interface EditLibraryArgs { id: string, name: string | null, description: string | null } - -export interface GenerateThumbsForLocationArgs { id: number, path: string } - -export interface IdentifyUniqueFilesArgs { id: number, path: string } - -export type ExplorerContext = { type: "Location" } & Location | { type: "Tag" } & Tag - -export interface Key { id: number, checksum: string, name: string | null, date_created: string | null, algorithm: number | null, files: Array | null, file_paths: Array | null } - -export interface SyncEvent { id: number, node_id: number, timestamp: string, record_id: Array, kind: number, column: string | null, value: string, node: Node | null } - -export interface SetNoteArgs { id: number, note: string | null } - -export interface File { id: number, cas_id: string, integrity_checksum: string | null, name: string | null, extension: string | null, kind: number, size_in_bytes: string, key_id: number | null, hidden: boolean, favorite: boolean, important: boolean, has_thumbnail: boolean, has_thumbstrip: boolean, has_video_preview: boolean, ipfs_id: string | null, note: string | null, date_created: string, date_modified: string, date_indexed: string, tags: Array | null, labels: Array | null, albums: Array | null, spaces: Array | null, paths: Array | null, comments: Array | null, media_data: MediaData | null | null, key: Key | null | null } +export interface ExplorerData { context: ExplorerContext, items: Array } diff --git a/core/src/file/cas/identifier.rs b/core/src/file/cas/identifier.rs index e193318a3..fa04a22d0 100644 --- a/core/src/file/cas/identifier.rs +++ b/core/src/file/cas/identifier.rs @@ -143,7 +143,7 @@ impl StatefulJob for FileIdentifierJob { // analyze each file_path for file_path in &file_paths { // get the cas_id and extract metadata - match prepare_file(&data.location_path, file_path).await { + match assemble_object_metadata(&data.location_path, file_path).await { Ok(file) => { let cas_id = file.cas_id.clone(); // create entry into chunks for created file data @@ -151,7 +151,7 @@ impl StatefulJob for FileIdentifierJob { cas_lookup.insert(cas_id, file_path.id); } Err(e) => { - info!("Error processing file: {:#?}", e); + info!("Error assembling Object metadata: {:#?}", e); continue; } }; @@ -167,12 +167,14 @@ impl StatefulJob for FileIdentifierJob { .exec() .await?; - info!("Found {} existing files", existing_files.len()); + info!("Found {} existing Objects", existing_files.len()); // link those existing files to their file paths // Had to put the file_path in a variable outside of the closure, to satisfy the borrow checker let library_ctx = ctx.library_ctx(); + // if existing_files.len() > 0 { + // connect Paths that match existing Objects in the database for existing_file in &existing_files { if let Err(e) = library_ctx .db @@ -203,6 +205,11 @@ impl StatefulJob for FileIdentifierJob { .filter(|create_file| !existing_files_cas_ids.contains(&create_file.cas_id)) .collect::>(); + if new_files.is_empty() { + error!("This shouldn't happen?"); + return Ok(()); + } + // assemble prisma values for new unique files let mut values = Vec::with_capacity(new_files.len() * 3); for file in &new_files { @@ -213,6 +220,8 @@ impl StatefulJob for FileIdentifierJob { ]); } + info!("{:?}", values); + // create new file records with assembled values let created_files: Vec = ctx .library_ctx() @@ -220,7 +229,7 @@ impl StatefulJob for FileIdentifierJob { ._query_raw(Raw::new( &format!( "INSERT INTO files (cas_id, size_in_bytes, date_created) VALUES {} - ON CONFLICT (cas_id) DO NOTHING RETURNING id, cas_id", + ON CONFLICT (cas_id) DO NOTHING RETURNING id, cas_id", vec!["({}, {}, {})"; new_files.len()].join(",") ), values, @@ -231,7 +240,6 @@ impl StatefulJob for FileIdentifierJob { error!("Error inserting files: {:#?}", e); Vec::new() }); - for created_file in created_files { // associate newly created files with their respective file_paths // TODO: this is potentially bottle necking the chunk system, individually linking file_path to file, 100 queries per chunk @@ -254,12 +262,13 @@ impl StatefulJob for FileIdentifierJob { } } - // handle last step + // set the step data cursor to the last row of this chunk if let Some(last_row) = file_paths.last() { data.cursor.file_path_id = last_row.id; } else { return Ok(()); } + // } ctx.progress(vec![ JobReportUpdate::CompletedTaskCount(state.step_number), @@ -348,7 +357,7 @@ struct FileCreated { pub cas_id: String, } -async fn prepare_file( +async fn assemble_object_metadata( location_path: impl AsRef, file_path: &file_path::Data, ) -> Result { diff --git a/core/src/job/worker.rs b/core/src/job/worker.rs index 99f1bc731..e94bd61d5 100644 --- a/core/src/job/worker.rs +++ b/core/src/job/worker.rs @@ -18,7 +18,10 @@ use super::JobReport; // used to update the worker state from inside the worker thread #[derive(Debug)] pub enum WorkerEvent { - Progressed(Vec), + Progressed { + updates: Vec, + debounce: bool, + }, Completed(oneshot::Sender<()>), Failed(oneshot::Sender<()>), Paused(Vec, oneshot::Sender<()>), @@ -34,7 +37,18 @@ pub struct WorkerContext { impl WorkerContext { pub fn progress(&self, updates: Vec) { self.events_tx - .send(WorkerEvent::Progressed(updates)) + .send(WorkerEvent::Progressed { + updates, + debounce: false, + }) + .expect("critical error: failed to send worker worker progress event updates"); + } + pub fn progress_debounced(&self, updates: Vec) { + self.events_tx + .send(WorkerEvent::Progressed { + updates, + debounce: true, + }) .expect("critical error: failed to send worker worker progress event updates"); } @@ -124,9 +138,10 @@ impl Worker { loop { interval.tick().await; if events_tx - .send(WorkerEvent::Progressed(vec![ - JobReportUpdate::SecondsElapsed(1), - ])) + .send(WorkerEvent::Progressed { + updates: vec![JobReportUpdate::SecondsElapsed(1)], + debounce: false, + }) .is_err() && events_tx.is_closed() { break; @@ -171,17 +186,27 @@ impl Worker { mut worker_events_rx: UnboundedReceiver, library: LibraryContext, ) { + let mut last = Instant::now(); + while let Some(command) = worker_events_rx.recv().await { let mut worker = worker.lock().await; match command { - WorkerEvent::Progressed(changes) => { + WorkerEvent::Progressed { updates, debounce } => { + if debounce { + let current = Instant::now(); + if current.duration_since(last) > Duration::from_millis(1000 / 60) { + last = current + } else { + continue; + } + } // protect against updates if job is not running if worker.report.status != JobStatus::Running { continue; }; - for change in changes { - match change { + for update in updates { + match update { JobReportUpdate::TaskCount(task_count) => { worker.report.task_count = task_count as i32; } diff --git a/core/src/location/indexer/indexer_job.rs b/core/src/location/indexer/indexer_job.rs index c9a89cbb2..fc5b2545a 100644 --- a/core/src/location/indexer/indexer_job.rs +++ b/core/src/location/indexer/indexer_job.rs @@ -66,7 +66,7 @@ pub struct IndexerJobStepEntry { impl IndexerJobData { fn on_scan_progress(ctx: WorkerContext, progress: Vec) { - ctx.progress( + ctx.progress_debounced( progress .iter() .map(|p| match p.clone() { diff --git a/packages/interface/src/components/explorer/FileThumb.tsx b/packages/interface/src/components/explorer/FileThumb.tsx index 8f0edaeba..303e701bd 100644 --- a/packages/interface/src/components/explorer/FileThumb.tsx +++ b/packages/interface/src/components/explorer/FileThumb.tsx @@ -1,7 +1,7 @@ import { AppPropsContext, explorerStore } from '@sd/client'; import { ExplorerItem } from '@sd/core'; import clsx from 'clsx'; -import React, { useContext } from 'react'; +import React, { useContext, useState } from 'react'; import { useSnapshot } from 'valtio'; import icons from '../../assets/icons'; @@ -39,6 +39,7 @@ export default function FileThumb({ data, ...props }: Props) { if (file_thumb_url) return ( ['children']; -}> = (props) => { - const { menu: sections = [], children } = props; - - return ( - - {children} - - - - ); -}; diff --git a/packages/interface/src/screens/Content.tsx b/packages/interface/src/screens/Content.tsx index 83b8834a2..2019ab92c 100644 --- a/packages/interface/src/screens/Content.tsx +++ b/packages/interface/src/screens/Content.tsx @@ -1,15 +1,7 @@ import { Button } from '@sd/ui'; import React from 'react'; -import { WithContextMenu } from '../components/layout/MenuOverlay'; - export const ContentScreen: React.FC = (props) => { // const [address, setAddress] = React.useState(''); - return ( -
- - - -
- ); + return
; }; diff --git a/packages/ui/src/ContextMenu.stories.tsx b/packages/ui/src/ContextMenu.stories.tsx deleted file mode 100644 index 9920e941b..000000000 --- a/packages/ui/src/ContextMenu.stories.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { FileText, Plus, Trash } from 'phosphor-react'; -import React from 'react'; - -import { ContextMenu } from './ContextMenu'; - -export default { - title: 'UI/Context Menu', - component: ContextMenu, - argTypes: {}, - parameters: {}, - args: {} -} as ComponentMeta; - -const Template: ComponentStory = (args) => ; - -export const Default = Template.bind({}); -Default.args = { - items: [ - [ - { - label: 'New Item', - icon: Plus, - onClick: () => {} - } - ], - [ - { - label: 'View Info', - icon: FileText, - onClick: () => {} - }, - { - label: 'Delete', - icon: Trash, - danger: true, - onClick: () => {} - } - ] - ] -}; diff --git a/packages/ui/src/ContextMenu.tsx b/packages/ui/src/ContextMenu.tsx deleted file mode 100644 index d9759e627..000000000 --- a/packages/ui/src/ContextMenu.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import * as ContextMenuPrimitive from '@radix-ui/react-context-menu'; -import { Root, Trigger } from '@radix-ui/react-context-menu'; -import clsx from 'clsx'; -import { CaretRight, Icon } from 'phosphor-react'; -import { Question } from 'phosphor-react'; -import React from 'react'; - -export interface ContextMenuItem { - label: string; - icon?: Icon; - danger?: boolean; - active?: boolean; - leftItem?: React.ReactNode; - rightItem?: React.ReactNode; - onClick?: React.MouseEventHandler; - - children?: ContextMenuSection[]; -} - -export type ContextMenuSection = (ContextMenuItem | string)[]; - -export interface ContextMenuProps { - items?: ContextMenuSection[]; - className?: string; - isChild?: boolean; -} - -export const ContextMenu: React.FC = (props) => { - const { items: sections = [], className, isChild, ...rest } = props; - - const ContentPrimitive = isChild ? ContextMenuPrimitive.SubContent : ContextMenuPrimitive.Content; - - return ( - { - // e.preventDefault(); - // }} - alignOffset={7} - className={clsx( - 'shadow-md min-w-[11rem] py-0.5 shadow-gray-300 dark:shadow-gray-750 flex flex-col select-none cursor-default bg-gray-50 text-gray-800 border-gray-200 dark:bg-gray-950 dark:text-gray-100 text-left text-sm rounded-lg ', - className - )} - {...rest} - > - {sections.map((sec, i) => ( - - {i !== 0 && ( - - )} - - - {sec.map((item) => { - if (typeof item === 'string') - return ( - - {item} - - ); - - const { icon: ItemIcon } = item; - - let ItemComponent: - | typeof ContextMenuPrimitive.Item - | typeof ContextMenuPrimitive.Trigger = ContextMenuPrimitive.Item; - - if ((item.children?.length ?? 0) > 0) - ItemComponent = (({ children, ref, ...props }) => ( - - - {children} - - - - - )) as typeof ContextMenuPrimitive.Trigger; - - return ( - -
- {ItemIcon && } - {item.leftItem} - - - {item.label} - - - {item.rightItem} - {(item.children?.length ?? 0) > 0 && ( - - )} -
-
- ); - })} -
-
- ))} -
- ); -}; - -export { Trigger, Root };