2019-11-05 21:39:39 +00:00
|
|
|
// Modules to control application life and create native browser window
|
|
|
|
const {
|
|
|
|
BrowserWindow,
|
|
|
|
Menu,
|
|
|
|
MenuItem,
|
|
|
|
ipcMain,
|
|
|
|
app,
|
|
|
|
shell,
|
2023-08-28 11:23:10 +00:00
|
|
|
dialog,
|
|
|
|
autoUpdater
|
|
|
|
} = require('electron/main')
|
2023-08-29 19:52:16 +00:00
|
|
|
const path = require('node:path')
|
2019-11-05 21:39:39 +00:00
|
|
|
|
|
|
|
const menu = new Menu()
|
|
|
|
menu.append(new MenuItem({ label: 'Hello' }))
|
|
|
|
menu.append(new MenuItem({ type: 'separator' }))
|
|
|
|
menu.append(
|
|
|
|
new MenuItem({ label: 'Electron', type: 'checkbox', checked: true })
|
|
|
|
)
|
|
|
|
|
|
|
|
const template = [
|
|
|
|
{
|
|
|
|
label: 'Edit',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Undo',
|
|
|
|
accelerator: 'CmdOrCtrl+Z',
|
|
|
|
role: 'undo'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Redo',
|
|
|
|
accelerator: 'Shift+CmdOrCtrl+Z',
|
|
|
|
role: 'redo'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Cut',
|
|
|
|
accelerator: 'CmdOrCtrl+X',
|
|
|
|
role: 'cut'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Copy',
|
|
|
|
accelerator: 'CmdOrCtrl+C',
|
|
|
|
role: 'copy'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Paste',
|
|
|
|
accelerator: 'CmdOrCtrl+V',
|
|
|
|
role: 'paste'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Select All',
|
|
|
|
accelerator: 'CmdOrCtrl+A',
|
|
|
|
role: 'selectall'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'View',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Reload',
|
|
|
|
accelerator: 'CmdOrCtrl+R',
|
|
|
|
click: (item, focusedWindow) => {
|
|
|
|
if (focusedWindow) {
|
|
|
|
// on reload, start fresh and close any old
|
|
|
|
// open secondary windows
|
|
|
|
if (focusedWindow.id === 1) {
|
2023-08-31 14:36:43 +00:00
|
|
|
for (const win of BrowserWindow.getAllWindows()) {
|
2019-11-05 21:39:39 +00:00
|
|
|
if (win.id > 1) win.close()
|
2023-08-31 14:36:43 +00:00
|
|
|
}
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
focusedWindow.reload()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Toggle Full Screen',
|
|
|
|
accelerator: (() => {
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
return 'Ctrl+Command+F'
|
|
|
|
} else {
|
|
|
|
return 'F11'
|
|
|
|
}
|
|
|
|
})(),
|
|
|
|
click: (item, focusedWindow) => {
|
|
|
|
if (focusedWindow) {
|
|
|
|
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Toggle Developer Tools',
|
|
|
|
accelerator: (() => {
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
return 'Alt+Command+I'
|
|
|
|
} else {
|
|
|
|
return 'Ctrl+Shift+I'
|
|
|
|
}
|
|
|
|
})(),
|
|
|
|
click: (item, focusedWindow) => {
|
|
|
|
if (focusedWindow) {
|
2023-12-12 19:36:34 +00:00
|
|
|
focusedWindow.webContents.toggleDevTools()
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'App Menu Demo',
|
|
|
|
click: function (item, focusedWindow) {
|
|
|
|
if (focusedWindow) {
|
|
|
|
const options = {
|
|
|
|
type: 'info',
|
|
|
|
title: 'Application Menu Demo',
|
|
|
|
buttons: ['Ok'],
|
|
|
|
message:
|
|
|
|
'This demo is for the Menu section, showing how to create a clickable menu item in the application menu.'
|
|
|
|
}
|
|
|
|
dialog.showMessageBox(focusedWindow, options, function () {})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Window',
|
|
|
|
role: 'window',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Minimize',
|
|
|
|
accelerator: 'CmdOrCtrl+M',
|
|
|
|
role: 'minimize'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Close',
|
|
|
|
accelerator: 'CmdOrCtrl+W',
|
|
|
|
role: 'close'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Reopen Window',
|
|
|
|
accelerator: 'CmdOrCtrl+Shift+T',
|
|
|
|
enabled: false,
|
|
|
|
key: 'reopenMenuItem',
|
|
|
|
click: () => {
|
|
|
|
app.emit('activate')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Help',
|
|
|
|
role: 'help',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Learn More',
|
|
|
|
click: () => {
|
2020-02-17 00:46:41 +00:00
|
|
|
shell.openExternal('https://electronjs.org')
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
function addUpdateMenuItems (items, position) {
|
|
|
|
if (process.mas) return
|
|
|
|
|
|
|
|
const version = app.getVersion()
|
|
|
|
const updateItems = [
|
|
|
|
{
|
|
|
|
label: `Version ${version}`,
|
|
|
|
enabled: false
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Checking for Update',
|
|
|
|
enabled: false,
|
|
|
|
key: 'checkingForUpdate'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Check for Update',
|
|
|
|
visible: false,
|
|
|
|
key: 'checkForUpdate',
|
|
|
|
click: () => {
|
2023-08-28 11:23:10 +00:00
|
|
|
autoUpdater.checkForUpdates()
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Restart and Install Update',
|
|
|
|
enabled: true,
|
|
|
|
visible: false,
|
|
|
|
key: 'restartToUpdate',
|
|
|
|
click: () => {
|
2023-08-28 11:23:10 +00:00
|
|
|
autoUpdater.quitAndInstall()
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
items.splice.apply(items, [position, 0].concat(updateItems))
|
|
|
|
}
|
|
|
|
|
|
|
|
function findReopenMenuItem () {
|
|
|
|
const menu = Menu.getApplicationMenu()
|
|
|
|
if (!menu) return
|
|
|
|
|
|
|
|
let reopenMenuItem
|
2023-08-31 14:36:43 +00:00
|
|
|
for (const item of menu.items) {
|
2019-11-05 21:39:39 +00:00
|
|
|
if (item.submenu) {
|
2023-08-31 14:36:43 +00:00
|
|
|
for (const subitem of item.submenu.items) {
|
|
|
|
if (subitem.key === 'reopenMenuItem') {
|
|
|
|
reopenMenuItem = subitem
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
2023-08-31 14:36:43 +00:00
|
|
|
}
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
2023-08-31 14:36:43 +00:00
|
|
|
}
|
2019-11-05 21:39:39 +00:00
|
|
|
return reopenMenuItem
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.platform === 'darwin') {
|
|
|
|
const name = app.getName()
|
|
|
|
template.unshift({
|
|
|
|
label: name,
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: `About ${name}`,
|
|
|
|
role: 'about'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Services',
|
|
|
|
role: 'services',
|
|
|
|
submenu: []
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: `Hide ${name}`,
|
|
|
|
accelerator: 'Command+H',
|
|
|
|
role: 'hide'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Hide Others',
|
|
|
|
accelerator: 'Command+Alt+H',
|
|
|
|
role: 'hideothers'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Show All',
|
|
|
|
role: 'unhide'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Quit',
|
|
|
|
accelerator: 'Command+Q',
|
|
|
|
click: () => {
|
|
|
|
app.quit()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
})
|
|
|
|
|
|
|
|
// Window menu.
|
|
|
|
template[3].submenu.push(
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Bring All to Front',
|
|
|
|
role: 'front'
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
addUpdateMenuItems(template[0].submenu, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (process.platform === 'win32') {
|
|
|
|
const helpMenu = template[template.length - 1].submenu
|
|
|
|
addUpdateMenuItems(helpMenu, 0)
|
|
|
|
}
|
|
|
|
// Keep a global reference of the window object, if you don't, the window will
|
|
|
|
// be closed automatically when the JavaScript object is garbage collected.
|
|
|
|
let mainWindow
|
|
|
|
|
|
|
|
function createWindow () {
|
|
|
|
// Create the browser window.
|
|
|
|
mainWindow = new BrowserWindow({
|
|
|
|
width: 800,
|
|
|
|
height: 600,
|
|
|
|
webPreferences: {
|
2023-08-29 19:52:16 +00:00
|
|
|
preload: path.join(__dirname, 'preload.js')
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
// and load the index.html of the app.
|
|
|
|
mainWindow.loadFile('index.html')
|
|
|
|
|
|
|
|
// Open the DevTools.
|
|
|
|
// mainWindow.webContents.openDevTools()
|
|
|
|
|
|
|
|
// Emitted when the window is closed.
|
|
|
|
mainWindow.on('closed', function () {
|
|
|
|
// Dereference the window object, usually you would store windows
|
|
|
|
// in an array if your app supports multi windows, this is the time
|
|
|
|
// when you should delete the corresponding element.
|
|
|
|
mainWindow = null
|
|
|
|
})
|
2023-08-08 10:35:59 +00:00
|
|
|
|
|
|
|
// Open external links in the default browser
|
|
|
|
mainWindow.webContents.on('will-navigate', (event, url) => {
|
|
|
|
event.preventDefault()
|
|
|
|
shell.openExternal(url)
|
|
|
|
})
|
2019-11-05 21:39:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// This method will be called when Electron has finished
|
|
|
|
// initialization and is ready to create browser windows.
|
|
|
|
// Some APIs can only be used after this event occurs.
|
2020-02-03 22:43:22 +00:00
|
|
|
app.whenReady().then(() => {
|
2019-11-05 21:39:39 +00:00
|
|
|
createWindow()
|
|
|
|
const menu = Menu.buildFromTemplate(template)
|
|
|
|
Menu.setApplicationMenu(menu)
|
|
|
|
})
|
|
|
|
|
|
|
|
// Quit when all windows are closed.
|
|
|
|
app.on('window-all-closed', function () {
|
2020-03-31 04:06:25 +00:00
|
|
|
// On macOS it is common for applications and their menu bar
|
2019-11-05 21:39:39 +00:00
|
|
|
// to stay active until the user quits explicitly with Cmd + Q
|
|
|
|
const reopenMenuItem = findReopenMenuItem()
|
|
|
|
if (reopenMenuItem) reopenMenuItem.enabled = true
|
|
|
|
|
|
|
|
if (process.platform !== 'darwin') {
|
|
|
|
app.quit()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
app.on('activate', function () {
|
2020-03-31 04:06:25 +00:00
|
|
|
// On macOS it is common to re-create a window in the app when the
|
2019-11-05 21:39:39 +00:00
|
|
|
// dock icon is clicked and there are no other windows open.
|
|
|
|
if (mainWindow === null) {
|
|
|
|
createWindow()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
app.on('browser-window-created', (event, win) => {
|
|
|
|
const reopenMenuItem = findReopenMenuItem()
|
|
|
|
if (reopenMenuItem) reopenMenuItem.enabled = false
|
|
|
|
|
|
|
|
win.webContents.on('context-menu', (e, params) => {
|
|
|
|
menu.popup(win, params.x, params.y)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
ipcMain.on('show-context-menu', event => {
|
|
|
|
const win = BrowserWindow.fromWebContents(event.sender)
|
|
|
|
menu.popup(win)
|
|
|
|
})
|
|
|
|
|
|
|
|
// In this file you can include the rest of your app's specific main process
|
|
|
|
// code. You can also put them in separate files and require them here.
|