jan/electron/managers/window.ts
Faisal Amir faa09bd2bf
feat: Dekstop Revamp (#2877)
* feat: desktop revamp

* feat: refactor system monitor

* fix linter CI

* remove unused import component

* added responsive and resizeable component

* responsive and resizeable local server page

* finalize responsive and resizeable component

* fix scroll custom ui

* remove react scroll to bottom from modal troubleshoot

* fix modal troubleshoot ui

* fix setting gpu list

* text area custom scroll bar

* fix padding message input

* cleanup classname

* update inference engine model dropdown

* update loader style

* update quick ask ui

* prepare theme provider

* update dark theme

* remove update hotkey list model and navigation

* fix: cleanup hardcode classname

* fix: update feedback

* Set native theme electron

* update destop ui revamp from feedback

* update button icon component insider icon chat input message

* update model dropdown ui

* update tranaparent baclground

* update logo model provider

* fix: set background material acrylic support to blur background windows

* fix: update tranparent left and right panel

* fix: linter CI

* update app using frameless window

* styling custom style minimize, maximize and close app

* temporary hidden maximize window

* fix: responsive left and right panel

* fix: enable click outside when leftpanel responsive

* fix: remove unused import

* update transparent variable css windows

* fix: ui import model

* feat: Support Theme system (#2946)

* feat: update support theme system

* update select component

* feat: add theme folder in root project

* fix: padding left and right center panel

* fix: update padding left and right

* chore: migrate themes

* fix: rmdirsync error

* chore: update gitignore

* fix: cp recursive

* fix: files electron package json

* fix: migration

* fix: update fgit ignore

---------

Co-authored-by: Louis <louis@jan.ai>

* fix: update feedback missing state when refrash app

* fix: error test CI

* chore: refactor useLoadThemes

* chore: cleanup unused vars

* fix: revert back menubar windows

* fix minor ui

* fix: minor ui

---------

Co-authored-by: Louis <louis@jan.ai>
2024-05-29 13:37:18 +07:00

193 lines
5.0 KiB
TypeScript

import { BrowserWindow, app, shell } from 'electron'
import { quickAskWindowConfig } from './quickAskWindowConfig'
import { mainWindowConfig } from './mainWindowConfig'
import { getAppConfigurations, AppEvent } from '@janhq/core/node'
import { getBounds, saveBounds } from '../utils/setup'
/**
* 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: {
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()