Merge branch 'dev' into docs-pena-team
This commit is contained in:
commit
463a8c791a
10
README.md
10
README.md
@ -76,31 +76,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute
|
|||||||
<tr style="text-align:center">
|
<tr style="text-align:center">
|
||||||
<td style="text-align:center"><b>Experimental (Nightly Build)</b></td>
|
<td style="text-align:center"><b>Experimental (Nightly Build)</b></td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-win-x64-0.4.8-313.exe'>
|
<a href='https://delta.jan.ai/latest/jan-win-x64-0.4.8-315.exe'>
|
||||||
<img src='./docs/static/img/windows.png' style="height:14px; width: 14px" />
|
<img src='./docs/static/img/windows.png' style="height:14px; width: 14px" />
|
||||||
<b>jan.exe</b>
|
<b>jan.exe</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-mac-x64-0.4.8-313.dmg'>
|
<a href='https://delta.jan.ai/latest/jan-mac-x64-0.4.8-315.dmg'>
|
||||||
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
||||||
<b>Intel</b>
|
<b>Intel</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-mac-arm64-0.4.8-313.dmg'>
|
<a href='https://delta.jan.ai/latest/jan-mac-arm64-0.4.8-315.dmg'>
|
||||||
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
<img src='./docs/static/img/mac.png' style="height:15px; width: 15px" />
|
||||||
<b>M1/M2</b>
|
<b>M1/M2</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-linux-amd64-0.4.8-313.deb'>
|
<a href='https://delta.jan.ai/latest/jan-linux-amd64-0.4.8-315.deb'>
|
||||||
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
||||||
<b>jan.deb</b>
|
<b>jan.deb</b>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align:center">
|
<td style="text-align:center">
|
||||||
<a href='https://delta.jan.ai/latest/jan-linux-x86_64-0.4.8-313.AppImage'>
|
<a href='https://delta.jan.ai/latest/jan-linux-x86_64-0.4.8-315.AppImage'>
|
||||||
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
<img src='./docs/static/img/linux.png' style="height:14px; width: 14px" />
|
||||||
<b>jan.AppImage</b>
|
<b>jan.AppImage</b>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -4,13 +4,13 @@ import fs from 'fs'
|
|||||||
import os from 'os'
|
import os from 'os'
|
||||||
import childProcess from 'child_process'
|
import childProcess from 'child_process'
|
||||||
|
|
||||||
// TODO: move this to core
|
|
||||||
const configurationFileName = 'settings.json'
|
const configurationFileName = 'settings.json'
|
||||||
|
|
||||||
// TODO: do no specify app name in framework module
|
// TODO: do no specify app name in framework module
|
||||||
const defaultJanDataFolder = join(os.homedir(), 'jan')
|
const defaultJanDataFolder = join(os.homedir(), 'jan')
|
||||||
const defaultAppConfig: AppConfiguration = {
|
const defaultAppConfig: AppConfiguration = {
|
||||||
data_folder: defaultJanDataFolder,
|
data_folder: defaultJanDataFolder,
|
||||||
|
quick_ask: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
export type AppConfiguration = {
|
export type AppConfiguration = {
|
||||||
data_folder: string
|
data_folder: string
|
||||||
|
quick_ask: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
|
||||||
async function fetchData(siteConfig) {
|
async function fetchData(siteConfig) {
|
||||||
const owner = siteConfig.organizationName;
|
const owner = siteConfig.organizationName;
|
||||||
@ -70,6 +71,14 @@ async function fetchData(siteConfig) {
|
|||||||
// Process the GitHub releases data here
|
// Process the GitHub releases data here
|
||||||
for (const release of releases) {
|
for (const release of releases) {
|
||||||
const version = release.tag_name;
|
const version = release.tag_name;
|
||||||
|
|
||||||
|
// Check if the changelog file already exists for the current version
|
||||||
|
const existingChangelogPath = path.join(outputDirectory, `changelog-${version}.mdx`);
|
||||||
|
if (fs.existsSync(existingChangelogPath)) {
|
||||||
|
console.log(`Changelog for version ${version} already exists. Skipping...`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const releaseUrl = release.html_url;
|
const releaseUrl = release.html_url;
|
||||||
const issueNumberMatch = release.body.match(/#(\d+)/);
|
const issueNumberMatch = release.body.match(/#(\d+)/);
|
||||||
const issueNumber = issueNumberMatch ? parseInt(issueNumberMatch[1], 10) : null;
|
const issueNumber = issueNumberMatch ? parseInt(issueNumberMatch[1], 10) : null;
|
||||||
@ -94,4 +103,4 @@ async function fetchData(siteConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = fetchData;
|
module.exports = fetchData;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { join } from 'path'
|
|||||||
* Managers
|
* Managers
|
||||||
**/
|
**/
|
||||||
import { windowManager } from './managers/window'
|
import { windowManager } from './managers/window'
|
||||||
import { log } from '@janhq/core/node'
|
import { getAppConfigurations, log } from '@janhq/core/node'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPC Handlers
|
* IPC Handlers
|
||||||
@ -43,6 +43,12 @@ const gotTheLock = app.requestSingleInstanceLock()
|
|||||||
|
|
||||||
app
|
app
|
||||||
.whenReady()
|
.whenReady()
|
||||||
|
.then(() => {
|
||||||
|
if (!gotTheLock) {
|
||||||
|
app.quit()
|
||||||
|
throw new Error('Another instance of the app is already running')
|
||||||
|
}
|
||||||
|
})
|
||||||
.then(setupReactDevTool)
|
.then(setupReactDevTool)
|
||||||
.then(setupCore)
|
.then(setupCore)
|
||||||
.then(createUserSpace)
|
.then(createUserSpace)
|
||||||
@ -63,22 +69,20 @@ app
|
|||||||
log(`Version: ${app.getVersion()}`)
|
log(`Version: ${app.getVersion()}`)
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (!gotTheLock) {
|
|
||||||
app.quit()
|
|
||||||
} else {
|
|
||||||
app.on('second-instance', (_event, _commandLine, _workingDirectory) => {
|
|
||||||
// Someone tried to run a second instance, we should focus our window.
|
|
||||||
windowManager.showMainWindow()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
if (!BrowserWindow.getAllWindows().length) {
|
if (!BrowserWindow.getAllWindows().length) {
|
||||||
createMainWindow()
|
createMainWindow()
|
||||||
|
} else {
|
||||||
|
windowManager.showMainWindow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(() => cleanLogs())
|
.then(() => cleanLogs())
|
||||||
|
|
||||||
|
app.on('second-instance', (_event, _commandLine, _workingDirectory) => {
|
||||||
|
windowManager.showMainWindow()
|
||||||
|
})
|
||||||
|
|
||||||
app.on('ready', () => {
|
app.on('ready', () => {
|
||||||
registerGlobalShortcuts()
|
registerGlobalShortcuts()
|
||||||
})
|
})
|
||||||
@ -91,7 +95,15 @@ app.once('quit', () => {
|
|||||||
cleanUpAndQuit()
|
cleanUpAndQuit()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.once('window-all-closed', () => {
|
||||||
|
// Feature Toggle for Quick Ask
|
||||||
|
if (getAppConfigurations().quick_ask) return
|
||||||
|
cleanUpAndQuit()
|
||||||
|
})
|
||||||
|
|
||||||
function createQuickAskWindow() {
|
function createQuickAskWindow() {
|
||||||
|
// Feature Toggle for Quick Ask
|
||||||
|
if (!getAppConfigurations().quick_ask) return
|
||||||
const startUrl = app.isPackaged ? `file://${quickAskPath}` : quickAskUrl
|
const startUrl = app.isPackaged ? `file://${quickAskPath}` : quickAskUrl
|
||||||
windowManager.createQuickAskWindow(preloadPath, startUrl)
|
windowManager.createQuickAskWindow(preloadPath, startUrl)
|
||||||
}
|
}
|
||||||
@ -103,6 +115,9 @@ function createMainWindow() {
|
|||||||
|
|
||||||
function registerGlobalShortcuts() {
|
function registerGlobalShortcuts() {
|
||||||
const ret = registerShortcut(quickAskHotKey, (selectedText: string) => {
|
const ret = registerShortcut(quickAskHotKey, (selectedText: string) => {
|
||||||
|
// Feature Toggle for Quick Ask
|
||||||
|
if (!getAppConfigurations().quick_ask) return
|
||||||
|
|
||||||
if (!windowManager.isQuickAskWindowVisible()) {
|
if (!windowManager.isQuickAskWindowVisible()) {
|
||||||
windowManager.showQuickAskWindow()
|
windowManager.showQuickAskWindow()
|
||||||
windowManager.sendQuickAskSelectedText(selectedText)
|
windowManager.sendQuickAskSelectedText(selectedText)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export const mainWindowConfig: Electron.BrowserWindowConstructorOptions = {
|
|||||||
width: DEFAULT_WIDTH,
|
width: DEFAULT_WIDTH,
|
||||||
minWidth: DEFAULT_WIDTH,
|
minWidth: DEFAULT_WIDTH,
|
||||||
height: DEFAULT_HEIGHT,
|
height: DEFAULT_HEIGHT,
|
||||||
skipTaskbar: true,
|
skipTaskbar: false,
|
||||||
show: true,
|
show: true,
|
||||||
trafficLightPosition: {
|
trafficLightPosition: {
|
||||||
x: 10,
|
x: 10,
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { Tray, app, Menu } from 'electron'
|
import { Tray, app, Menu } from 'electron'
|
||||||
import { windowManager } from '../managers/window'
|
import { windowManager } from '../managers/window'
|
||||||
|
import { getAppConfigurations } from '@janhq/core/node'
|
||||||
|
|
||||||
class TrayManager {
|
class TrayManager {
|
||||||
currentTray: Tray | undefined
|
currentTray: Tray | undefined
|
||||||
|
|
||||||
createSystemTray = () => {
|
createSystemTray = () => {
|
||||||
|
// Feature Toggle for Quick Ask
|
||||||
|
if (!getAppConfigurations().quick_ask) return
|
||||||
|
|
||||||
if (this.currentTray) {
|
if (this.currentTray) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -13,20 +17,28 @@ class TrayManager {
|
|||||||
const tray = new Tray(iconPath)
|
const tray = new Tray(iconPath)
|
||||||
tray.setToolTip(app.getName())
|
tray.setToolTip(app.getName())
|
||||||
|
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
tray.on('click', () => {
|
||||||
{
|
windowManager.showQuickAskWindow()
|
||||||
label: 'Open Jan',
|
})
|
||||||
type: 'normal',
|
|
||||||
click: () => windowManager.showMainWindow(),
|
// Add context menu for windows only
|
||||||
},
|
if (process.platform === 'win32') {
|
||||||
{
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
label: 'Open Quick Ask',
|
{
|
||||||
type: 'normal',
|
label: 'Open Jan',
|
||||||
click: () => windowManager.showQuickAskWindow(),
|
type: 'normal',
|
||||||
},
|
click: () => windowManager.showMainWindow(),
|
||||||
{ label: 'Quit', type: 'normal', click: () => app.quit() },
|
},
|
||||||
])
|
{
|
||||||
tray.setContextMenu(contextMenu)
|
label: 'Open Quick Ask',
|
||||||
|
type: 'normal',
|
||||||
|
click: () => windowManager.showQuickAskWindow(),
|
||||||
|
},
|
||||||
|
{ label: 'Quit', type: 'normal', click: () => app.quit() },
|
||||||
|
])
|
||||||
|
|
||||||
|
tray.setContextMenu(contextMenu)
|
||||||
|
}
|
||||||
this.currentTray = tray
|
this.currentTray = tray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { BrowserWindow, app, shell } from 'electron'
|
|||||||
import { quickAskWindowConfig } from './quickAskWindowConfig'
|
import { quickAskWindowConfig } from './quickAskWindowConfig'
|
||||||
import { AppEvent } from '@janhq/core'
|
import { AppEvent } from '@janhq/core'
|
||||||
import { mainWindowConfig } from './mainWindowConfig'
|
import { mainWindowConfig } from './mainWindowConfig'
|
||||||
|
import { getAppConfigurations } from '@janhq/core/node'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the current window instance.
|
* Manages the current window instance.
|
||||||
@ -43,6 +44,9 @@ class WindowManager {
|
|||||||
})
|
})
|
||||||
|
|
||||||
windowManager.mainWindow?.on('close', function (evt) {
|
windowManager.mainWindow?.on('close', function (evt) {
|
||||||
|
// Feature Toggle for Quick Ask
|
||||||
|
if (!getAppConfigurations().quick_ask) return
|
||||||
|
|
||||||
if (!isAppQuitting) {
|
if (!isAppQuitting) {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
windowManager.hideMainWindow()
|
windowManager.hideMainWindow()
|
||||||
@ -73,15 +77,11 @@ class WindowManager {
|
|||||||
hideMainWindow(): void {
|
hideMainWindow(): void {
|
||||||
this.mainWindow?.hide()
|
this.mainWindow?.hide()
|
||||||
this._mainWindowVisible = false
|
this._mainWindowVisible = false
|
||||||
// Only macos
|
|
||||||
if (process.platform === 'darwin') app.dock.hide()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
showMainWindow(): void {
|
showMainWindow(): void {
|
||||||
this.mainWindow?.show()
|
this.mainWindow?.show()
|
||||||
this._mainWindowVisible = true
|
this._mainWindowVisible = true
|
||||||
// Only macos
|
|
||||||
if (process.platform === 'darwin') app.dock.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hideQuickAskWindow(): void {
|
hideQuickAskWindow(): void {
|
||||||
|
|||||||
@ -10,7 +10,10 @@ import useGetSystemResources from '@/hooks/useGetSystemResources'
|
|||||||
import useModels from '@/hooks/useModels'
|
import useModels from '@/hooks/useModels'
|
||||||
import useThreads from '@/hooks/useThreads'
|
import useThreads from '@/hooks/useThreads'
|
||||||
|
|
||||||
import { janDataFolderPathAtom } from '@/helpers/atoms/AppConfig.atom'
|
import {
|
||||||
|
janDataFolderPathAtom,
|
||||||
|
quickAskEnabledAtom,
|
||||||
|
} from '@/helpers/atoms/AppConfig.atom'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
@ -18,6 +21,7 @@ type Props = {
|
|||||||
|
|
||||||
const DataLoader: React.FC<Props> = ({ children }) => {
|
const DataLoader: React.FC<Props> = ({ children }) => {
|
||||||
const setJanDataFolderPath = useSetAtom(janDataFolderPathAtom)
|
const setJanDataFolderPath = useSetAtom(janDataFolderPathAtom)
|
||||||
|
const setQuickAskEnabled = useSetAtom(quickAskEnabledAtom)
|
||||||
|
|
||||||
useModels()
|
useModels()
|
||||||
useThreads()
|
useThreads()
|
||||||
@ -29,8 +33,9 @@ const DataLoader: React.FC<Props> = ({ children }) => {
|
|||||||
?.getAppConfigurations()
|
?.getAppConfigurations()
|
||||||
?.then((appConfig: AppConfiguration) => {
|
?.then((appConfig: AppConfiguration) => {
|
||||||
setJanDataFolderPath(appConfig.data_folder)
|
setJanDataFolderPath(appConfig.data_folder)
|
||||||
|
setQuickAskEnabled(appConfig.quick_ask)
|
||||||
})
|
})
|
||||||
}, [setJanDataFolderPath])
|
}, [setJanDataFolderPath, setQuickAskEnabled])
|
||||||
|
|
||||||
console.debug('Load Data...')
|
console.debug('Load Data...')
|
||||||
|
|
||||||
|
|||||||
@ -24,10 +24,6 @@ export default function KeyListener({ children }: Props) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onKeyDown = (e: KeyboardEvent) => {
|
const onKeyDown = (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Escape') {
|
|
||||||
window.core?.api?.hideMainWindow()
|
|
||||||
}
|
|
||||||
|
|
||||||
const prefixKey = isMac ? e.metaKey : e.ctrlKey
|
const prefixKey = isMac ? e.metaKey : e.ctrlKey
|
||||||
|
|
||||||
if (e.key === 'b' && prefixKey) {
|
if (e.key === 'b' && prefixKey) {
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { PropsWithChildren, useEffect, useState } from 'react'
|
|||||||
|
|
||||||
import { Toaster } from 'react-hot-toast'
|
import { Toaster } from 'react-hot-toast'
|
||||||
|
|
||||||
|
import { usePathname } from 'next/navigation'
|
||||||
|
|
||||||
import { TooltipProvider } from '@janhq/uikit'
|
import { TooltipProvider } from '@janhq/uikit'
|
||||||
|
|
||||||
import GPUDriverPrompt from '@/containers/GPUDriverPromptModal'
|
import GPUDriverPrompt from '@/containers/GPUDriverPromptModal'
|
||||||
@ -29,6 +31,7 @@ import { extensionManager } from '@/extension'
|
|||||||
|
|
||||||
const Providers = (props: PropsWithChildren) => {
|
const Providers = (props: PropsWithChildren) => {
|
||||||
const { children } = props
|
const { children } = props
|
||||||
|
const pathname = usePathname()
|
||||||
|
|
||||||
const [setupCore, setSetupCore] = useState(false)
|
const [setupCore, setSetupCore] = useState(false)
|
||||||
const [activated, setActivated] = useState(false)
|
const [activated, setActivated] = useState(false)
|
||||||
@ -40,6 +43,11 @@ const Providers = (props: PropsWithChildren) => {
|
|||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
if (!isCoreExtensionInstalled()) {
|
if (!isCoreExtensionInstalled()) {
|
||||||
|
// TODO: Proper window handle
|
||||||
|
// Do not migrate extension from quick ask window
|
||||||
|
if (pathname === '/search') {
|
||||||
|
return
|
||||||
|
}
|
||||||
setSettingUp(true)
|
setSettingUp(true)
|
||||||
await setupBaseExtensions()
|
await setupBaseExtensions()
|
||||||
return
|
return
|
||||||
|
|||||||
@ -6,6 +6,7 @@ const PROXY_FEATURE_ENABLED = 'proxyFeatureEnabled'
|
|||||||
const VULKAN_ENABLED = 'vulkanEnabled'
|
const VULKAN_ENABLED = 'vulkanEnabled'
|
||||||
const IGNORE_SSL = 'ignoreSSLFeature'
|
const IGNORE_SSL = 'ignoreSSLFeature'
|
||||||
const HTTPS_PROXY_FEATURE = 'httpsProxyFeature'
|
const HTTPS_PROXY_FEATURE = 'httpsProxyFeature'
|
||||||
|
const QUICK_ASK_ENABLED = 'quickAskEnabled'
|
||||||
|
|
||||||
export const janDataFolderPathAtom = atom('')
|
export const janDataFolderPathAtom = atom('')
|
||||||
|
|
||||||
@ -19,3 +20,4 @@ export const proxyAtom = atomWithStorage(HTTPS_PROXY_FEATURE, '')
|
|||||||
|
|
||||||
export const ignoreSslAtom = atomWithStorage(IGNORE_SSL, false)
|
export const ignoreSslAtom = atomWithStorage(IGNORE_SSL, false)
|
||||||
export const vulkanEnabledAtom = atomWithStorage(VULKAN_ENABLED, false)
|
export const vulkanEnabledAtom = atomWithStorage(VULKAN_ENABLED, false)
|
||||||
|
export const quickAskEnabledAtom = atomWithStorage(QUICK_ASK_ENABLED, false)
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export default function useFactoryReset() {
|
|||||||
// set the default jan data folder to user's home directory
|
// set the default jan data folder to user's home directory
|
||||||
const configuration: AppConfiguration = {
|
const configuration: AppConfiguration = {
|
||||||
data_folder: defaultJanDataFolder,
|
data_folder: defaultJanDataFolder,
|
||||||
|
quick_ask: appConfiguration?.quick_ask ?? false,
|
||||||
}
|
}
|
||||||
await window.core?.api?.updateAppConfiguration(configuration)
|
await window.core?.api?.updateAppConfiguration(configuration)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useState, useCallback, ChangeEvent } from 'react'
|
import { useEffect, useState, useCallback, ChangeEvent } from 'react'
|
||||||
|
|
||||||
import { openExternalUrl, fs } from '@janhq/core'
|
import { openExternalUrl, fs, AppConfiguration } from '@janhq/core'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Switch,
|
Switch,
|
||||||
@ -23,7 +23,7 @@ import {
|
|||||||
ScrollArea,
|
ScrollArea,
|
||||||
} from '@janhq/uikit'
|
} from '@janhq/uikit'
|
||||||
|
|
||||||
import { useAtom } from 'jotai'
|
import { useAtom, useAtomValue } from 'jotai'
|
||||||
import { AlertTriangleIcon, AlertCircleIcon } from 'lucide-react'
|
import { AlertTriangleIcon, AlertCircleIcon } from 'lucide-react'
|
||||||
|
|
||||||
import ShortcutModal from '@/containers/ShortcutModal'
|
import ShortcutModal from '@/containers/ShortcutModal'
|
||||||
@ -42,6 +42,7 @@ import {
|
|||||||
proxyAtom,
|
proxyAtom,
|
||||||
proxyEnabledAtom,
|
proxyEnabledAtom,
|
||||||
vulkanEnabledAtom,
|
vulkanEnabledAtom,
|
||||||
|
quickAskEnabledAtom,
|
||||||
} from '@/helpers/atoms/AppConfig.atom'
|
} from '@/helpers/atoms/AppConfig.atom'
|
||||||
|
|
||||||
type GPU = {
|
type GPU = {
|
||||||
@ -56,6 +57,8 @@ const Advanced = () => {
|
|||||||
)
|
)
|
||||||
const [vulkanEnabled, setVulkanEnabled] = useAtom(vulkanEnabledAtom)
|
const [vulkanEnabled, setVulkanEnabled] = useAtom(vulkanEnabledAtom)
|
||||||
const [proxyEnabled, setProxyEnabled] = useAtom(proxyEnabledAtom)
|
const [proxyEnabled, setProxyEnabled] = useAtom(proxyEnabledAtom)
|
||||||
|
const quickAskEnabled = useAtomValue(quickAskEnabledAtom)
|
||||||
|
|
||||||
const [proxy, setProxy] = useAtom(proxyAtom)
|
const [proxy, setProxy] = useAtom(proxyAtom)
|
||||||
const [ignoreSSL, setIgnoreSSL] = useAtom(ignoreSslAtom)
|
const [ignoreSSL, setIgnoreSSL] = useAtom(ignoreSslAtom)
|
||||||
|
|
||||||
@ -87,6 +90,14 @@ const Advanced = () => {
|
|||||||
[setPartialProxy, setProxy]
|
[setPartialProxy, setProxy]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const updateQuickAskEnabled = async (e: boolean) => {
|
||||||
|
const appConfiguration: AppConfiguration =
|
||||||
|
await window.core?.api?.getAppConfigurations()
|
||||||
|
appConfiguration.quick_ask = e
|
||||||
|
await window.core?.api?.updateAppConfiguration(appConfiguration)
|
||||||
|
window.core?.api?.relaunch()
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const setUseGpuIfPossible = async () => {
|
const setUseGpuIfPossible = async () => {
|
||||||
const settings = await readSettings()
|
const settings = await readSettings()
|
||||||
@ -361,7 +372,7 @@ const Advanced = () => {
|
|||||||
Vulkan Support
|
Vulkan Support
|
||||||
</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-xs leading-relaxed">
|
<p className="leading-relaxed">
|
||||||
Enable Vulkan with AMD GPU/APU and Intel Arc GPU for better
|
Enable Vulkan with AMD GPU/APU and Intel Arc GPU for better
|
||||||
model performance (reload needed).
|
model performance (reload needed).
|
||||||
</p>
|
</p>
|
||||||
@ -426,6 +437,36 @@ const Advanced = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{experimentalEnabled && (
|
||||||
|
<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 gap-x-2">
|
||||||
|
<h6 className="text-sm font-semibold capitalize">
|
||||||
|
Jan Quick Ask
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<p className="leading-relaxed">
|
||||||
|
Enable Quick Ask to be triggered via the default hotkey{' '}
|
||||||
|
<div className="inline-flex items-center justify-center rounded-full bg-secondary px-1 py-0.5 text-xs font-bold text-muted-foreground">
|
||||||
|
<span className="font-bold">{isMac ? '⌘' : 'Ctrl'} + J</span>
|
||||||
|
</div>{' '}
|
||||||
|
(reload needed).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={quickAskEnabled}
|
||||||
|
onCheckedChange={() => {
|
||||||
|
toaster({
|
||||||
|
title: 'Reload',
|
||||||
|
description:
|
||||||
|
'Quick Ask settings updated. Reload now to apply the changes.',
|
||||||
|
})
|
||||||
|
updateQuickAskEnabled(!quickAskEnabled)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Clear 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">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user