Skip to content

Commit

Permalink
Menu improvements (#139)
Browse files Browse the repository at this point in the history
* Extract methods to utils

* Refactor mapMenu

* Change/remove imports/calls to mapMenu

* Code style

* Allow main app menu to be modified

* Fix triggering menu item events

* Scrap custom event menu item

We can get enough custom event data through on other types, making this redundant

* Fold 'goto' items into 'link'
  • Loading branch information
simonhamp authored Dec 1, 2024
1 parent 5bea8c2 commit ce7b02c
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 117 deletions.
28 changes: 15 additions & 13 deletions resources/js/electron-plugin/src/server/api/contextMenu.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
import express from 'express'
import {app, Menu} from 'electron'
import {mapMenu} from "./helper";
import express from 'express';
import { app, Menu } from 'electron';
import { compileMenu } from "./helper";
import contextMenu from "electron-context-menu";

const router = express.Router();

let contextMenuDisposable = null

router.delete('/', (req, res) => {
res.sendStatus(200)
res.sendStatus(200);

if (contextMenuDisposable) {
contextMenuDisposable()
contextMenuDisposable = null
contextMenuDisposable();
contextMenuDisposable = null;
}
});

router.post('/', (req, res) => {
res.sendStatus(200)
res.sendStatus(200);

if (contextMenuDisposable) {
contextMenuDisposable()
contextMenuDisposable = null
contextMenuDisposable();
contextMenuDisposable = null;
}

contextMenuDisposable = contextMenu({
showLookUpSelection: false,
showSearchWithGoogle: false,
showInspectElement: false,
prepend: (defaultActions, parameters, browserWindow) => {
return req.body.entries.map(mapMenu)
}
})
})
return req.body.entries.map(compileMenu);
},
});
});

export default router;
4 changes: 2 additions & 2 deletions resources/js/electron-plugin/src/server/api/dock.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import express from 'express';
import { app, Menu } from 'electron';
import { mapMenu } from './helper';
import { compileMenu } from './helper';
import state from '../state';

const router = express.Router();

