From 892bf852a5abe7a245b1a56d3b7b0ffc6d59cf4b Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 25 Mar 2024 15:29:39 +0530 Subject: [PATCH] Convert remaining upload functions --- desktop/src/api/fs.ts | 7 --- desktop/src/main/ipc.ts | 32 +++++++++++++- desktop/src/preload.ts | 43 ++++++++++++++----- desktop/src/services/fs.ts | 6 +++ .../photos/src/components/Upload/Uploader.tsx | 4 +- web/apps/photos/src/services/importService.ts | 18 ++++---- .../src/services/upload/uploadManager.ts | 6 +-- web/packages/shared/electron/types.ts | 14 ++++-- 8 files changed, 95 insertions(+), 35 deletions(-) delete mode 100644 desktop/src/api/fs.ts diff --git a/desktop/src/api/fs.ts b/desktop/src/api/fs.ts deleted file mode 100644 index 5acc5fd48..000000000 --- a/desktop/src/api/fs.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { getDirFilePaths, getElectronFile } from "../services/fs"; - -export async function getDirFiles(dirPath: string) { - const files = await getDirFilePaths(dirPath); - const electronFiles = await Promise.all(files.map(getElectronFile)); - return electronFiles; -} diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index f4798c3c4..725081657 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -10,6 +10,12 @@ import type { FSWatcher } from "chokidar"; import { ipcMain } from "electron/main"; import { clearElectronStore } from "../api/electronStore"; import { getEncryptionKey, setEncryptionKey } from "../api/safeStorage"; +import { + getElectronFilesFromGoogleZip, + getPendingUploads, + setToUploadCollection, + setToUploadFiles, +} from "../api/upload"; import { appVersion, muteUpdateNotification, @@ -21,6 +27,7 @@ import { computeTextEmbedding, } from "../services/clipService"; import { runFFmpegCmd } from "../services/ffmpeg"; +import { getDirFiles } from "../services/fs"; import { convertToJPEG, generateImageThumbnail, @@ -32,7 +39,12 @@ import { updateWatchMappingIgnoredFiles, updateWatchMappingSyncedFiles, } from "../services/watch"; -import type { ElectronFile, Model, WatchMapping } from "../types"; +import type { + ElectronFile, + FILE_PATH_TYPE, + Model, + WatchMapping, +} from "../types"; import { selectDirectory, showUploadDirsDialog, @@ -174,6 +186,24 @@ export const attachIPCHandlers = () => { ipcMain.handle("rename", (_, oldPath: string, newPath: string) => rename(oldPath, newPath), ); + + ipcMain.handle("getPendingUploads", (_) => getPendingUploads()); + + ipcMain.handle( + "setToUploadFiles", + (_, type: FILE_PATH_TYPE, filePaths: string[]) => + setToUploadFiles(type, filePaths), + ); + + ipcMain.handle("getElectronFilesFromGoogleZip", (_, filePath: string) => + getElectronFilesFromGoogleZip(filePath), + ); + + ipcMain.handle("setToUploadCollection", (_, collectionName: string) => + setToUploadCollection(collectionName), + ); + + ipcMain.handle("getDirFiles", (_, dirPath: string) => getDirFiles(dirPath)); }; /** diff --git a/desktop/src/preload.ts b/desktop/src/preload.ts index 2ea1c2bca..2d38539ba 100644 --- a/desktop/src/preload.ts +++ b/desktop/src/preload.ts @@ -27,13 +27,6 @@ */ import { contextBridge, ipcRenderer } from "electron"; -import { getDirFiles } from "./api/fs"; -import { - getElectronFilesFromGoogleZip, - getPendingUploads, - setToUploadCollection, - setToUploadFiles, -} from "./api/upload"; import { setupLogging } from "./main/log"; import type { ElectronFile } from "./types"; @@ -159,7 +152,7 @@ const runFFmpegCmd = ( // - ML /* preload: duplicated Model */ -export enum Model { +enum Model { GGML_CLIP = "ggml-clip", ONNX_CLIP = "onnx-clip", } @@ -236,7 +229,7 @@ interface WatchMappingSyncedFile { } /* preload: duplicated WatchMapping */ -export interface WatchMapping { +interface WatchMapping { rootFolderName: string; uploadStrategy: number; folderPath: string; @@ -290,6 +283,36 @@ const deleteFile = (path: string): Promise => const rename = (oldPath: string, newPath: string): Promise => ipcRenderer.invoke("rename", oldPath, newPath); +// - Upload + +const getPendingUploads = (): Promise<{ + files: ElectronFile[]; + collectionName: string; + type: string; +}> => ipcRenderer.invoke("getPendingUploads"); + +/* preload: duplicated FILE_PATH_TYPE */ +enum FILE_PATH_TYPE { + FILES = "files", + ZIPS = "zips", +} + +const setToUploadFiles = ( + type: FILE_PATH_TYPE, + filePaths: string[], +): Promise => ipcRenderer.invoke("setToUploadFiles", type, filePaths); + +const getElectronFilesFromGoogleZip = ( + filePath: string, +): Promise => + ipcRenderer.invoke("getElectronFilesFromGoogleZip", filePath); + +const setToUploadCollection = (collectionName: string): Promise => + ipcRenderer.invoke("setToUploadCollection", collectionName); + +const getDirFiles = (dirPath: string): Promise => + ipcRenderer.invoke("getDirFiles", dirPath); + // These objects exposed here will become available to the JS code in our // renderer (the web/ code) as `window.ElectronAPIs.*` // @@ -381,7 +404,7 @@ contextBridge.exposeInMainWorld("ElectronAPIs", { deleteFile, rename, - // - Export + // - Upload getPendingUploads, setToUploadFiles, diff --git a/desktop/src/services/fs.ts b/desktop/src/services/fs.ts index 50848d6c1..6e4fff214 100644 --- a/desktop/src/services/fs.ts +++ b/desktop/src/services/fs.ts @@ -7,6 +7,12 @@ import { ElectronFile } from "../types"; const FILE_STREAM_CHUNK_SIZE: number = 4 * 1024 * 1024; +export async function getDirFiles(dirPath: string) { + const files = await getDirFilePaths(dirPath); + const electronFiles = await Promise.all(files.map(getElectronFile)); + return electronFiles; +} + // https://stackoverflow.com/a/63111390 export const getDirFilePaths = async (dirPath: string) => { if (!(await fs.stat(dirPath)).isDirectory()) { diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index 8daeda505..ef91f0670 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -530,13 +530,13 @@ export default function Uploader(props: Props) { ) { await ImportService.setToUploadCollection(collections); if (zipPaths.current) { - ElectronAPIs.setToUploadFiles( + await ElectronAPIs.setToUploadFiles( PICKED_UPLOAD_TYPE.ZIPS, zipPaths.current, ); zipPaths.current = null; } - ElectronAPIs.setToUploadFiles( + await ElectronAPIs.setToUploadFiles( PICKED_UPLOAD_TYPE.FILES, filesWithCollectionToUploadIn.map( ({ file }) => (file as ElectronFile).path, diff --git a/web/apps/photos/src/services/importService.ts b/web/apps/photos/src/services/importService.ts index 2b99686d0..f19e6618c 100644 --- a/web/apps/photos/src/services/importService.ts +++ b/web/apps/photos/src/services/importService.ts @@ -30,20 +30,20 @@ class ImportService { let collectionName: string = null; /* collection being one suggest one of two things 1. Either the user has upload to a single existing collection - 2. Created a new single collection to upload to + 2. Created a new single collection to upload to may have had multiple folder, but chose to upload to one album hence saving the collection name when upload collection count is 1 helps the info of user choosing this options - and on next upload we can directly start uploading to this collection + and on next upload we can directly start uploading to this collection */ if (collections.length === 1) { collectionName = collections[0].name; } - ElectronAPIs.setToUploadCollection(collectionName); + await ElectronAPIs.setToUploadCollection(collectionName); } - updatePendingUploads(files: FileWithCollection[]) { + async updatePendingUploads(files: FileWithCollection[]) { const filePaths = []; for (const fileWithCollection of files) { if (fileWithCollection.isLivePhoto) { @@ -57,13 +57,13 @@ class ImportService { filePaths.push((fileWithCollection.file as ElectronFile).path); } } - ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, filePaths); + await ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, filePaths); } - cancelRemainingUploads() { - ElectronAPIs.setToUploadCollection(null); - ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.ZIPS, []); - ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, []); + async cancelRemainingUploads() { + await ElectronAPIs.setToUploadCollection(null); + await ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.ZIPS, []); + await ElectronAPIs.setToUploadFiles(PICKED_UPLOAD_TYPE.FILES, []); } } diff --git a/web/apps/photos/src/services/upload/uploadManager.ts b/web/apps/photos/src/services/upload/uploadManager.ts index 734ae7bcb..321b78990 100644 --- a/web/apps/photos/src/services/upload/uploadManager.ts +++ b/web/apps/photos/src/services/upload/uploadManager.ts @@ -180,7 +180,7 @@ class UploadManager { if (e.message === CustomError.UPLOAD_CANCELLED) { if (isElectron()) { this.remainingFiles = []; - ImportService.cancelRemainingUploads(); + await ImportService.cancelRemainingUploads(); } } else { logError(e, "uploading failed with error"); @@ -326,7 +326,7 @@ class UploadManager { addLogLine( `post upload action -> fileUploadResult: ${fileUploadResult} uploadedFile present ${!!uploadedFile}`, ); - this.updateElectronRemainingFiles(fileWithCollection); + await this.updateElectronRemainingFiles(fileWithCollection); switch (fileUploadResult) { case UPLOAD_RESULT.FAILED: case UPLOAD_RESULT.BLOCKED: @@ -434,7 +434,7 @@ class UploadManager { this.remainingFiles = this.remainingFiles.filter( (file) => !areFileWithCollectionsSame(file, fileWithCollection), ); - ImportService.updatePendingUploads(this.remainingFiles); + await ImportService.updatePendingUploads(this.remainingFiles); } } diff --git a/web/packages/shared/electron/types.ts b/web/packages/shared/electron/types.ts index 0949c18ba..d1ab9ed8a 100644 --- a/web/packages/shared/electron/types.ts +++ b/web/packages/shared/electron/types.ts @@ -11,6 +11,11 @@ export enum Model { ONNX_CLIP = "onnx-clip", } +export enum FILE_PATH_TYPE { + FILES = "files", + ZIPS = "zips", +} + /** * Extra APIs provided by the Node.js layer when our code is running in Electron * @@ -192,17 +197,20 @@ export interface ElectronAPIsType { deleteFile: (path: string) => Promise; rename: (oldPath: string, newPath: string) => Promise; - /** TODO: FIXME or migrate below this */ + // - Upload getPendingUploads: () => Promise<{ files: ElectronFile[]; collectionName: string; type: string; }>; - setToUploadFiles: (type: string, filePaths: string[]) => void; + setToUploadFiles: ( + type: FILE_PATH_TYPE, + filePaths: string[], + ) => Promise; getElectronFilesFromGoogleZip: ( filePath: string, ) => Promise; - setToUploadCollection: (collectionName: string) => void; + setToUploadCollection: (collectionName: string) => Promise; getDirFiles: (dirPath: string) => Promise; }