Electron side
This commit is contained in:
parent
96cd6b3759
commit
176431ba1f
|
@ -17,7 +17,11 @@ import { existsSync } from "node:fs";
|
||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
import os from "node:os";
|
import os from "node:os";
|
||||||
import path from "node:path";
|
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 log, { initLogging } from "./main/log";
|
||||||
import { createApplicationMenu, createTrayContextMenu } from "./main/menu";
|
import { createApplicationMenu, createTrayContextMenu } from "./main/menu";
|
||||||
import { setupAutoUpdater } from "./main/services/app-update";
|
import { setupAutoUpdater } from "./main/services/app-update";
|
||||||
|
@ -377,8 +381,12 @@ const main = () => {
|
||||||
void (async () => {
|
void (async () => {
|
||||||
// Create window and prepare for the renderer.
|
// Create window and prepare for the renderer.
|
||||||
mainWindow = createMainWindow();
|
mainWindow = createMainWindow();
|
||||||
|
|
||||||
|
// Setup IPC and streams.
|
||||||
|
const watcher = createWatcher(mainWindow);
|
||||||
attachIPCHandlers();
|
attachIPCHandlers();
|
||||||
attachFSWatchIPCHandlers(createWatcher(mainWindow));
|
attachFSWatchIPCHandlers(watcher);
|
||||||
|
attachLogoutIPCHandler(watcher);
|
||||||
registerStreamProtocol();
|
registerStreamProtocol();
|
||||||
|
|
||||||
// Configure the renderer's environment.
|
// Configure the renderer's environment.
|
||||||
|
|
|
@ -41,16 +41,13 @@ import {
|
||||||
fsWriteFile,
|
fsWriteFile,
|
||||||
} from "./services/fs";
|
} from "./services/fs";
|
||||||
import { convertToJPEG, generateImageThumbnail } from "./services/image";
|
import { convertToJPEG, generateImageThumbnail } from "./services/image";
|
||||||
|
import { logout } from "./services/logout";
|
||||||
import {
|
import {
|
||||||
clipImageEmbedding,
|
clipImageEmbedding,
|
||||||
clipTextEmbeddingIfAvailable,
|
clipTextEmbeddingIfAvailable,
|
||||||
} from "./services/ml-clip";
|
} from "./services/ml-clip";
|
||||||
import { detectFaces, faceEmbedding } from "./services/ml-face";
|
import { detectFaces, faceEmbedding } from "./services/ml-face";
|
||||||
import {
|
import { encryptionKey, saveEncryptionKey } from "./services/store";
|
||||||
clearStores,
|
|
||||||
encryptionKey,
|
|
||||||
saveEncryptionKey,
|
|
||||||
} from "./services/store";
|
|
||||||
import {
|
import {
|
||||||
clearPendingUploads,
|
clearPendingUploads,
|
||||||
listZipItems,
|
listZipItems,
|
||||||
|
@ -65,11 +62,9 @@ import {
|
||||||
watchFindFiles,
|
watchFindFiles,
|
||||||
watchGet,
|
watchGet,
|
||||||
watchRemove,
|
watchRemove,
|
||||||
watchReset,
|
|
||||||
watchUpdateIgnoredFiles,
|
watchUpdateIgnoredFiles,
|
||||||
watchUpdateSyncedFiles,
|
watchUpdateSyncedFiles,
|
||||||
} from "./services/watch";
|
} from "./services/watch";
|
||||||
import { clearConvertToMP4Results } from "./stream";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for IPC events sent/invoked by the renderer process, and route them to
|
* 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.handle("selectDirectory", () => selectDirectory());
|
||||||
|
|
||||||
ipcMain.on("clearStores", () => clearStores());
|
|
||||||
|
|
||||||
ipcMain.on("clearConvertToMP4Results", () => clearConvertToMP4Results());
|
|
||||||
|
|
||||||
ipcMain.handle("saveEncryptionKey", (_, encryptionKey: string) =>
|
ipcMain.handle("saveEncryptionKey", (_, encryptionKey: string) =>
|
||||||
saveEncryptionKey(encryptionKey),
|
saveEncryptionKey(encryptionKey),
|
||||||
);
|
);
|
||||||
|
@ -265,6 +256,12 @@ export const attachFSWatchIPCHandlers = (watcher: FSWatcher) => {
|
||||||
ipcMain.handle("watchFindFiles", (_, folderPath: string) =>
|
ipcMain.handle("watchFindFiles", (_, folderPath: string) =>
|
||||||
watchFindFiles(folderPath),
|
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
desktop/src/main/services/logout.ts
Normal file
30
desktop/src/main/services/logout.ts
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -151,6 +151,15 @@ export const watchFindFiles = async (dirPath: string) => {
|
||||||
return paths;
|
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) => {
|
export const watchReset = (watcher: FSWatcher) => {
|
||||||
watcher.unwatch(folderWatches().map((watch) => watch.folderPath));
|
watcher.unwatch(folderWatches().map((watch) => watch.folderPath));
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,10 +63,10 @@ const openLogDirectory = () => ipcRenderer.invoke("openLogDirectory");
|
||||||
|
|
||||||
const selectDirectory = () => ipcRenderer.invoke("selectDirectory");
|
const selectDirectory = () => ipcRenderer.invoke("selectDirectory");
|
||||||
|
|
||||||
const clearStores = () => ipcRenderer.send("clearStores");
|
const logout = () => {
|
||||||
|
watchRemoveListeners();
|
||||||
const clearConvertToMP4Results = () =>
|
ipcRenderer.send("logout");
|
||||||
ipcRenderer.send("clearConvertToMP4Results");
|
};
|
||||||
|
|
||||||
const encryptionKey = () => ipcRenderer.invoke("encryptionKey");
|
const encryptionKey = () => ipcRenderer.invoke("encryptionKey");
|
||||||
|
|
||||||
|
@ -212,11 +212,10 @@ const watchOnRemoveDir = (f: (path: string, watch: FolderWatch) => void) => {
|
||||||
const watchFindFiles = (folderPath: string) =>
|
const watchFindFiles = (folderPath: string) =>
|
||||||
ipcRenderer.invoke("watchFindFiles", folderPath);
|
ipcRenderer.invoke("watchFindFiles", folderPath);
|
||||||
|
|
||||||
const watchReset = async () => {
|
const watchRemoveListeners = () => {
|
||||||
ipcRenderer.removeAllListeners("watchAddFile");
|
ipcRenderer.removeAllListeners("watchAddFile");
|
||||||
ipcRenderer.removeAllListeners("watchRemoveFile");
|
ipcRenderer.removeAllListeners("watchRemoveFile");
|
||||||
ipcRenderer.removeAllListeners("watchRemoveDir");
|
ipcRenderer.removeAllListeners("watchRemoveDir");
|
||||||
await ipcRenderer.invoke("watchReset");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// - Upload
|
// - Upload
|
||||||
|
@ -308,8 +307,7 @@ contextBridge.exposeInMainWorld("electron", {
|
||||||
openDirectory,
|
openDirectory,
|
||||||
openLogDirectory,
|
openLogDirectory,
|
||||||
selectDirectory,
|
selectDirectory,
|
||||||
clearStores,
|
logout,
|
||||||
clearConvertToMP4Results,
|
|
||||||
encryptionKey,
|
encryptionKey,
|
||||||
saveEncryptionKey,
|
saveEncryptionKey,
|
||||||
onMainWindowFocus,
|
onMainWindowFocus,
|
||||||
|
@ -360,7 +358,6 @@ contextBridge.exposeInMainWorld("electron", {
|
||||||
onRemoveFile: watchOnRemoveFile,
|
onRemoveFile: watchOnRemoveFile,
|
||||||
onRemoveDir: watchOnRemoveDir,
|
onRemoveDir: watchOnRemoveDir,
|
||||||
findFiles: watchFindFiles,
|
findFiles: watchFindFiles,
|
||||||
reset: watchReset,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// - Upload
|
// - Upload
|
||||||
|
|
|
@ -101,7 +101,7 @@ type AppContextType = {
|
||||||
setDialogBoxAttributesV2: SetDialogBoxAttributesV2;
|
setDialogBoxAttributesV2: SetDialogBoxAttributesV2;
|
||||||
isCFProxyDisabled: boolean;
|
isCFProxyDisabled: boolean;
|
||||||
setIsCFProxyDisabled: (disabled: boolean) => void;
|
setIsCFProxyDisabled: (disabled: boolean) => void;
|
||||||
logout: () => Promise<void>;
|
logout: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppContext = createContext<AppContextType>(null);
|
export const AppContext = createContext<AppContextType>(null);
|
||||||
|
|
|
@ -15,19 +15,9 @@ export const photosLogout = async () => {
|
||||||
const electron = globalThis.electron;
|
const electron = globalThis.electron;
|
||||||
if (electron) {
|
if (electron) {
|
||||||
try {
|
try {
|
||||||
await electron.watch.reset();
|
await electron?.logout();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error("Ignoring error when resetting native folder watches", e);
|
log.error("Ignoring error in native side logout sequence", 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -64,19 +64,9 @@ export interface Electron {
|
||||||
selectDirectory: () => Promise<string | undefined>;
|
selectDirectory: () => Promise<string | undefined>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear any stored data.
|
* Perform any logout related cleanup of native side state.
|
||||||
*
|
|
||||||
* This is a coarse single shot cleanup, meant for use in clearing any
|
|
||||||
* persisted Electron side state during logout.
|
|
||||||
*/
|
*/
|
||||||
clearStores: () => Promise<void>;
|
logout: () => Promise<void>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear an state corresponding to in-flight convert-to-mp4 requests.
|
|
||||||
*
|
|
||||||
* This is meant for use during logout.
|
|
||||||
*/
|
|
||||||
clearConvertToMP4Results: () => Promise<void>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the previously saved encryption key from persistent safe storage.
|
* 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 ('/').
|
* The returned paths are guaranteed to use POSIX separators ('/').
|
||||||
*/
|
*/
|
||||||
findFiles: (folderPath: string) => Promise<string[]>;
|
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
|
// - Upload
|
||||||
|
|
Loading…
Reference in a new issue