feat: add the ability to display the application in tray #297
This commit is contained in:
parent
612b39a878
commit
e11633310c
BIN
build/tray_icon_dark.png
Normal file
BIN
build/tray_icon_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
build/tray_icon_light.png
Normal file
BIN
build/tray_icon_light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
9
src/main/electron.d.ts
vendored
Normal file
9
src/main/electron.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
declare global {
|
||||||
|
namespace Electron {
|
||||||
|
interface App {
|
||||||
|
isQuitting: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {}
|
||||||
@ -4,8 +4,9 @@ import installExtension, { REDUX_DEVTOOLS } from 'electron-devtools-installer'
|
|||||||
|
|
||||||
import { registerIpc } from './ipc'
|
import { registerIpc } from './ipc'
|
||||||
import { registerZoomShortcut } from './services/ShortcutService'
|
import { registerZoomShortcut } from './services/ShortcutService'
|
||||||
|
import { TrayService } from './services/TrayService'
|
||||||
|
import { windowService } from './services/WindowService'
|
||||||
import { updateUserDataPath } from './utils/upgrade'
|
import { updateUserDataPath } from './utils/upgrade'
|
||||||
import { createMainWindow } from './window'
|
|
||||||
|
|
||||||
// Check for single instance lock
|
// Check for single instance lock
|
||||||
if (!app.requestSingleInstanceLock()) {
|
if (!app.requestSingleInstanceLock()) {
|
||||||
@ -21,21 +22,19 @@ app.whenReady().then(async () => {
|
|||||||
// Set app user model id for windows
|
// Set app user model id for windows
|
||||||
electronApp.setAppUserModelId(import.meta.env.VITE_MAIN_BUNDLE_ID || 'com.kangfenmao.CherryStudio')
|
electronApp.setAppUserModelId(import.meta.env.VITE_MAIN_BUNDLE_ID || 'com.kangfenmao.CherryStudio')
|
||||||
|
|
||||||
// Default open or close DevTools by F12 in development
|
const mainWindow = windowService.createMainWindow()
|
||||||
// and ignore CommandOrControl + R in production.
|
new TrayService()
|
||||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
|
||||||
app.on('browser-window-created', (_, window) => {
|
|
||||||
optimizer.watchWindowShortcuts(window)
|
|
||||||
})
|
|
||||||
|
|
||||||
app.on('activate', function () {
|
app.on('activate', function () {
|
||||||
// On macOS it's common to re-create a window in the app when the
|
// On macOS it's common to re-create a window in the app when the
|
||||||
// dock icon is clicked and there are no other windows open.
|
// dock icon is clicked and there are no other windows open.
|
||||||
if (BrowserWindow.getAllWindows().length === 0) createMainWindow()
|
if (BrowserWindow.getAllWindows().length === 0) {
|
||||||
|
windowService.createMainWindow()
|
||||||
|
} else {
|
||||||
|
windowService.showMainWindow()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const mainWindow = createMainWindow()
|
|
||||||
|
|
||||||
registerZoomShortcut(mainWindow)
|
registerZoomShortcut(mainWindow)
|
||||||
|
|
||||||
registerIpc(mainWindow, app)
|
registerIpc(mainWindow, app)
|
||||||
@ -56,13 +55,12 @@ app.on('second-instance', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Quit when all windows are closed, except on macOS. There, it's common
|
app.on('browser-window-created', (_, window) => {
|
||||||
// for applications and their menu bar to stay active until the user quits
|
optimizer.watchWindowShortcuts(window)
|
||||||
// explicitly with Cmd + Q.
|
})
|
||||||
app.on('window-all-closed', () => {
|
|
||||||
if (process.platform !== 'darwin') {
|
app.on('before-quit', () => {
|
||||||
app.quit()
|
app.isQuitting = true
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// In this file you can include the rest of your app"s specific main process
|
// In this file you can include the rest of your app"s specific main process
|
||||||
|
|||||||
@ -9,8 +9,8 @@ import BackupManager from './services/BackupManager'
|
|||||||
import { configManager } from './services/ConfigManager'
|
import { configManager } from './services/ConfigManager'
|
||||||
import { ExportService } from './services/ExportService'
|
import { ExportService } from './services/ExportService'
|
||||||
import FileStorage from './services/FileStorage'
|
import FileStorage from './services/FileStorage'
|
||||||
|
import { windowService } from './services/WindowService'
|
||||||
import { compress, decompress } from './utils/zip'
|
import { compress, decompress } from './utils/zip'
|
||||||
import { createMinappWindow } from './window'
|
|
||||||
|
|
||||||
const fileManager = new FileStorage()
|
const fileManager = new FileStorage()
|
||||||
const backupManager = new BackupManager()
|
const backupManager = new BackupManager()
|
||||||
@ -79,7 +79,7 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
|||||||
|
|
||||||
// minapp
|
// minapp
|
||||||
ipcMain.handle('minapp', (_, args) => {
|
ipcMain.handle('minapp', (_, args) => {
|
||||||
createMinappWindow({
|
windowService.createMinappWindow({
|
||||||
url: args.url,
|
url: args.url,
|
||||||
parent: mainWindow,
|
parent: mainWindow,
|
||||||
windowOptions: {
|
windowOptions: {
|
||||||
|
|||||||
BIN
src/main/resources/icon.ico
Normal file
BIN
src/main/resources/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 353 KiB |
68
src/main/services/TrayService.ts
Normal file
68
src/main/services/TrayService.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { app, Menu, nativeImage, nativeTheme, Tray } from 'electron'
|
||||||
|
|
||||||
|
import iconDark from '../../../build/tray_icon_dark.png?asset'
|
||||||
|
import iconLight from '../../../build/tray_icon_light.png?asset'
|
||||||
|
import { windowService } from './WindowService'
|
||||||
|
|
||||||
|
export class TrayService {
|
||||||
|
private tray: Tray | null = null
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.createTray()
|
||||||
|
}
|
||||||
|
|
||||||
|
private createTray() {
|
||||||
|
const iconPath = nativeTheme.shouldUseDarkColors ? iconLight : iconDark
|
||||||
|
const tray = new Tray(iconPath)
|
||||||
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
tray.setImage(iconPath)
|
||||||
|
nativeTheme.on('updated', () => {
|
||||||
|
const newIconPath = nativeTheme.shouldUseDarkColors ? iconLight : iconDark
|
||||||
|
tray.setImage(newIconPath)
|
||||||
|
})
|
||||||
|
} else if (process.platform === 'darwin') {
|
||||||
|
const image = nativeImage.createFromPath(iconPath)
|
||||||
|
const resizedImage = image.resize({ width: 16, height: 16 })
|
||||||
|
resizedImage.setTemplateImage(true)
|
||||||
|
tray.setImage(resizedImage)
|
||||||
|
} else if (process.platform === 'linux') {
|
||||||
|
const image = nativeImage.createFromPath(iconPath)
|
||||||
|
const resizedImage = image.resize({ width: 24, height: 24 })
|
||||||
|
tray.setImage(resizedImage)
|
||||||
|
nativeTheme.on('updated', () => {
|
||||||
|
const newIconPath = nativeTheme.shouldUseDarkColors ? iconLight : iconDark
|
||||||
|
const newImage = nativeImage.createFromPath(newIconPath)
|
||||||
|
const newResizedImage = newImage.resize({ width: 24, height: 24 })
|
||||||
|
tray.setImage(newResizedImage)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tray = tray
|
||||||
|
|
||||||
|
const contextMenu = Menu.buildFromTemplate([
|
||||||
|
{
|
||||||
|
label: '显示窗口',
|
||||||
|
click: () => windowService.showMainWindow()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '退出',
|
||||||
|
click: () => this.quit()
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
this.tray.setToolTip('Cherry Studio')
|
||||||
|
|
||||||
|
this.tray.on('right-click', () => {
|
||||||
|
this.tray?.popUpContextMenu(contextMenu)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.tray.on('click', () => {
|
||||||
|
windowService.showMainWindow()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private quit() {
|
||||||
|
app.quit()
|
||||||
|
}
|
||||||
|
}
|
||||||
194
src/main/services/WindowService.ts
Normal file
194
src/main/services/WindowService.ts
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
import { is } from '@electron-toolkit/utils'
|
||||||
|
import { app, BrowserWindow, Menu, MenuItem, shell } from 'electron'
|
||||||
|
import windowStateKeeper from 'electron-window-state'
|
||||||
|
import { join } from 'path'
|
||||||
|
|
||||||
|
import icon from '../../../build/icon.png?asset'
|
||||||
|
import { titleBarOverlayDark, titleBarOverlayLight } from '../config'
|
||||||
|
import { locales } from '../utils/locales'
|
||||||
|
import { configManager } from './ConfigManager'
|
||||||
|
|
||||||
|
export class WindowService {
|
||||||
|
private static instance: WindowService | null = null
|
||||||
|
private mainWindow: BrowserWindow | null = null
|
||||||
|
|
||||||
|
public static getInstance(): WindowService {
|
||||||
|
if (!WindowService.instance) {
|
||||||
|
WindowService.instance = new WindowService()
|
||||||
|
}
|
||||||
|
return WindowService.instance
|
||||||
|
}
|
||||||
|
|
||||||
|
public createMainWindow(): BrowserWindow {
|
||||||
|
if (this.mainWindow && !this.mainWindow.isDestroyed()) {
|
||||||
|
return this.mainWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
const mainWindowState = windowStateKeeper({
|
||||||
|
defaultWidth: 1080,
|
||||||
|
defaultHeight: 670
|
||||||
|
})
|
||||||
|
|
||||||
|
const theme = configManager.getTheme()
|
||||||
|
const isMac = process.platform === 'darwin'
|
||||||
|
|
||||||
|
this.mainWindow = new BrowserWindow({
|
||||||
|
x: mainWindowState.x,
|
||||||
|
y: mainWindowState.y,
|
||||||
|
width: mainWindowState.width,
|
||||||
|
height: mainWindowState.height,
|
||||||
|
minWidth: 1080,
|
||||||
|
minHeight: 600,
|
||||||
|
show: true,
|
||||||
|
autoHideMenuBar: true,
|
||||||
|
transparent: isMac,
|
||||||
|
vibrancy: 'fullscreen-ui',
|
||||||
|
visualEffectState: 'active',
|
||||||
|
titleBarStyle: 'hidden',
|
||||||
|
titleBarOverlay: theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight,
|
||||||
|
backgroundColor: isMac ? undefined : theme === 'dark' ? '#181818' : '#FFFFFF',
|
||||||
|
trafficLightPosition: { x: 8, y: 12 },
|
||||||
|
...(process.platform === 'linux' ? { icon } : {}),
|
||||||
|
webPreferences: {
|
||||||
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
|
sandbox: false,
|
||||||
|
webSecurity: false,
|
||||||
|
webviewTag: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.setupMainWindow(this.mainWindow, mainWindowState)
|
||||||
|
return this.mainWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
public createMinappWindow({
|
||||||
|
url,
|
||||||
|
parent,
|
||||||
|
windowOptions
|
||||||
|
}: {
|
||||||
|
url: string
|
||||||
|
parent?: BrowserWindow
|
||||||
|
windowOptions?: Electron.BrowserWindowConstructorOptions
|
||||||
|
}): BrowserWindow {
|
||||||
|
const width = windowOptions?.width || 1000
|
||||||
|
const height = windowOptions?.height || 680
|
||||||
|
|
||||||
|
const minappWindow = new BrowserWindow({
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
autoHideMenuBar: true,
|
||||||
|
title: 'Cherry Studio',
|
||||||
|
...windowOptions,
|
||||||
|
parent,
|
||||||
|
webPreferences: {
|
||||||
|
preload: join(__dirname, '../preload/minapp.js'),
|
||||||
|
sandbox: false,
|
||||||
|
contextIsolation: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minappWindow.loadURL(url)
|
||||||
|
return minappWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupMainWindow(mainWindow: BrowserWindow, mainWindowState: any) {
|
||||||
|
mainWindowState.manage(mainWindow)
|
||||||
|
|
||||||
|
this.setupContextMenu(mainWindow)
|
||||||
|
this.setupWindowEvents(mainWindow)
|
||||||
|
this.setupWebContentsHandlers(mainWindow)
|
||||||
|
this.setupWindowLifecycleEvents(mainWindow)
|
||||||
|
this.loadMainWindowContent(mainWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupContextMenu(mainWindow: BrowserWindow) {
|
||||||
|
mainWindow.webContents.on('context-menu', () => {
|
||||||
|
const locale = locales[configManager.getLanguage()]
|
||||||
|
const { common } = locale.translation
|
||||||
|
|
||||||
|
const menu = new Menu()
|
||||||
|
menu.append(new MenuItem({ label: common.copy, role: 'copy' }))
|
||||||
|
menu.append(new MenuItem({ label: common.paste, role: 'paste' }))
|
||||||
|
menu.append(new MenuItem({ label: common.cut, role: 'cut' }))
|
||||||
|
menu.popup()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupWindowEvents(mainWindow: BrowserWindow) {
|
||||||
|
mainWindow.on('ready-to-show', () => {
|
||||||
|
mainWindow.show()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupWebContentsHandlers(mainWindow: BrowserWindow) {
|
||||||
|
mainWindow.webContents.on('will-navigate', (event, url) => {
|
||||||
|
event.preventDefault()
|
||||||
|
shell.openExternal(url)
|
||||||
|
})
|
||||||
|
|
||||||
|
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||||
|
shell.openExternal(details.url)
|
||||||
|
return { action: 'deny' }
|
||||||
|
})
|
||||||
|
|
||||||
|
this.setupWebRequestHeaders(mainWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupWebRequestHeaders(mainWindow: BrowserWindow) {
|
||||||
|
mainWindow.webContents.session.webRequest.onHeadersReceived({ urls: ['*://*/*'] }, (details, callback) => {
|
||||||
|
if (details.responseHeaders?.['X-Frame-Options']) {
|
||||||
|
delete details.responseHeaders['X-Frame-Options']
|
||||||
|
}
|
||||||
|
if (details.responseHeaders?.['x-frame-options']) {
|
||||||
|
delete details.responseHeaders['x-frame-options']
|
||||||
|
}
|
||||||
|
if (details.responseHeaders?.['Content-Security-Policy']) {
|
||||||
|
delete details.responseHeaders['Content-Security-Policy']
|
||||||
|
}
|
||||||
|
if (details.responseHeaders?.['content-security-policy']) {
|
||||||
|
delete details.responseHeaders['content-security-policy']
|
||||||
|
}
|
||||||
|
callback({ cancel: false, responseHeaders: details.responseHeaders })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadMainWindowContent(mainWindow: BrowserWindow) {
|
||||||
|
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||||
|
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
||||||
|
} else {
|
||||||
|
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMainWindow(): BrowserWindow | null {
|
||||||
|
return this.mainWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupWindowLifecycleEvents(mainWindow: BrowserWindow) {
|
||||||
|
mainWindow.on('close', (event) => {
|
||||||
|
if (!app.isQuitting) {
|
||||||
|
event.preventDefault()
|
||||||
|
mainWindow.hide()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mainWindow.on('minimize', (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
mainWindow.hide()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public showMainWindow() {
|
||||||
|
if (this.mainWindow) {
|
||||||
|
if (this.mainWindow.isMinimized()) {
|
||||||
|
this.mainWindow.restore()
|
||||||
|
}
|
||||||
|
this.mainWindow.show()
|
||||||
|
this.mainWindow.focus()
|
||||||
|
} else {
|
||||||
|
this.createMainWindow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const windowService = WindowService.getInstance()
|
||||||
@ -1,132 +0,0 @@
|
|||||||
import { is } from '@electron-toolkit/utils'
|
|
||||||
import { BrowserWindow, Menu, MenuItem, shell } from 'electron'
|
|
||||||
import windowStateKeeper from 'electron-window-state'
|
|
||||||
import { join } from 'path'
|
|
||||||
|
|
||||||
import icon from '../../build/icon.png?asset'
|
|
||||||
import { titleBarOverlayDark, titleBarOverlayLight } from './config'
|
|
||||||
import { configManager } from './services/ConfigManager'
|
|
||||||
import { locales } from './utils/locales'
|
|
||||||
|
|
||||||
export function createMainWindow() {
|
|
||||||
// Load the previous state with fallback to defaults
|
|
||||||
const mainWindowState = windowStateKeeper({
|
|
||||||
defaultWidth: 1080,
|
|
||||||
defaultHeight: 670
|
|
||||||
})
|
|
||||||
|
|
||||||
const theme = configManager.getTheme()
|
|
||||||
|
|
||||||
// Create the browser window.
|
|
||||||
const isMac = process.platform === 'darwin'
|
|
||||||
|
|
||||||
const mainWindow = new BrowserWindow({
|
|
||||||
x: mainWindowState.x,
|
|
||||||
y: mainWindowState.y,
|
|
||||||
width: mainWindowState.width,
|
|
||||||
height: mainWindowState.height,
|
|
||||||
minWidth: 1080,
|
|
||||||
minHeight: 600,
|
|
||||||
show: true,
|
|
||||||
autoHideMenuBar: true,
|
|
||||||
transparent: isMac,
|
|
||||||
vibrancy: 'fullscreen-ui',
|
|
||||||
visualEffectState: 'active',
|
|
||||||
titleBarStyle: 'hidden',
|
|
||||||
titleBarOverlay: theme === 'dark' ? titleBarOverlayDark : titleBarOverlayLight,
|
|
||||||
backgroundColor: isMac ? undefined : theme === 'dark' ? '#181818' : '#FFFFFF',
|
|
||||||
trafficLightPosition: { x: 8, y: 12 },
|
|
||||||
...(process.platform === 'linux' ? { icon } : {}),
|
|
||||||
webPreferences: {
|
|
||||||
preload: join(__dirname, '../preload/index.js'),
|
|
||||||
sandbox: false,
|
|
||||||
webSecurity: false,
|
|
||||||
webviewTag: true
|
|
||||||
// devTools: !app.isPackaged,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindowState.manage(mainWindow)
|
|
||||||
|
|
||||||
mainWindow.webContents.on('context-menu', () => {
|
|
||||||
const locale = locales[configManager.getLanguage()]
|
|
||||||
const { common } = locale.translation
|
|
||||||
|
|
||||||
const menu = new Menu()
|
|
||||||
menu.append(new MenuItem({ label: common.copy, role: 'copy' }))
|
|
||||||
menu.append(new MenuItem({ label: common.paste, role: 'paste' }))
|
|
||||||
menu.append(new MenuItem({ label: common.cut, role: 'cut' }))
|
|
||||||
menu.popup()
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.on('ready-to-show', () => {
|
|
||||||
mainWindow.show()
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.webContents.on('will-navigate', (event, url) => {
|
|
||||||
event.preventDefault()
|
|
||||||
shell.openExternal(url)
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
|
||||||
shell.openExternal(details.url)
|
|
||||||
return { action: 'deny' }
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.webContents.session.webRequest.onHeadersReceived({ urls: ['*://*/*'] }, (details, callback) => {
|
|
||||||
if (details.responseHeaders?.['X-Frame-Options']) {
|
|
||||||
delete details.responseHeaders['X-Frame-Options']
|
|
||||||
}
|
|
||||||
if (details.responseHeaders?.['x-frame-options']) {
|
|
||||||
delete details.responseHeaders['x-frame-options']
|
|
||||||
}
|
|
||||||
if (details.responseHeaders?.['Content-Security-Policy']) {
|
|
||||||
delete details.responseHeaders['Content-Security-Policy']
|
|
||||||
}
|
|
||||||
if (details.responseHeaders?.['content-security-policy']) {
|
|
||||||
delete details.responseHeaders['content-security-policy']
|
|
||||||
}
|
|
||||||
callback({ cancel: false, responseHeaders: details.responseHeaders })
|
|
||||||
})
|
|
||||||
|
|
||||||
// HMR for renderer base on electron-vite cli.
|
|
||||||
// Load the remote URL for development or the local html file for production.
|
|
||||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
|
||||||
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
|
||||||
} else {
|
|
||||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
|
||||||
}
|
|
||||||
|
|
||||||
return mainWindow
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createMinappWindow({
|
|
||||||
url,
|
|
||||||
parent,
|
|
||||||
windowOptions
|
|
||||||
}: {
|
|
||||||
url: string
|
|
||||||
parent?: BrowserWindow
|
|
||||||
windowOptions?: Electron.BrowserWindowConstructorOptions
|
|
||||||
}) {
|
|
||||||
const width = windowOptions?.width || 1000
|
|
||||||
const height = windowOptions?.height || 680
|
|
||||||
|
|
||||||
const minappWindow = new BrowserWindow({
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
autoHideMenuBar: true,
|
|
||||||
title: 'Cherry Studio',
|
|
||||||
...windowOptions,
|
|
||||||
parent,
|
|
||||||
webPreferences: {
|
|
||||||
preload: join(__dirname, '../preload/minapp.js'),
|
|
||||||
sandbox: false,
|
|
||||||
contextIsolation: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
minappWindow.loadURL(url)
|
|
||||||
|
|
||||||
return minappWindow
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user