diff --git a/desktop/src/api/upload.ts b/desktop/src/api/upload.ts index 0a31ee353..49c9d094d 100644 --- a/desktop/src/api/upload.ts +++ b/desktop/src/api/upload.ts @@ -1,5 +1,3 @@ -import { ipcRenderer } from "electron"; -import { logError } from "../main/log"; import { getElectronFilesFromGoogleZip, getSavedFilePaths, @@ -36,53 +34,6 @@ export const getPendingUploads = async () => { }; }; -export const showUploadDirsDialog = async () => { - try { - const filePaths: string[] = await ipcRenderer.invoke( - "show-upload-dirs-dialog", - ); - const files = await Promise.all(filePaths.map(getElectronFile)); - return files; - } catch (e) { - logError(e, "error while selecting folders"); - } -}; - -export const showUploadFilesDialog = async () => { - try { - const filePaths: string[] = await ipcRenderer.invoke( - "show-upload-files-dialog", - ); - const files = await Promise.all(filePaths.map(getElectronFile)); - return files; - } catch (e) { - logError(e, "error while selecting files"); - } -}; - -export const showUploadZipDialog = async () => { - try { - const filePaths: string[] = await ipcRenderer.invoke( - "show-upload-zip-dialog", - ); - let files: ElectronFile[] = []; - - for (const filePath of filePaths) { - files = [ - ...files, - ...(await getElectronFilesFromGoogleZip(filePath)), - ]; - } - - return { - zipPaths: filePaths, - files, - }; - } catch (e) { - logError(e, "error while selecting zips"); - } -}; - export { getElectronFilesFromGoogleZip, setToUploadCollection, diff --git a/desktop/src/main/dialogs.ts b/desktop/src/main/dialogs.ts new file mode 100644 index 000000000..a4efed473 --- /dev/null +++ b/desktop/src/main/dialogs.ts @@ -0,0 +1,54 @@ +import { dialog } from "electron/main"; +import * as path from "node:path"; +import { getDirFilePaths, getElectronFile } from "../services/fs"; +import { getElectronFilesFromGoogleZip } from "../services/upload"; +import type { ElectronFile } from "../types"; + +export const selectDirectory = async () => { + const result = await dialog.showOpenDialog({ + properties: ["openDirectory"], + }); + if (result.filePaths && result.filePaths.length > 0) { + return result.filePaths[0]?.split(path.sep)?.join(path.posix.sep); + } +}; + +export const showUploadFilesDialog = async () => { + const selectedFiles = await dialog.showOpenDialog({ + properties: ["openFile", "multiSelections"], + }); + const filePaths = selectedFiles.filePaths; + return await Promise.all(filePaths.map(getElectronFile)); +}; + +export const showUploadDirsDialog = async () => { + const dir = await dialog.showOpenDialog({ + properties: ["openDirectory", "multiSelections"], + }); + + let filePaths: string[] = []; + for (const dirPath of dir.filePaths) { + filePaths = [...filePaths, ...(await getDirFilePaths(dirPath))]; + } + + return await Promise.all(filePaths.map(getElectronFile)); +}; + +export const showUploadZipDialog = async () => { + const selectedFiles = await dialog.showOpenDialog({ + properties: ["openFile", "multiSelections"], + filters: [{ name: "Zip File", extensions: ["zip"] }], + }); + const filePaths = selectedFiles.filePaths; + + let files: ElectronFile[] = []; + + for (const filePath of filePaths) { + files = [...files, ...(await getElectronFilesFromGoogleZip(filePath))]; + } + + return { + zipPaths: filePaths, + files, + }; +}; diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index 89698ae4a..c60219f4d 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -25,6 +25,12 @@ import { generateImageThumbnail, } from "../services/imageProcessor"; import type { ElectronFile, Model } from "../types"; +import { + selectDirectory, + showUploadDirsDialog, + showUploadFilesDialog, + showUploadZipDialog, +} from "./dialogs"; import { checkExistsAndCreateDir, fsExists } from "./fs"; import { openDirectory, openLogDirectory } from "./general"; import { logToDisk } from "./log"; @@ -106,6 +112,14 @@ export const attachIPCHandlers = () => { computeTextEmbedding(model, text), ); + ipcMain.handle("selectDirectory", (_) => selectDirectory()); + + ipcMain.handle("showUploadFilesDialog", (_) => showUploadFilesDialog()); + + ipcMain.handle("showUploadDirsDialog", (_) => showUploadDirsDialog()); + + ipcMain.handle("showUploadZipDialog", (_) => showUploadZipDialog()); + ipcMain.handle("fsExists", (_, path) => fsExists(path)); ipcMain.handle("checkExistsAndCreateDir", (_, dirPath) => diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index 3c1d2057d..eb8a59fdc 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -31,15 +31,13 @@ import { createWriteStream, existsSync } from "node:fs"; import * as fs from "node:fs/promises"; import { Readable } from "node:stream"; import path from "path"; +import type { ElectronFile } from "./types"; import { getDirFiles } from "./api/fs"; import { getElectronFilesFromGoogleZip, getPendingUploads, setToUploadCollection, setToUploadFiles, - showUploadDirsDialog, - showUploadFilesDialog, - showUploadZipDialog, } from "./api/upload"; import { addWatchMapping, @@ -50,7 +48,6 @@ import { updateWatchMappingSyncedFiles, } from "./api/watch"; import { logErrorSentry, setupLogging } from "./main/log"; -import type { ElectronFile } from "types"; setupLogging(); @@ -176,6 +173,12 @@ const runFFmpegCmd = ( // - ML +/* preload: duplicated Model */ +export enum Model { + GGML_CLIP = "ggml-clip", + ONNX_CLIP = "onnx-clip", +} + const computeImageEmbedding = ( model: Model, imageData: Uint8Array, @@ -188,6 +191,24 @@ const computeTextEmbedding = ( ): Promise => ipcRenderer.invoke("computeTextEmbedding", model, text); +// - File selection + +// TODO: Deprecated - use dialogs on the renderer process itself + +const selectDirectory = (): Promise => + ipcRenderer.invoke("selectDirectory"); + +const showUploadFilesDialog = (): Promise => + ipcRenderer.invoke("showUploadFilesDialog"); + +const showUploadDirsDialog = (): Promise => + ipcRenderer.invoke("showUploadDirsDialog"); + +const showUploadZipDialog = (): Promise<{ + zipPaths: string[]; + files: ElectronFile[]; +}> => ipcRenderer.invoke("showUploadZipDialog"); + // - FIXME below this /* preload: duplicated logError */ @@ -344,24 +365,6 @@ const deleteFile = async (filePath: string) => { return fs.rm(filePath); }; -// - ML - -/* preload: duplicated Model */ -export enum Model { - GGML_CLIP = "ggml-clip", - ONNX_CLIP = "onnx-clip", -} - -// - - -const selectDirectory = async (): Promise => { - try { - return await ipcRenderer.invoke("select-dir"); - } catch (e) { - logError(e, "error while selecting root directory"); - } -}; - // - // These objects exposed here will become available to the JS code in our @@ -397,7 +400,7 @@ const selectDirectory = async (): Promise => { // The copy itself is relatively fast, but the problem with transfering large // amounts of data is potentially running out of memory during the copy. contextBridge.exposeInMainWorld("ElectronAPIs", { - // General + // - General appVersion, openDirectory, registerForegroundEventListener, @@ -405,7 +408,7 @@ contextBridge.exposeInMainWorld("ElectronAPIs", { getEncryptionKey, setEncryptionKey, - // Logging + // - Logging openLogDirectory, logToDisk, @@ -424,6 +427,12 @@ contextBridge.exposeInMainWorld("ElectronAPIs", { computeImageEmbedding, computeTextEmbedding, + // - File selection + selectDirectory, + showUploadFilesDialog, + showUploadDirsDialog, + showUploadZipDialog, + // - FS fs: { exists: fsExists, @@ -436,14 +445,10 @@ contextBridge.exposeInMainWorld("ElectronAPIs", { // - Export saveStreamToDisk, saveFileToDisk, - - selectDirectory, readTextFile, - showUploadFilesDialog, - showUploadDirsDialog, + getPendingUploads, setToUploadFiles, - showUploadZipDialog, getElectronFilesFromGoogleZip, setToUploadCollection, getDirFiles, diff --git a/desktop/src/utils/ipcComms.ts b/desktop/src/utils/ipcComms.ts index d203c56f2..bd0c5da44 100644 --- a/desktop/src/utils/ipcComms.ts +++ b/desktop/src/utils/ipcComms.ts @@ -1,8 +1,6 @@ import chokidar from "chokidar"; -import { BrowserWindow, dialog, ipcMain, Tray } from "electron"; -import path from "path"; +import { BrowserWindow, ipcMain, Tray } from "electron"; import { attachIPCHandlers } from "../main/ipc"; -import { getDirFilePaths } from "../services/fs"; export default function setupIpcComs( tray: Tray, @@ -11,43 +9,6 @@ export default function setupIpcComs( ): void { attachIPCHandlers(); - ipcMain.handle("select-dir", async () => { - const result = await dialog.showOpenDialog({ - properties: ["openDirectory"], - }); - if (result.filePaths && result.filePaths.length > 0) { - return result.filePaths[0]?.split(path.sep)?.join(path.posix.sep); - } - }); - - ipcMain.handle("show-upload-files-dialog", async () => { - const files = await dialog.showOpenDialog({ - properties: ["openFile", "multiSelections"], - }); - return files.filePaths; - }); - - ipcMain.handle("show-upload-zip-dialog", async () => { - const files = await dialog.showOpenDialog({ - properties: ["openFile", "multiSelections"], - filters: [{ name: "Zip File", extensions: ["zip"] }], - }); - return files.filePaths; - }); - - ipcMain.handle("show-upload-dirs-dialog", async () => { - const dir = await dialog.showOpenDialog({ - properties: ["openDirectory", "multiSelections"], - }); - - let files: string[] = []; - for (const dirPath of dir.filePaths) { - files = [...files, ...(await getDirFilePaths(dirPath))]; - } - - return files; - }); - ipcMain.handle("add-watcher", async (_, args: { dir: string }) => { watcher.add(args.dir); }); diff --git a/web/packages/shared/electron/types.ts b/web/packages/shared/electron/types.ts index 03ceaf94b..6115e23e5 100644 --- a/web/packages/shared/electron/types.ts +++ b/web/packages/shared/electron/types.ts @@ -123,12 +123,28 @@ export interface ElectronAPIsType { ) => Promise; // - ML + computeImageEmbedding: ( model: Model, imageData: Uint8Array, ) => Promise; + computeTextEmbedding: (model: Model, text: string) => Promise; + // - File selection + // TODO: Deprecated - use dialogs on the renderer process itself + + selectDirectory: () => Promise; + + showUploadFilesDialog: () => Promise; + + showUploadDirsDialog: () => Promise; + + showUploadZipDialog: () => Promise<{ + zipPaths: string[]; + files: ElectronFile[]; + }>; + // - FS legacy checkExistsAndCreateDir: (dirPath: string) => Promise; @@ -138,20 +154,14 @@ export interface ElectronAPIsType { fileStream: ReadableStream, ) => Promise; saveFileToDisk: (path: string, file: any) => Promise; - selectDirectory: () => Promise; readTextFile: (path: string) => Promise; - showUploadFilesDialog: () => Promise; - showUploadDirsDialog: () => Promise; + getPendingUploads: () => Promise<{ files: ElectronFile[]; collectionName: string; type: string; }>; setToUploadFiles: (type: string, filePaths: string[]) => void; - showUploadZipDialog: () => Promise<{ - zipPaths: string[]; - files: ElectronFile[]; - }>; getElectronFilesFromGoogleZip: ( filePath: string, ) => Promise;