diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index 246e04bcd..10b5b9bd9 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -10,7 +10,12 @@ import type { FSWatcher } from "chokidar"; import { ipcMain } from "electron/main"; -import type { ElectronFile, FolderWatch, PendingUploads } from "../types/ipc"; +import type { + CollectionMapping, + ElectronFile, + FolderWatch, + PendingUploads, +} from "../types/ipc"; import { selectDirectory, showUploadDirsDialog, @@ -54,12 +59,12 @@ import { setPendingUploadFiles, } from "./services/upload"; import { - addWatchMapping, - findFiles, - getWatchMappings, - removeWatchMapping, updateWatchMappingIgnoredFiles, updateWatchMappingSyncedFiles, + watchAdd, + watchFindFiles, + watchGet, + watchRemove, } from "./services/watch"; import { openDirectory, openLogDirectory } from "./util"; @@ -214,36 +219,26 @@ export const attachIPCHandlers = () => { * watch folder functionality. * * It gets passed a {@link FSWatcher} instance which it can then forward to the - * actual handlers. + * actual handlers if they need access to it to do their thing. */ export const attachFSWatchIPCHandlers = (watcher: FSWatcher) => { // - Watch - ipcMain.handle("findFiles", (_, folderPath: string) => - findFiles(folderPath), - ); + ipcMain.handle("watchGet", () => watchGet()); ipcMain.handle( - "addWatchMapping", - ( - _, - collectionName: string, - folderPath: string, - uploadStrategy: number, - ) => - addWatchMapping( - watcher, - collectionName, - folderPath, - uploadStrategy, - ), + "watchAdd", + (_, folderPath: string, collectionMapping: CollectionMapping) => + watchAdd(watcher, folderPath, collectionMapping), ); - ipcMain.handle("removeWatchMapping", (_, folderPath: string) => - removeWatchMapping(watcher, folderPath), + ipcMain.handle("watchRemove", (_, folderPath: string) => + watchRemove(watcher, folderPath), ); - ipcMain.handle("getWatchMappings", () => getWatchMappings()); + ipcMain.handle("watchFindFiles", (_, folderPath: string) => + watchFindFiles(folderPath), + ); ipcMain.handle( "updateWatchMappingSyncedFiles", diff --git a/desktop/src/main/services/watch.ts b/desktop/src/main/services/watch.ts index b12913ed4..a5cfe58d3 100644 --- a/desktop/src/main/services/watch.ts +++ b/desktop/src/main/services/watch.ts @@ -2,7 +2,7 @@ import chokidar, { type FSWatcher } from "chokidar"; import { BrowserWindow } from "electron/main"; import fs from "node:fs/promises"; import path from "node:path"; -import { FolderWatch } from "../../types/ipc"; +import { FolderWatch, type CollectionMapping } from "../../types/ipc"; import log from "../log"; import { watchStore } from "../stores/watch"; @@ -52,27 +52,15 @@ const eventData = (path: string): [string, FolderWatch] => { const posixPath = (filePath: string) => filePath.split(path.sep).join(path.posix.sep); -export const findFiles = async (dirPath: string) => { - const items = await fs.readdir(dirPath, { withFileTypes: true }); - let paths: string[] = []; - for (const item of items) { - const itemPath = path.posix.join(dirPath, item.name); - if (item.isFile()) { - paths.push(itemPath); - } else if (item.isDirectory()) { - paths = [...paths, ...(await findFiles(itemPath))]; - } - } - return paths; +export const watchGet = () => { + return folderWatches(); }; -export const addWatchMapping = async ( +export const watchAdd = async ( watcher: FSWatcher, - rootFolderName: string, folderPath: string, - uploadStrategy: number, + collectionMapping: CollectionMapping, ) => { - log.info(`Adding watch mapping: ${folderPath}`); const watchMappings = getWatchMappings(); if (isMappingPresent(watchMappings, folderPath)) { throw new Error(`Watch mapping already exists`); @@ -98,10 +86,7 @@ function isMappingPresent(watchMappings: FolderWatch[], folderPath: string) { return !!watchMapping; } -export const removeWatchMapping = async ( - watcher: FSWatcher, - folderPath: string, -) => { +export const watchRemove = async (watcher: FSWatcher, folderPath: string) => { let watchMappings = getWatchMappings(); const watchMapping = watchMappings.find( (mapping) => mapping.folderPath === folderPath, @@ -154,7 +139,7 @@ export function updateWatchMappingIgnoredFiles( setWatchMappings(watchMappings); } -export const folderWatches = () => { +const folderWatches = () => { const mappings = watchStore.get("mappings") ?? []; return mappings; }; @@ -162,3 +147,17 @@ export const folderWatches = () => { function setWatchMappings(watchMappings: WatchStoreType["mappings"]) { watchStore.set("mappings", watchMappings); } + +export const watchFindFiles = async (dirPath: string) => { + const items = await fs.readdir(dirPath, { withFileTypes: true }); + let paths: string[] = []; + for (const item of items) { + const itemPath = path.posix.join(dirPath, item.name); + if (item.isFile()) { + paths.push(itemPath); + } else if (item.isDirectory()) { + paths = [...paths, ...(await watchFindFiles(itemPath))]; + } + } + return paths; +}; diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index c23baef4e..7af959256 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -192,9 +192,6 @@ const showUploadZipDialog = (): Promise<{ // - Watch -const watchFindFiles = (folderPath: string): Promise => - ipcRenderer.invoke("watchFindFiles", folderPath); - const watchAdd = ( folderPath: string, collectionMapping: CollectionMapping, @@ -227,6 +224,9 @@ const watchOnRemoveDir = (f: (path: string, watch: FolderWatch) => void) => { ); }; +const watchFindFiles = (folderPath: string): Promise => + ipcRenderer.invoke("watchFindFiles", folderPath); + const updateWatchMappingSyncedFiles = ( folderPath: string, files: FolderWatch["syncedFiles"], @@ -354,13 +354,13 @@ contextBridge.exposeInMainWorld("electron", { // - Watch watch: { - findFiles: watchFindFiles, + get: watchGet, add: watchAdd, remove: watchRemove, - get: watchGet, onAddFile: watchOnAddFile, onRemoveFile: watchOnRemoveFile, onRemoveDir: watchOnRemoveDir, + findFiles: watchFindFiles, }, updateWatchMappingSyncedFiles, updateWatchMappingIgnoredFiles, diff --git a/web/packages/next/types/ipc.ts b/web/packages/next/types/ipc.ts index 7bb8428dd..3a7aff3e8 100644 --- a/web/packages/next/types/ipc.ts +++ b/web/packages/next/types/ipc.ts @@ -290,16 +290,14 @@ export interface Electron { */ watch: { /** - * Return the paths of all the files under the given folder. + * Return the list of folder watches. * - * This function walks the directory tree starting at {@link folderPath} - * and returns a list of the absolute paths of all the files that exist - * therein. It will recursively traverse into nested directories, and - * return the absolute paths of the files there too. - * - * The returned paths are guaranteed to use POSIX separators ('/'). + * The list of folder paths (and auxillary details) is persisted in the + * Node.js layer. When we invoke this method, the Node.js goes through + * the list, permanently removes any watches whose on-disk directory has + * is no longer present, and returns this pruned list of watches. */ - findFiles: (folderPath: string) => Promise; + get: () => Promise; /** * Add a new folder watch for the given {@link folderPath}. @@ -324,16 +322,6 @@ export interface Electron { */ remove: (folderPath: string) => Promise; - /** - * Return the list of folder watches. - * - * The list of folder paths (and auxillary details) is persisted in the - * Node.js layer. When we invoke this method, the Node.js goes through - * the list, permanently removes any watches whose on-disk directory has - * is no longer present, and returns this pruned list of watches. - */ - get: () => Promise; - /** * Register the function to invoke when a file is added in one of the * folders we are watching. @@ -366,6 +354,18 @@ export interface Electron { * The path is guaranteed to use POSIX separators ('/'). */ onRemoveDir: (f: (path: string, watch: FolderWatch) => void) => void; + + /** + * Return the paths of all the files under the given folder. + * + * This function walks the directory tree starting at {@link folderPath} + * and returns a list of the absolute paths of all the files that exist + * therein. It will recursively traverse into nested directories, and + * return the absolute paths of the files there too. + * + * The returned paths are guaranteed to use POSIX separators ('/'). + */ + findFiles: (folderPath: string) => Promise; }; updateWatchMappingSyncedFiles: (