diff --git a/core/src/node/api/processors/fsExt.ts b/core/src/node/api/processors/fsExt.ts index 155732cfce..5ddd26a781 100644 --- a/core/src/node/api/processors/fsExt.ts +++ b/core/src/node/api/processors/fsExt.ts @@ -1,7 +1,7 @@ import { join } from 'path' import fs from 'fs' import { appResourcePath, normalizeFilePath, validatePath } from '../../helper/path' -import { getJanDataFolderPath, getJanDataFolderPath as getPath } from '../../helper' +import { defaultAppConfig, getJanDataFolderPath, getJanDataFolderPath as getPath } from '../../helper' import { Processor } from './Processor' import { FileStat } from '../../../types' @@ -28,9 +28,10 @@ export class FSExt implements Processor { return appResourcePath() } - // Handles the 'getUserHomePath' IPC event. This event is triggered to get the user home path. + // Handles the 'getUserHomePath' IPC event. This event is triggered to get the user app data path. + // CAUTION: This would not return OS home path but the app data path. getUserHomePath() { - return process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME'] + return defaultAppConfig().data_folder } // handle fs is directory here diff --git a/core/src/node/helper/config.ts b/core/src/node/helper/config.ts index 0d14280ccf..8bf48d629c 100644 --- a/core/src/node/helper/config.ts +++ b/core/src/node/helper/config.ts @@ -3,27 +3,16 @@ import { join, resolve } from 'path' import fs from 'fs' import os from 'os' import childProcess from 'child_process' - const configurationFileName = 'settings.json' -// TODO: do no specify app name in framework module -// TODO: do not default the os.homedir -const defaultJanDataFolder = join(os?.homedir() || '', 'jan') -const defaultAppConfig: AppConfiguration = { - data_folder: - process.env.CI === 'e2e' - ? process.env.APP_CONFIG_PATH ?? resolve('./test-data') - : defaultJanDataFolder, - quick_ask: false, -} - /** * Getting App Configurations. * * @returns {AppConfiguration} The app configurations. */ export const getAppConfigurations = (): AppConfiguration => { - if (process.env.CI === 'e2e') return defaultAppConfig + const appDefaultConfiguration = defaultAppConfig() + if (process.env.CI === 'e2e') return appDefaultConfiguration // Retrieve Application Support folder path // Fallback to user home directory if not found const configurationFile = getConfigurationFilePath() @@ -31,8 +20,8 @@ export const getAppConfigurations = (): AppConfiguration => { if (!fs.existsSync(configurationFile)) { // create default app config if we don't have one console.debug(`App config not found, creating default config at ${configurationFile}`) - fs.writeFileSync(configurationFile, JSON.stringify(defaultAppConfig)) - return defaultAppConfig + fs.writeFileSync(configurationFile, JSON.stringify(appDefaultConfiguration)) + return appDefaultConfiguration } try { @@ -42,7 +31,7 @@ export const getAppConfigurations = (): AppConfiguration => { return appConfigurations } catch (err) { console.error(`Failed to read app config, return default config instead! Err: ${err}`) - return defaultAppConfig + return defaultAppConfig() } } @@ -159,3 +148,22 @@ export const getEngineConfiguration = async (engineId: string) => { full_url: fullUrl, } } + +/** + * Default app configurations + * App Data Folder default to Electron's userData + * %APPDATA% on Windows + * $XDG_CONFIG_HOME or ~/.config on Linux + * ~/Library/Application Support on macOS + */ +export const defaultAppConfig = (): AppConfiguration => { + const { app } = require('electron') + const defaultJanDataFolder = join(app?.getPath('userData') ?? os?.homedir() ?? '', 'data') + return { + data_folder: + process.env.CI === 'e2e' + ? (process.env.APP_CONFIG_PATH ?? resolve('./test-data')) + : defaultJanDataFolder, + quick_ask: false, + } +} diff --git a/web/app/search/layout.tsx b/web/app/search/layout.tsx index dedbe22f53..b87c9da727 100644 --- a/web/app/search/layout.tsx +++ b/web/app/search/layout.tsx @@ -38,8 +38,7 @@ export default function RootLayout() { useEffect(() => { async function getDefaultJanDataFolder() { - const homePath = await getUserHomePath() - const defaultJanDataFolder = await joinPath([homePath, 'jan']) + const defaultJanDataFolder = await getUserHomePath() setJanDefaultDataFolder(defaultJanDataFolder) } diff --git a/web/containers/Providers/DataLoader.tsx b/web/containers/Providers/DataLoader.tsx index 269d2f8770..d8dce12027 100644 --- a/web/containers/Providers/DataLoader.tsx +++ b/web/containers/Providers/DataLoader.tsx @@ -47,8 +47,7 @@ const DataLoader: React.FC = ({ children }) => { useEffect(() => { async function getDefaultJanDataFolder() { - const homePath = await getUserHomePath() - const defaultJanDataFolder = await joinPath([homePath, 'jan']) + const defaultJanDataFolder = await getUserHomePath() setJanDefaultDataFolder(defaultJanDataFolder) } diff --git a/web/hooks/useFactoryReset.ts b/web/hooks/useFactoryReset.ts index 8364ca10d9..a8e3efb9ab 100644 --- a/web/hooks/useFactoryReset.ts +++ b/web/hooks/useFactoryReset.ts @@ -34,7 +34,16 @@ export default function useFactoryReset() { } const janDataFolderPath = appConfiguration!.data_folder + // 1: Stop running model + setFactoryResetState(FactoryResetState.StoppingModel) + await stopModel() + await new Promise((resolve) => setTimeout(resolve, 4000)) + // 2: Delete the old jan data folder + setFactoryResetState(FactoryResetState.DeletingData) + await fs.rm(janDataFolderPath) + + // 3: Set the default jan data folder if (!keepCurrentFolder) { // set the default jan data folder to user's home directory const configuration: AppConfiguration = { @@ -44,17 +53,12 @@ export default function useFactoryReset() { await window.core?.api?.updateAppConfiguration(configuration) } - setFactoryResetState(FactoryResetState.StoppingModel) - await stopModel() - await new Promise((resolve) => setTimeout(resolve, 4000)) - - setFactoryResetState(FactoryResetState.DeletingData) - await fs.rm(janDataFolderPath) - + // 4: Clear app local storage setFactoryResetState(FactoryResetState.ClearLocalStorage) // reset the localStorage localStorage.clear() + // 5: Relaunch the app await window.core?.api?.relaunch() }, [defaultJanDataFolder, stopModel, setFactoryResetState]