feat: add factory reset feature (#1750)
* feat(FactoryReset): add factory reset feature Signed-off-by: nam <namnh0122@gmail.com> Signed-off-by: James <james@jan.ai> Co-authored-by: Faisal Amir <urmauur@gmail.com> Co-authored-by: James <james@jan.ai>
This commit is contained in:
parent
5e58f67abd
commit
8151ef0313
@ -3,7 +3,6 @@
|
|||||||
* @description Enum of all the routes exposed by the app
|
* @description Enum of all the routes exposed by the app
|
||||||
*/
|
*/
|
||||||
export enum AppRoute {
|
export enum AppRoute {
|
||||||
appDataPath = 'appDataPath',
|
|
||||||
openExternalUrl = 'openExternalUrl',
|
openExternalUrl = 'openExternalUrl',
|
||||||
openAppDirectory = 'openAppDirectory',
|
openAppDirectory = 'openAppDirectory',
|
||||||
openFileExplore = 'openFileExplorer',
|
openFileExplore = 'openFileExplorer',
|
||||||
@ -62,6 +61,7 @@ export enum FileManagerRoute {
|
|||||||
syncFile = 'syncFile',
|
syncFile = 'syncFile',
|
||||||
getJanDataFolderPath = 'getJanDataFolderPath',
|
getJanDataFolderPath = 'getJanDataFolderPath',
|
||||||
getResourcePath = 'getResourcePath',
|
getResourcePath = 'getResourcePath',
|
||||||
|
getUserHomePath = 'getUserHomePath',
|
||||||
fileStat = 'fileStat',
|
fileStat = 'fileStat',
|
||||||
writeBlob = 'writeBlob',
|
writeBlob = 'writeBlob',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,12 @@ const openExternalUrl: (url: string) => Promise<any> = (url) =>
|
|||||||
*/
|
*/
|
||||||
const getResourcePath: () => Promise<string> = () => global.core.api?.getResourcePath()
|
const getResourcePath: () => Promise<string> = () => global.core.api?.getResourcePath()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user's home path.
|
||||||
|
* @returns return user's home path
|
||||||
|
*/
|
||||||
|
const getUserHomePath = (): Promise<string> => global.core.api?.getUserHomePath()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log to file from browser processes.
|
* Log to file from browser processes.
|
||||||
*
|
*
|
||||||
@ -127,5 +133,6 @@ export {
|
|||||||
baseName,
|
baseName,
|
||||||
log,
|
log,
|
||||||
isSubdirectory,
|
isSubdirectory,
|
||||||
|
getUserHomePath,
|
||||||
FileStat,
|
FileStat,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,5 +8,7 @@ export const fsRouter = async (app: HttpServer) => {
|
|||||||
|
|
||||||
app.post(`/app/${FileManagerRoute.getResourcePath}`, async (request: any, reply: any) => {})
|
app.post(`/app/${FileManagerRoute.getResourcePath}`, async (request: any, reply: any) => {})
|
||||||
|
|
||||||
|
app.post(`/app/${FileManagerRoute.getUserHomePath}`, async (request: any, reply: any) => {})
|
||||||
|
|
||||||
app.post(`/app/${FileManagerRoute.fileStat}`, async (request: any, reply: any) => {})
|
app.post(`/app/${FileManagerRoute.fileStat}`, async (request: any, reply: any) => {})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ipcMain } from 'electron'
|
import { ipcMain, app } from 'electron'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import reflect from '@alumna/reflect'
|
import reflect from '@alumna/reflect'
|
||||||
|
|
||||||
@ -38,6 +38,10 @@ export function handleFileMangerIPCs() {
|
|||||||
getResourcePath()
|
getResourcePath()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ipcMain.handle(FileManagerRoute.getUserHomePath, async (_event) =>
|
||||||
|
app.getPath('home')
|
||||||
|
)
|
||||||
|
|
||||||
// handle fs is directory here
|
// handle fs is directory here
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
FileManagerRoute.fileStat,
|
FileManagerRoute.fileStat,
|
||||||
|
|||||||
@ -86,7 +86,7 @@
|
|||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"request-progress": "^3.0.0",
|
"request-progress": "^3.0.0",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.2.2",
|
||||||
"ulid": "^2.3.0",
|
"ulid": "^2.3.0",
|
||||||
"use-debounce": "^9.0.4"
|
"use-debounce": "^9.0.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
"rollup-plugin-sourcemaps": "^0.6.3",
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
||||||
"rollup-plugin-typescript2": "^0.36.0",
|
"rollup-plugin-typescript2": "^0.36.0",
|
||||||
"run-script-os": "^1.1.6",
|
"run-script-os": "^1.1.6",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@janhq/core": "file:../../core",
|
"@janhq/core": "file:../../core",
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/react-avatar": "^1.0.4",
|
"@radix-ui/react-avatar": "^1.0.4",
|
||||||
|
"@radix-ui/react-checkbox": "^1.0.4",
|
||||||
"@radix-ui/react-context": "^1.0.1",
|
"@radix-ui/react-context": "^1.0.1",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-secondary-blue {
|
&-secondary-blue {
|
||||||
@apply bg-blue-200 text-blue-600 hover:bg-blue-500/50;
|
@apply bg-blue-200 text-blue-600 hover:bg-blue-300/50 dark:hover:bg-blue-200/80;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-danger {
|
&-danger {
|
||||||
@ -17,7 +17,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-secondary-danger {
|
&-secondary-danger {
|
||||||
@apply bg-red-200 text-red-600 hover:bg-red-500/50;
|
@apply bg-red-200 text-red-600 hover:bg-red-300/50 dark:hover:bg-red-200/80;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-outline {
|
&-outline {
|
||||||
@ -67,14 +67,18 @@
|
|||||||
[type='submit'] {
|
[type='submit'] {
|
||||||
&.btn-primary {
|
&.btn-primary {
|
||||||
@apply bg-primary hover:bg-primary/90;
|
@apply bg-primary hover:bg-primary/90;
|
||||||
|
@apply disabled:pointer-events-none disabled:bg-zinc-100 disabled:text-zinc-400;
|
||||||
}
|
}
|
||||||
&.btn-secondary {
|
&.btn-secondary {
|
||||||
@apply bg-secondary hover:bg-secondary/80;
|
@apply bg-secondary hover:bg-secondary/80;
|
||||||
|
@apply disabled:pointer-events-none disabled:bg-zinc-100 disabled:text-zinc-400;
|
||||||
}
|
}
|
||||||
&.btn-secondary-blue {
|
&.btn-secondary-blue {
|
||||||
@apply bg-blue-200 text-blue-900 hover:bg-blue-200/80;
|
@apply bg-blue-200 text-blue-900 hover:bg-blue-200/80;
|
||||||
|
@apply disabled:pointer-events-none disabled:bg-zinc-100 disabled:text-zinc-400;
|
||||||
}
|
}
|
||||||
&.btn-danger {
|
&.btn-danger {
|
||||||
@apply bg-danger hover:bg-danger/90;
|
@apply bg-danger hover:bg-danger/90;
|
||||||
|
@apply disabled:pointer-events-none disabled:bg-zinc-100 disabled:text-zinc-400;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
uikit/src/checkbox/index.tsx
Normal file
29
uikit/src/checkbox/index.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import * as React from 'react'
|
||||||
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox'
|
||||||
|
import { CheckIcon } from '@radix-ui/react-icons'
|
||||||
|
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
const Checkbox = React.forwardRef<
|
||||||
|
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<CheckboxPrimitive.Root
|
||||||
|
ref={ref}
|
||||||
|
className={twMerge('checkbox', className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<CheckboxPrimitive.Indicator
|
||||||
|
className={twMerge(
|
||||||
|
'flex flex-shrink-0 items-center justify-center text-current'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<CheckIcon className="checkbox--icon" />
|
||||||
|
</CheckboxPrimitive.Indicator>
|
||||||
|
</CheckboxPrimitive.Root>
|
||||||
|
))
|
||||||
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName
|
||||||
|
|
||||||
|
export { Checkbox }
|
||||||
7
uikit/src/checkbox/styles.scss
Normal file
7
uikit/src/checkbox/styles.scss
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.checkbox {
|
||||||
|
@apply border-border data-[state=checked]:bg-primary h-5 w-5 flex-shrink-0 rounded-md border data-[state=checked]:text-white;
|
||||||
|
|
||||||
|
&--icon {
|
||||||
|
@apply h-4 w-4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,3 +12,4 @@ export * from './command'
|
|||||||
export * from './textarea'
|
export * from './textarea'
|
||||||
export * from './select'
|
export * from './select'
|
||||||
export * from './slider'
|
export * from './slider'
|
||||||
|
export * from './checkbox'
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
@import './textarea/styles.scss';
|
@import './textarea/styles.scss';
|
||||||
@import './select/styles.scss';
|
@import './select/styles.scss';
|
||||||
@import './slider/styles.scss';
|
@import './slider/styles.scss';
|
||||||
|
@import './checkbox/styles.scss';
|
||||||
|
|
||||||
.animate-spin {
|
.animate-spin {
|
||||||
animation: spin 1s linear infinite;
|
animation: spin 1s linear infinite;
|
||||||
|
|||||||
59
web/hooks/useFactoryReset.ts
Normal file
59
web/hooks/useFactoryReset.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
import { fs, AppConfiguration, joinPath, getUserHomePath } from '@janhq/core'
|
||||||
|
|
||||||
|
export default function useFactoryReset() {
|
||||||
|
const [defaultJanDataFolder, setdefaultJanDataFolder] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getDefaultJanDataFolder() {
|
||||||
|
const homePath = await getUserHomePath()
|
||||||
|
const defaultJanDataFolder = await joinPath([homePath, 'jan'])
|
||||||
|
setdefaultJanDataFolder(defaultJanDataFolder)
|
||||||
|
}
|
||||||
|
getDefaultJanDataFolder()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const resetAll = async (keepCurrentFolder?: boolean) => {
|
||||||
|
// read the place of jan data folder
|
||||||
|
const appConfiguration: AppConfiguration | undefined =
|
||||||
|
await window.core?.api?.getAppConfigurations()
|
||||||
|
|
||||||
|
if (!appConfiguration) {
|
||||||
|
console.debug('Failed to get app configuration')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug('appConfiguration: ', appConfiguration)
|
||||||
|
const janDataFolderPath = appConfiguration!.data_folder
|
||||||
|
|
||||||
|
if (defaultJanDataFolder === janDataFolderPath) {
|
||||||
|
console.debug('Jan data folder is already at user home')
|
||||||
|
} else {
|
||||||
|
// if jan data folder is not at user home, we update the app configuration to point to user home
|
||||||
|
if (!keepCurrentFolder) {
|
||||||
|
const configuration: AppConfiguration = {
|
||||||
|
data_folder: defaultJanDataFolder,
|
||||||
|
}
|
||||||
|
await window.core?.api?.updateAppConfiguration(configuration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelPath = await joinPath([janDataFolderPath, 'models'])
|
||||||
|
const threadPath = await joinPath([janDataFolderPath, 'threads'])
|
||||||
|
|
||||||
|
console.debug(`Removing models at ${modelPath}`)
|
||||||
|
await fs.rmdirSync(modelPath, { recursive: true })
|
||||||
|
|
||||||
|
console.debug(`Removing threads at ${threadPath}`)
|
||||||
|
await fs.rmdirSync(threadPath, { recursive: true })
|
||||||
|
|
||||||
|
// reset the localStorage
|
||||||
|
localStorage.clear()
|
||||||
|
await window.core?.api?.relaunch()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
defaultJanDataFolder,
|
||||||
|
resetAll,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { fs, joinPath } from '@janhq/core'
|
import { fs, joinPath } from '@janhq/core'
|
||||||
import { atom, useAtom } from 'jotai'
|
import { atom, useAtom } from 'jotai'
|
||||||
@ -32,7 +32,7 @@ export const useSettings = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const readSettings = async () => {
|
const readSettings = useCallback(async () => {
|
||||||
if (!window?.core?.api) {
|
if (!window?.core?.api) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -42,7 +42,8 @@ export const useSettings = () => {
|
|||||||
return typeof settings === 'object' ? settings : JSON.parse(settings)
|
return typeof settings === 'object' ? settings : JSON.parse(settings)
|
||||||
}
|
}
|
||||||
return {}
|
return {}
|
||||||
}
|
}, [])
|
||||||
|
|
||||||
const saveSettings = async ({
|
const saveSettings = async ({
|
||||||
runMode,
|
runMode,
|
||||||
notify,
|
notify,
|
||||||
|
|||||||
@ -91,11 +91,7 @@ const LocalServerScreen = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (localStorage.getItem(FIRST_TIME_VISIT_API_SERVER) == null) {
|
||||||
localStorage.getItem(FIRST_TIME_VISIT_API_SERVER) === null ||
|
|
||||||
localStorage.getItem(FIRST_TIME_VISIT_API_SERVER) === 'true'
|
|
||||||
) {
|
|
||||||
localStorage.setItem(FIRST_TIME_VISIT_API_SERVER, 'true')
|
|
||||||
setFirstTimeVisitAPIServer(true)
|
setFirstTimeVisitAPIServer(true)
|
||||||
}
|
}
|
||||||
}, [firstTimeVisitAPIServer])
|
}, [firstTimeVisitAPIServer])
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
import { fs, AppConfiguration, joinPath, getUserHomePath } from '@janhq/core'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalPortal,
|
||||||
|
ModalContent,
|
||||||
|
ModalHeader,
|
||||||
|
ModalTitle,
|
||||||
|
ModalFooter,
|
||||||
|
ModalClose,
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Input,
|
||||||
|
} from '@janhq/uikit'
|
||||||
|
import { atom, useAtom } from 'jotai'
|
||||||
|
|
||||||
|
import useFactoryReset from '@/hooks/useFactoryReset'
|
||||||
|
|
||||||
|
export const modalValidationAtom = atom(false)
|
||||||
|
|
||||||
|
const ModalConfirmReset = () => {
|
||||||
|
const [modalValidation, setModalValidation] = useAtom(modalValidationAtom)
|
||||||
|
const { resetAll, defaultJanDataFolder } = useFactoryReset()
|
||||||
|
const [inputValue, setInputValue] = useState('')
|
||||||
|
const [currentDirectoryChecked, setCurrentDirectoryChecked] = useState(true)
|
||||||
|
const onFactoryResetClick = useCallback(
|
||||||
|
() => resetAll(currentDirectoryChecked),
|
||||||
|
[currentDirectoryChecked, resetAll]
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={modalValidation}
|
||||||
|
onOpenChange={() => setModalValidation(false)}
|
||||||
|
>
|
||||||
|
<ModalPortal />
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader>
|
||||||
|
<ModalTitle>
|
||||||
|
Are you sure you want to reset to default settings?
|
||||||
|
</ModalTitle>
|
||||||
|
</ModalHeader>
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
It will reset the application to its original state, deleting all your
|
||||||
|
usage data, including model customizations and conversation history.
|
||||||
|
This action is irreversible.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<p className="mb-2 mt-1 text-muted-foreground">{`To confirm, please enter the word "RESET" below:`}</p>
|
||||||
|
<Input
|
||||||
|
placeholder='Enter "RESET"'
|
||||||
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-shrink-0 items-start space-x-2">
|
||||||
|
<Checkbox
|
||||||
|
id="currentDirectory"
|
||||||
|
checked={currentDirectoryChecked}
|
||||||
|
onCheckedChange={(e) => setCurrentDirectoryChecked(Boolean(e))}
|
||||||
|
/>
|
||||||
|
<div className="mt-0.5 flex flex-col">
|
||||||
|
<label
|
||||||
|
htmlFor="currentDirectory"
|
||||||
|
className="cursor-pointer text-sm font-medium leading-none"
|
||||||
|
>
|
||||||
|
Keep the current app data location
|
||||||
|
</label>
|
||||||
|
<p className="mt-2 leading-relaxed">
|
||||||
|
Otherwise it will reset back to its original location at:
|
||||||
|
{/* TODO should be from system */}
|
||||||
|
<span className="font-medium">{defaultJanDataFolder}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ModalFooter>
|
||||||
|
<div className="flex gap-x-2">
|
||||||
|
<ModalClose asChild onClick={() => setModalValidation(false)}>
|
||||||
|
<Button themes="outline">Cancel</Button>
|
||||||
|
</ModalClose>
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button
|
||||||
|
autoFocus
|
||||||
|
themes="danger"
|
||||||
|
disabled={inputValue !== 'RESET'}
|
||||||
|
onClick={onFactoryResetClick}
|
||||||
|
>
|
||||||
|
Reset Now
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</ModalFooter>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ModalConfirmReset
|
||||||
37
web/screens/Settings/Advanced/FactoryReset/index.tsx
Normal file
37
web/screens/Settings/Advanced/FactoryReset/index.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { Button } from '@janhq/uikit'
|
||||||
|
|
||||||
|
import { useSetAtom } from 'jotai'
|
||||||
|
|
||||||
|
import ModalValidation, { modalValidationAtom } from './ModalConfirmReset'
|
||||||
|
|
||||||
|
const FactoryReset = () => {
|
||||||
|
const setModalValidation = useSetAtom(modalValidationAtom)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
||||||
|
<div className="w-4/5 flex-shrink-0 space-y-1.5">
|
||||||
|
<div className="flex gap-x-2">
|
||||||
|
<h6 className="text-sm font-semibold capitalize">
|
||||||
|
Reset to Factory Default
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<p className="whitespace-pre-wrap leading-relaxed">
|
||||||
|
Reset the application to its original state, deleting all your usage
|
||||||
|
data, including model customizations and conversation history. This
|
||||||
|
action is irreversible and recommended only if the application is in a
|
||||||
|
corrupted state.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
themes="secondaryDanger"
|
||||||
|
onClick={() => setModalValidation(true)}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<ModalValidation />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FactoryReset
|
||||||
@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -21,6 +20,7 @@ import { FeatureToggleContext } from '@/context/FeatureToggle'
|
|||||||
import { useSettings } from '@/hooks/useSettings'
|
import { useSettings } from '@/hooks/useSettings'
|
||||||
|
|
||||||
import DataFolder from './DataFolder'
|
import DataFolder from './DataFolder'
|
||||||
|
import FactoryReset from './FactoryReset'
|
||||||
|
|
||||||
const Advanced = () => {
|
const Advanced = () => {
|
||||||
const {
|
const {
|
||||||
@ -36,6 +36,7 @@ const Advanced = () => {
|
|||||||
|
|
||||||
const { readSettings, saveSettings, validateSettings, setShowNotification } =
|
const { readSettings, saveSettings, validateSettings, setShowNotification } =
|
||||||
useSettings()
|
useSettings()
|
||||||
|
|
||||||
const onProxyChange = useCallback(
|
const onProxyChange = useCallback(
|
||||||
(event: ChangeEvent<HTMLInputElement>) => {
|
(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = event.target.value || ''
|
const value = event.target.value || ''
|
||||||
@ -50,10 +51,12 @@ const Advanced = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
readSettings().then((settings) => {
|
const setUseGpuIfPossible = async () => {
|
||||||
|
const settings = await readSettings()
|
||||||
setGpuEnabled(settings.run_mode === 'gpu')
|
setGpuEnabled(settings.run_mode === 'gpu')
|
||||||
})
|
}
|
||||||
}, [])
|
setUseGpuIfPossible()
|
||||||
|
}, [readSettings])
|
||||||
|
|
||||||
const clearLogs = async () => {
|
const clearLogs = async () => {
|
||||||
if (await fs.existsSync(`file://logs`)) {
|
if (await fs.existsSync(`file://logs`)) {
|
||||||
@ -96,13 +99,7 @@ const Advanced = () => {
|
|||||||
</div>
|
</div>
|
||||||
<Switch
|
<Switch
|
||||||
checked={experimentalFeature}
|
checked={experimentalFeature}
|
||||||
onCheckedChange={(e) => {
|
onCheckedChange={setExperimentalFeature}
|
||||||
if (e === true) {
|
|
||||||
setExperimentalFeature(true)
|
|
||||||
} else {
|
|
||||||
setExperimentalFeature(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -119,7 +116,7 @@ const Advanced = () => {
|
|||||||
</div>
|
</div>
|
||||||
<Switch
|
<Switch
|
||||||
checked={gpuEnabled}
|
checked={gpuEnabled}
|
||||||
onCheckedChange={(e: boolean) => {
|
onCheckedChange={(e) => {
|
||||||
if (e === true) {
|
if (e === true) {
|
||||||
saveSettings({ runMode: 'gpu' })
|
saveSettings({ runMode: 'gpu' })
|
||||||
setGpuEnabled(true)
|
setGpuEnabled(true)
|
||||||
@ -137,7 +134,7 @@ const Advanced = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Directory */}
|
{/* Directory */}
|
||||||
<DataFolder />
|
{experimentalFeature && <DataFolder />}
|
||||||
|
|
||||||
{/* Proxy */}
|
{/* Proxy */}
|
||||||
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
||||||
@ -170,16 +167,7 @@ const Advanced = () => {
|
|||||||
certain proxies.
|
certain proxies.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Switch
|
<Switch checked={ignoreSSL} onCheckedChange={(e) => setIgnoreSSL(e)} />
|
||||||
checked={ignoreSSL}
|
|
||||||
onCheckedChange={(e) => {
|
|
||||||
if (e === true) {
|
|
||||||
setIgnoreSSL(true)
|
|
||||||
} else {
|
|
||||||
setIgnoreSSL(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Open app directory */}
|
{/* Open app directory */}
|
||||||
@ -206,7 +194,7 @@ const Advanced = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Claer log */}
|
{/* Clear log */}
|
||||||
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
<div className="flex w-full items-start justify-between border-b border-border py-4 first:pt-0 last:border-none">
|
||||||
<div className="flex-shrink-0 space-y-1.5">
|
<div className="flex-shrink-0 space-y-1.5">
|
||||||
<div className="flex gap-x-2">
|
<div className="flex gap-x-2">
|
||||||
@ -218,6 +206,9 @@ const Advanced = () => {
|
|||||||
Clear
|
Clear
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Factory Reset */}
|
||||||
|
<FactoryReset />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user