Parcourir la source

Electron side

Manav Rathi il y a 1 an
Parent
commit
176431ba1f

+ 10 - 2
desktop/src/main.ts

@@ -17,7 +17,11 @@ import { existsSync } from "node:fs";
 import fs from "node:fs/promises";
 import os from "node:os";
 import path from "node:path";
-import { attachFSWatchIPCHandlers, attachIPCHandlers } from "./main/ipc";
+import {
+    attachFSWatchIPCHandlers,
+    attachIPCHandlers,
+    attachLogoutIPCHandler,
+} from "./main/ipc";
 import log, { initLogging } from "./main/log";
 import { createApplicationMenu, createTrayContextMenu } from "./main/menu";
 import { setupAutoUpdater } from "./main/services/app-update";
@@ -377,8 +381,12 @@ const main = () => {
         void (async () => {
             // Create window and prepare for the renderer.
             mainWindow = createMainWindow();
+
+            // Setup IPC and streams.
+            const watcher = createWatcher(mainWindow);
             attachIPCHandlers();
-            attachFSWatchIPCHandlers(createWatcher(mainWindow));
+            attachFSWatchIPCHandlers(watcher);
+            attachLogoutIPCHandler(watcher);
             registerStreamProtocol();
 
             // Configure the renderer's environment.

+ 9 - 12
desktop/src/main/ipc.ts

@@ -41,16 +41,13 @@ import {
     fsWriteFile,
 } from "./services/fs";
 import { convertToJPEG, generateImageThumbnail } from "./services/image";
+import { logout } from "./services/logout";
 import {
     clipImageEmbedding,
     clipTextEmbeddingIfAvailable,
 } from "./services/ml-clip";
 import { detectFaces, faceEmbedding } from "./services/ml-face";
-import {
-    clearStores,
-    encryptionKey,
-    saveEncryptionKey,
-} from "./services/store";
+import { encryptionKey, saveEncryptionKey } from "./services/store";
 import {
     clearPendingUploads,
     listZipItems,
@@ -65,11 +62,9 @@ import {
     watchFindFiles,
     watchGet,
     watchRemove,
-    watchReset,
     watchUpdateIgnoredFiles,
     watchUpdateSyncedFiles,
 } from "./services/watch";
-import { clearConvertToMP4Results } from "./stream";
 
 /**
  * Listen for IPC events sent/invoked by the renderer process, and route them to
@@ -107,10 +102,6 @@ export const attachIPCHandlers = () => {
 
     ipcMain.handle("selectDirectory", () => selectDirectory());
 
-    ipcMain.on("clearStores", () => clearStores());
-
-    ipcMain.on("clearConvertToMP4Results", () => clearConvertToMP4Results());
-
     ipcMain.handle("saveEncryptionKey", (_, encryptionKey: string) =>
         saveEncryptionKey(encryptionKey),
     );
@@ -265,6 +256,12 @@ export const attachFSWatchIPCHandlers = (watcher: FSWatcher) => {
     ipcMain.handle("watchFindFiles", (_, folderPath: string) =>
         watchFindFiles(folderPath),
     );
+};
 
-    ipcMain.handle("watchReset", () => watchReset(watcher));
+/**
+ * Sibling of {@link attachIPCHandlers} specifically for use with the logout
+ * event with needs access to the {@link FSWatcher} instance.
+ */
+export const attachLogoutIPCHandler = (watcher: FSWatcher) => {
+    ipcMain.handle("logout", () => logout(watcher));
 };

+ 30 - 0
desktop/src/main/services/logout.ts

@@ -0,0 +1,30 @@
+import type { FSWatcher } from "chokidar";
+import log from "../log";
+import { clearConvertToMP4Results } from "../stream";
+import { clearStores } from "./store";
+import { watchReset } from "./watch";
+
+/**
+ * Perform the native side logout sequence.
+ *
+ * This function is guaranteed not to throw any errors.
+ *
+ * See: [Note: Do not throw during logout].
+ */
+export const logout = (watcher: FSWatcher) => {
+    try {
+        watchReset(watcher);
+    } catch (e) {
+        log.error("Ignoring error when resetting native folder watches", e);
+    }
+    try {
+        clearConvertToMP4Results();
+    } catch (e) {
+        log.error("Ignoring error when clearing convert-to-mp4 results", e);
+    }
+    try {
+        clearStores();
+    } catch (e) {
+        log.error("Ignoring error when clearing native stores", e);
+    }
+}

+ 9 - 0
desktop/src/main/services/watch.ts

@@ -151,6 +151,15 @@ export const watchFindFiles = async (dirPath: string) => {
     return paths;
 };
 
+/**
+ * Stop watching all existing folder watches and remove any callbacks.
+ *
+ * This function is meant to be called when the user logs out. It stops
+ * all existing folder watches and forgets about any "on*" callback
+ * functions that have been registered.
+ *
+ * The persisted state itself gets cleared via {@link clearStores}.
+ */
 export const watchReset = (watcher: FSWatcher) => {
     watcher.unwatch(folderWatches().map((watch) => watch.folderPath));
 };

+ 6 - 9
desktop/src/preload.ts

@@ -63,10 +63,10 @@ const openLogDirectory = () => ipcRenderer.invoke("openLogDirectory");
 
 const selectDirectory = () => ipcRenderer.invoke("selectDirectory");
 
-const clearStores = () => ipcRenderer.send("clearStores");
-
-const clearConvertToMP4Results = () =>
-    ipcRenderer.send("clearConvertToMP4Results");
+const logout = () => {
+    watchRemoveListeners();
+    ipcRenderer.send("logout");
+};
 
 const encryptionKey = () => ipcRenderer.invoke("encryptionKey");
 
@@ -212,11 +212,10 @@ const watchOnRemoveDir = (f: (path: string, watch: FolderWatch) => void) => {
 const watchFindFiles = (folderPath: string) =>
     ipcRenderer.invoke("watchFindFiles", folderPath);
 
-const watchReset = async () => {
+const watchRemoveListeners = () => {
     ipcRenderer.removeAllListeners("watchAddFile");
     ipcRenderer.removeAllListeners("watchRemoveFile");
     ipcRenderer.removeAllListeners("watchRemoveDir");
-    await ipcRenderer.invoke("watchReset");
 };
 
 // - Upload
@@ -308,8 +307,7 @@ contextBridge.exposeInMainWorld("electron", {
     openDirectory,
     openLogDirectory,
     selectDirectory,
-    clearStores,
-    clearConvertToMP4Results,
+    logout,
     encryptionKey,
     saveEncryptionKey,
     onMainWindowFocus,
@@ -360,7 +358,6 @@ contextBridge.exposeInMainWorld("electron", {
         onRemoveFile: watchOnRemoveFile,
         onRemoveDir: watchOnRemoveDir,
         findFiles: watchFindFiles,
-        reset: watchReset,
     },
 
     // - Upload

+ 1 - 1
web/apps/photos/src/pages/_app.tsx

@@ -101,7 +101,7 @@ type AppContextType = {
     setDialogBoxAttributesV2: SetDialogBoxAttributesV2;
     isCFProxyDisabled: boolean;
     setIsCFProxyDisabled: (disabled: boolean) => void;
-    logout: () => Promise<void>;
+    logout: () => void;
 };
 
 export const AppContext = createContext<AppContextType>(null);

+ 2 - 12
web/apps/photos/src/services/logout.ts

@@ -15,19 +15,9 @@ export const photosLogout = async () => {
     const electron = globalThis.electron;
     if (electron) {
         try {
-            await electron.watch.reset();
+            await electron?.logout();
         } catch (e) {
-            log.error("Ignoring error when resetting native folder watches", e);
-        }
-        try {
-            await electron.clearConvertToMP4Results();
-        } catch (e) {
-            log.error("Ignoring error when clearing convert-to-mp4 results", e);
-        }
-        try {
-            await electron.clearStores();
-        } catch (e) {
-            log.error("Ignoring error when clearing native stores", e);
+            log.error("Ignoring error in native side logout sequence", e);
         }
     }
     try {

+ 2 - 23
web/packages/next/types/ipc.ts

@@ -64,19 +64,9 @@ export interface Electron {
     selectDirectory: () => Promise<string | undefined>;
 
     /**
-     * Clear any stored data.
-     *
-     * This is a coarse single shot cleanup, meant for use in clearing any
-     * persisted Electron side state during logout.
-     */
-    clearStores: () => Promise<void>;
-
-    /**
-     * Clear an state corresponding to in-flight convert-to-mp4 requests.
-     *
-     * This is meant for use during logout.
+     * Perform any logout related cleanup of native side state.
      */
-    clearConvertToMP4Results: () => Promise<void>;
+    logout: () => Promise<void>;
 
     /**
      * Return the previously saved encryption key from persistent safe storage.
@@ -487,17 +477,6 @@ export interface Electron {
          * The returned paths are guaranteed to use POSIX separators ('/').
          */
         findFiles: (folderPath: string) => Promise<string[]>;
-
-        /**
-         * Stop watching all existing folder watches and remove any callbacks.
-         *
-         * This function is meant to be called when the user logs out. It stops
-         * all existing folder watches and forgets about any "on*" callback
-         * functions that have been registered.
-         *
-         * The persisted state itself gets cleared via {@link clearStores}.
-         */
-        reset: () => Promise<void>;
     };
 
     // - Upload