router.post('/', (req, res) => {
const menuEntries = req.body.items.map(mapMenu);
const menuEntries = req.body.items.map(compileMenu);

const menu = Menu.buildFromTemplate(menuEntries);
app.dock.setMenu(menu);
Expand Down
103 changes: 56 additions & 47 deletions resources/js/electron-plugin/src/server/api/helper/index.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,82 @@
import {shell} from "electron";
import {notifyLaravel} from "../../utils";
import { shell } from 'electron';
import { notifyLaravel, goToUrl } from '../../utils';
import state from '../../state';

function triggerMenuItemEvent(menuItem) {
function triggerMenuItemEvent(menuItem, combo) {
notifyLaravel('events', {
event: '\\Native\\Laravel\\Events\\Menu\\MenuItemClicked',
payload: [
{
event: menuItem.event || '\\Native\\Laravel\\Events\\Menu\\MenuItemClicked',
payload: {
item: {
id: menuItem.id,
label: menuItem.label,
checked: menuItem.checked
}
]
})
checked: menuItem.checked,
},
combo,
},
});
}

const mapMenu = (menu) => {
if (menu.submenu) {
menu.submenu = menu.submenu.map(mapMenu)
}

if (menu.type === 'link') {
menu.type = 'normal'
menu.click = () => {
triggerMenuItemEvent(menu)
shell.openExternal(menu.url)
export function compileMenu (item) {
if (item.submenu) {
if (Array.isArray(item.submenu)) {
item.submenu = item.submenu?.map(compileMenu);
} else {
item.submenu = item.submenu.submenu?.map(compileMenu);
}
return menu
}

if (menu.type === 'checkbox') {
menu.click = () => {
menu.checked = !menu.checked
triggerMenuItemEvent(menu)
}
}
if (item.type === 'link') {
item.type = 'normal';

if (menu.type === 'event') {
return {
label: menu.label,
accelerator: menu.accelerator,
click() {
notifyLaravel('events', {
event: menu.event
})
item.click = (menuItem, focusedWindow, combo) => {
triggerMenuItemEvent(item, combo);

if (item.openInBrowser) {
shell.openExternal(item.url);
return;
}

if (! focusedWindow) {
// TODO: Bring a window to the front?
return;
}

const id = Object.keys(state.windows)
.find(key => state.windows[key] === focusedWindow);

goToUrl(item.url, id);
}

return item;
}

if (item.type === 'checkbox' || item.type === 'radio') {
item.click = (menuItem, focusedWindow, combo) => {
item.checked = !item.checked;
triggerMenuItemEvent(item, combo);
};

return item;
}

if (menu.type === 'role') {
if (item.type === 'role') {
let menuItem = {
role: menu.role
role: item.role
};

if (menu.label) {
menuItem['label'] = menu.label;
if (item.label) {
menuItem['label'] = item.label;
}

return menuItem;
}

if (! menu.click) {
menu.click = () => {
triggerMenuItemEvent(menu)
// Default click event
if (! item.click) {
item.click = (menuItem, focusedWindow, combo) => {
triggerMenuItemEvent(item, combo);
}
}

return menu
}

export {
mapMenu,
return item;
}
21 changes: 13 additions & 8 deletions resources/js/electron-plugin/src/server/api/menu.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import express from 'express'
import {Menu} from 'electron'
import {mapMenu} from "./helper";
import express from 'express';
import { Menu } from 'electron';
import { compileMenu } from './helper';

const router = express.Router();

router.post('/', (req, res) => {
const menuEntries = req.body.items.map(mapMenu)
Menu.setApplicationMenu(null);

const menuEntries = req.body.items.map(compileMenu);

const menu = Menu.buildFromTemplate(menuEntries);

Menu.setApplicationMenu(menu);

const menu = Menu.buildFromTemplate(menuEntries)
Menu.setApplicationMenu(menu)
res.sendStatus(200)
})
res.sendStatus(200);
});

export default router;
4 changes: 2 additions & 2 deletions resources/js/electron-plugin/src/server/api/menuBar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from "express";
import { Menu, Tray } from "electron";
import { mapMenu } from "./helper";
import { compileMenu } from "./helper";
import state from "../state";
import { menubar } from "menubar";
import { notifyLaravel } from "../utils";
Expand Down Expand Up @@ -193,7 +193,7 @@ function buildMenu(contextMenu) {
let menu = Menu.buildFromTemplate([{ role: "quit" }]);

if (contextMenu) {
const menuEntries = contextMenu.map(mapMenu);
const menuEntries = contextMenu.map(compileMenu);
menu = Menu.buildFromTemplate(menuEntries);
}

Expand Down
1 change: 0 additions & 1 deletion resources/js/electron-plugin/src/server/api/progressBar.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import express from 'express'
import {app, Menu} from 'electron'
import state from "../state";
import {mapMenu} from "./helper";
const router = express.Router();

router.post('/update', (req, res) => {
Expand Down
6 changes: 3 additions & 3 deletions resources/js/electron-plugin/src/server/api/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express from 'express'
import state from "../state";
import express from 'express';
import state from '../state';

const router = express.Router();

router.get('/:key', (req, res) => {
Expand Down Expand Up @@ -28,7 +29,6 @@ router.delete('/:key', (req, res) => {
});

router.delete('/', (req, res) => {

state.store.clear();

res.sendStatus(200)
Expand Down
2 changes: 1 addition & 1 deletion resources/js/electron-plugin/src/server/api/system.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from 'express';
import {BrowserWindow, systemPreferences, safeStorage} from 'electron';
import { BrowserWindow, systemPreferences, safeStorage } from 'electron';

const router = express.Router();

Expand Down
17 changes: 7 additions & 10 deletions resources/js/electron-plugin/src/server/api/window.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import express from 'express';
import {BrowserWindow, clipboard, NativeImage} from 'electron';
import { BrowserWindow, clipboard, NativeImage } from 'electron';
import state from '../state';
import {join} from "path";
import {notifyLaravel} from "../utils";
import { join } from 'path';
import { notifyLaravel, goToUrl, appendWindowIdToUrl } from '../utils';
import windowStateKeeper from 'electron-window-state';

const router = express.Router();
import windowStateKeeper from "electron-window-state";

router.post('/maximize', (req, res) => {
const {id} = req.body;
Expand Down Expand Up @@ -41,7 +42,7 @@ router.post('/title', (req, res) => {
router.post('/url', (req, res) => {
const {id, url} = req.body;

state.windows[id]?.loadURL(appendWindowIdToUrl(url, id));
goToUrl(url, id);

res.sendStatus(200);
});
Expand Down Expand Up @@ -142,10 +143,6 @@ router.get('/get/:id', (req, res) => {
res.json(getWindowData(id));
});

function appendWindowIdToUrl(url, id) {
return url + (url.indexOf('?') === -1 ? '?' : '&') + '_windowId=' + id;
}

function getWindowData(id) {
const currentWindow = state.windows[id];

Expand Down Expand Up @@ -360,7 +357,7 @@ router.post('/open', (req, res) => {

window.webContents.on('did-finish-load', () => {
window.show();
})
});

window.webContents.on('did-fail-load', (event) => {
console.error('failed to open window...', event);
Expand Down
Loading

0 comments on commit ce7b02c

Please sign in to comment.