jan/electron/managers/window.ts
NamH ec9b5bf682
fix: update new api from cortex to support 0.5.0 (#3221)
* fix: update new api from cortex to support 0.5.0

Signed-off-by: James <namnh0122@gmail.com>

* fix stop button for streaming

Signed-off-by: James <namnh0122@gmail.com>

* fix stop inference for nonstreaming

Signed-off-by: James <namnh0122@gmail.com>

* chore: remove umami prevent tracking call to vercel

Signed-off-by: James <namnh0122@gmail.com>

* add warning modal when running more than 2 model concurrently

Signed-off-by: James <namnh0122@gmail.com>

* fix: skip summarize if abort

Signed-off-by: James <namnh0122@gmail.com>

* 0.5.0-3

* add inference error popup

Signed-off-by: James <namnh0122@gmail.com>

* add back import local model

Signed-off-by: James <namnh0122@gmail.com>

* fix: max token issue (#3225)

Signed-off-by: James <namnh0122@gmail.com>

* format status

Signed-off-by: James <namnh0122@gmail.com>

* fix migration missing instructions

Signed-off-by: James <namnh0122@gmail.com>

* fix: wait for cortex process overlay should be on top (#3224)

* fix: wait for cortex process overlay should be on top

* chore: update cortex.js

* Cortex 0.5.0-5

* add import model to my model screen

Signed-off-by: James <namnh0122@gmail.com>

* fix: should migrate symlink models (#3226)

* fix import on windows (#3229)

Signed-off-by: James <namnh0122@gmail.com>

* fix yarn lint

Signed-off-by: James <namnh0122@gmail.com>

* fix: clean up port before start jan (#3232)

Signed-off-by: James <namnh0122@gmail.com>

---------

Signed-off-by: James <namnh0122@gmail.com>
Co-authored-by: Van Pham <64197333+Van-QA@users.noreply.github.com>
Co-authored-by: Louis <louis@jan.ai>
2024-08-02 09:37:04 +07:00

195 lines
5.1 KiB
TypeScript

import { BrowserWindow, app, shell } from 'electron'
import { quickAskWindowConfig } from './quickAskWindowConfig'
import { mainWindowConfig } from './mainWindowConfig'
import { getAppConfigurations } from './../utils/path'
import { getBounds, saveBounds } from '../utils/setup'
import { AppEvent } from '@janhq/core/node'
/**
* Manages the current window instance.
*/
// TODO: refactor this
let isAppQuitting = false
class WindowManager {
public mainWindow?: BrowserWindow
private _quickAskWindow: BrowserWindow | undefined = undefined
private _quickAskWindowVisible = false
private _mainWindowVisible = false
private deeplink: string | undefined
/**
* Creates a new window instance.
* @returns The created window instance.
*/
async createMainWindow(preloadPath: string, startUrl: string) {
const bounds = await getBounds()
this.mainWindow = new BrowserWindow({
...mainWindowConfig,
width: bounds.width,
height: bounds.height,
x: bounds.x,
y: bounds.y,
webPreferences: {
allowRunningInsecureContent: true,
nodeIntegration: true,
preload: preloadPath,
webSecurity: false,
},
})
if (process.platform === 'win32' || process.platform === 'linux') {
/// This is work around for windows deeplink.
/// second-instance event is not fired when app is not open, so the app
/// does not received the deeplink.
const commandLine = process.argv.slice(1)
if (commandLine.length > 0) {
const url = commandLine[0]
this.sendMainAppDeepLink(url)
}
}
this.mainWindow.on('resized', () => {
saveBounds(this.mainWindow?.getBounds())
})
this.mainWindow.on('moved', () => {
saveBounds(this.mainWindow?.getBounds())
})
/* Load frontend app to the window */
this.mainWindow.loadURL(startUrl)
/* Open external links in the default browser */
this.mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url)
return { action: 'deny' }
})
app.on('before-quit', function () {
isAppQuitting = true
})
windowManager.mainWindow?.on('close', function (evt) {
// Feature Toggle for Quick Ask
if (!getAppConfigurations().quick_ask) return
if (!isAppQuitting) {
evt.preventDefault()
windowManager.hideMainWindow()
}
})
}
createQuickAskWindow(preloadPath: string, startUrl: string): void {
this._quickAskWindow = new BrowserWindow({
...quickAskWindowConfig,
webPreferences: {
nodeIntegration: true,
preload: preloadPath,
webSecurity: false,
},
})
this._quickAskWindow.loadURL(startUrl)
this._quickAskWindow.on('blur', () => {
this.hideQuickAskWindow()
})
}
isMainWindowVisible(): boolean {
return this._mainWindowVisible
}
hideMainWindow(): void {
this.mainWindow?.hide()
this._mainWindowVisible = false
}
showMainWindow(): void {
this.mainWindow?.show()
this._mainWindowVisible = true
}
hideQuickAskWindow(): void {
this._quickAskWindow?.hide()
this._quickAskWindowVisible = false
}
showQuickAskWindow(): void {
this._quickAskWindow?.show()
this._quickAskWindowVisible = true
}
closeQuickAskWindow(): void {
if (this._quickAskWindow?.isDestroyed()) return
this._quickAskWindow?.close()
this._quickAskWindow?.destroy()
this._quickAskWindow = undefined
this._quickAskWindowVisible = false
}
isQuickAskWindowVisible(): boolean {
return this._quickAskWindowVisible
}
isQuickAskWindowDestroyed(): boolean {
return this._quickAskWindow?.isDestroyed() ?? true
}
expandQuickAskWindow(heightOffset: number): void {
const width = quickAskWindowConfig.width!
const height = quickAskWindowConfig.height! + heightOffset
this._quickAskWindow?.setMinimumSize(width, height)
this._quickAskWindow?.setSize(width, height, true)
}
sendQuickAskSelectedText(selectedText: string): void {
this._quickAskWindow?.webContents.send(
AppEvent.onSelectedText,
selectedText
)
}
/**
* Try to send the deep link to the main app.
*/
sendMainAppDeepLink(url: string): void {
this.deeplink = url
const interval = setInterval(() => {
if (!this.deeplink) clearInterval(interval)
const mainWindow = this.mainWindow
if (mainWindow) {
mainWindow.webContents.send(AppEvent.onDeepLink, this.deeplink)
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
}, 500)
}
cleanUp(): void {
if (!this.mainWindow?.isDestroyed()) {
this.mainWindow?.close()
this.mainWindow?.destroy()
this.mainWindow = undefined
this._mainWindowVisible = false
}
if (!this._quickAskWindow?.isDestroyed()) {
this._quickAskWindow?.close()
this._quickAskWindow?.destroy()
this._quickAskWindow = undefined
this._quickAskWindowVisible = false
}
}
/**
* Acknowledges that the window has received a deep link. We can remove it.
*/
ackDeepLink() {
this.deeplink = undefined
}
}
export const windowManager = new WindowManager()