Tom Butcher 3b28aa4308 Add application menu structure for macOS and Windows
- Implemented functions to build application menus for macOS, including 'About', 'Edit', 'File', and 'Window' menus.
- Enhanced the application menu template to include these new menu structures, improving user navigation and functionality.
- Ensured compatibility with macOS by conditionally adding the app menu based on the platform.
2026-08-02 19:04:14 +01:00

168 lines
3.5 KiB
JavaScript

import { ApplicationMenu } from "electrobun/bun";
const SIDEBAR_MENU_ACTION_PREFIX = "sidebar-nav:";
let sidebarViewMenuSections = [];
let navigateHandler = null;
function buildMacAppMenu() {
return {
submenu: [
{
label: "About Farm Control",
action: `${SIDEBAR_MENU_ACTION_PREFIX}/dashboard/management/about`,
},
{ type: "separator" },
{ role: "hide" },
{ role: "hideOthers" },
{ role: "showAll" },
{ type: "separator" },
{ role: "quit" },
],
};
}
function buildEditMenu() {
return {
label: "Edit",
submenu: [
{ role: "undo" },
{ role: "redo" },
{ type: "separator" },
{ role: "cut" },
{ role: "copy" },
{ role: "paste" },
{ role: "pasteAndMatchStyle" },
{ role: "delete" },
{ type: "separator" },
{ role: "selectAll" },
{ type: "separator" },
{ role: "startSpeaking" },
{ role: "stopSpeaking" },
],
};
}
function buildFileMenu() {
return {
label: "File",
submenu: [{ role: "close" }],
};
}
function buildWindowMenu() {
return {
label: "Window",
submenu: [
{ role: "minimize" },
{ role: "zoom" },
{ type: "separator" },
{ role: "bringAllToFront" },
],
};
}
function toMenuItems(items = []) {
return items
.map((item) => {
if (item?.type === "divider") {
return { type: "separator" };
}
const menuItem = {
label: item.label,
};
if (
item?.children &&
Array.isArray(item.children) &&
item.children.length
) {
menuItem.submenu = toMenuItems(item.children);
} else if (item?.path) {
menuItem.action = `${SIDEBAR_MENU_ACTION_PREFIX}${item.path}`;
} else {
menuItem.enabled = false;
}
return menuItem;
})
.filter(Boolean);
}
function buildApplicationMenuTemplate() {
const env = (process.env.NODE_ENV || "development").trim();
const viewSubmenu = sidebarViewMenuSections.map((section) => ({
label: section.label,
submenu: toMenuItems(section.items || []),
}));
if (viewSubmenu.length === 0) {
viewSubmenu.push({ label: "No sidebar items available", enabled: false });
}
if (env === "development") {
viewSubmenu.push(
{ type: "separator" },
{
label: "Toggle Developer Tools",
accelerator: "i",
action: "toggle-devtools",
},
);
}
const template = [
buildFileMenu(),
buildEditMenu(),
{ label: "View", submenu: viewSubmenu },
buildWindowMenu(),
];
if (process.platform === "darwin") {
template.unshift(buildMacAppMenu());
}
return template;
}
export function applyApplicationMenu() {
ApplicationMenu.setApplicationMenu(buildApplicationMenuTemplate());
}
export function setSidebarViewMenu(sections) {
if (!Array.isArray(sections)) {
return false;
}
sidebarViewMenuSections = sections;
applyApplicationMenu();
return true;
}
export function setupApplicationMenuEvents({
onNavigate,
onToggleDevTools,
}) {
navigateHandler = onNavigate;
ApplicationMenu.on("application-menu-clicked", (event) => {
const action = event?.data?.action;
if (!action) return;
if (action === "toggle-devtools") {
onToggleDevTools?.();
return;
}
if (action.startsWith(SIDEBAR_MENU_ACTION_PREFIX)) {
const path = action.slice(SIDEBAR_MENU_ACTION_PREFIX.length);
navigateHandler?.(path || "/");
}
});
}
export function getSidebarMenuActionPrefix() {
return SIDEBAR_MENU_ACTION_PREFIX;
}