From 873dd41460557457aeb9ca8990cde103f4b359c9 Mon Sep 17 00:00:00 2001 From: Louis Date: Wed, 27 Nov 2024 15:27:59 +0700 Subject: [PATCH] fix: 4098 - factory reset closes the app & never opens again on Linux --- core/src/types/api/index.ts | 1 + electron/handlers/native.ts | 77 ++++++++++++++++++++++++++++++++++++ electron/utils/migration.ts | 1 - web/hooks/useFactoryReset.ts | 6 ++- 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/core/src/types/api/index.ts b/core/src/types/api/index.ts index b8bf273a7..dc9afcb00 100644 --- a/core/src/types/api/index.ts +++ b/core/src/types/api/index.ts @@ -27,6 +27,7 @@ export enum NativeRoute { quickAskSizeUpdated = 'quickAskSizeUpdated', ackDeepLink = 'ackDeepLink', + factoryReset = 'factoryReset' } /** diff --git a/electron/handlers/native.ts b/electron/handlers/native.ts index 869b9fd58..813231bd4 100644 --- a/electron/handlers/native.ts +++ b/electron/handlers/native.ts @@ -12,6 +12,9 @@ import { } from '@janhq/core/node' import { SelectFileOption } from '@janhq/core' import { menu } from '../utils/menu' +import { migrate } from '../utils/migration' +import { createUserSpace } from '../utils/path' +import { setupExtensions } from '../utils/extension' const isMac = process.platform === 'darwin' @@ -33,14 +36,28 @@ export function handleAppIPCs() { nativeTheme.themeSource = 'light' }) + /** + * Handles the "setCloseApp" IPC message by closing the main application window. + * This effectively closes the application if no other windows are open. + */ ipcMain.handle(NativeRoute.setCloseApp, () => { windowManager.mainWindow?.close() }) + /** + * Handles the "setMinimizeApp" IPC message by minimizing the main application window. + * The window will be minimized to the system's taskbar or dock. + */ ipcMain.handle(NativeRoute.setMinimizeApp, () => { windowManager.mainWindow?.minimize() }) + /** + * Handles the "setMaximizeApp" IPC message. It toggles the maximization state of the main window. + * If the window is currently maximized, it will be un-maximized (restored to its previous size). + * If the window is not maximized, it will be maximized to fill the screen. + * @param _event - The IPC event object. + */ ipcMain.handle(NativeRoute.setMaximizeApp, async (_event) => { if (windowManager.mainWindow?.isMaximized()) { windowManager.mainWindow.unmaximize() @@ -104,6 +121,11 @@ export function handleAppIPCs() { } }) + /** + * Handles the "selectDirectory" IPC message to open a dialog for selecting a directory. + * If no main window is found, logs an error and exits. + * @returns {string} The path of the selected directory, or nothing if canceled. + */ ipcMain.handle(NativeRoute.selectDirectory, async () => { const mainWindow = windowManager.mainWindow if (!mainWindow) { @@ -122,6 +144,14 @@ export function handleAppIPCs() { } }) + /** + * Handles the "selectFiles" IPC message to open a dialog for selecting files. + * Allows options for setting the dialog title, button label, and selection properties. + * Logs an error if no main window is found. + * @param _event - The IPC event object. + * @param option - Options for customizing file selection dialog. + * @returns {string[]} An array of selected file paths, or nothing if canceled. + */ ipcMain.handle( NativeRoute.selectFiles, async (_event, option?: SelectFileOption) => { @@ -156,11 +186,20 @@ export function handleAppIPCs() { } ) + /** + * Handles the "hideQuickAskWindow" IPC message to hide the quick ask window. + * @returns A promise that resolves when the window is hidden. + */ ipcMain.handle( NativeRoute.hideQuickAskWindow, async (): Promise => windowManager.hideQuickAskWindow() ) + /** + * Handles the "sendQuickAskInput" IPC message to send user input to the main window. + * @param _event - The IPC event object. + * @param input - User input string to be sent. + */ ipcMain.handle( NativeRoute.sendQuickAskInput, async (_event, input: string): Promise => { @@ -171,6 +210,12 @@ export function handleAppIPCs() { } ) + /** + * Handles the "showOpenMenu" IPC message to show the context menu at given coordinates. + * Only applicable on non-Mac platforms. + * @param e - The event object. + * @param args - Contains coordinates where the menu should appear. + */ ipcMain.handle(NativeRoute.showOpenMenu, function (e, args) { if (!isMac && windowManager.mainWindow) { menu.popup({ @@ -181,23 +226,55 @@ export function handleAppIPCs() { } }) + /** + * Handles the "hideMainWindow" IPC message to hide the main application window. + * @returns A promise that resolves when the window is hidden. + */ ipcMain.handle( NativeRoute.hideMainWindow, async (): Promise => windowManager.hideMainWindow() ) + /** + * Handles the "showMainWindow" IPC message to show the main application window. + * @returns A promise that resolves when the window is shown. + */ ipcMain.handle( NativeRoute.showMainWindow, async (): Promise => windowManager.showMainWindow() ) + /** + * Handles the "quickAskSizeUpdated" IPC message to update the size of the quick ask window. + * Resizes window by the given height offset. + * @param _event - The IPC event object. + * @param heightOffset - The amount of height to increase. + * @returns A promise that resolves when the window is resized. + */ ipcMain.handle( NativeRoute.quickAskSizeUpdated, async (_event, heightOffset: number): Promise => windowManager.expandQuickAskWindow(heightOffset) ) + /** + * Handles the "ackDeepLink" IPC message to acknowledge a deep link. + * Triggers handling of deep link in the application. + * @param _event - The IPC event object. + * @returns A promise that resolves when the deep link is acknowledged. + */ ipcMain.handle(NativeRoute.ackDeepLink, async (_event): Promise => { windowManager.ackDeepLink() }) + + /** + * Handles the "factoryReset" IPC message to reset the application to its initial state. + * Clears loaded modules, recreates user space, runs migrations, and sets up extensions. + * @param _event - The IPC event object. + * @returns A promise that resolves after the reset operations are complete. + */ + ipcMain.handle(NativeRoute.factoryReset, async (_event): Promise => { + ModuleManager.instance.clearImportedModules() + return createUserSpace().then(migrate).then(setupExtensions) + }) } diff --git a/electron/utils/migration.ts b/electron/utils/migration.ts index 80851f9de..505de0f7b 100644 --- a/electron/utils/migration.ts +++ b/electron/utils/migration.ts @@ -3,7 +3,6 @@ import { app } from 'electron' import { join } from 'path' import { rmdirSync, - readFileSync, existsSync, mkdirSync, readdirSync, diff --git a/web/hooks/useFactoryReset.ts b/web/hooks/useFactoryReset.ts index f68a6fd8c..da2e15b03 100644 --- a/web/hooks/useFactoryReset.ts +++ b/web/hooks/useFactoryReset.ts @@ -62,13 +62,17 @@ export default function useFactoryReset() { await window.core?.api?.updateAppConfiguration(configuration) } + // Perform factory reset + await window.core?.api?.factoryReset() + // 4: Clear app local storage setFactoryResetState(FactoryResetState.ClearLocalStorage) // reset the localStorage localStorage.clear() + window.core = undefined // 5: Relaunch the app - await window.core?.api?.relaunch() + window.location.reload() }, [defaultJanDataFolder, stopModel, setFactoryResetState] )