From 3c5d7777dfdbd335525bd46bdb1b2f9882fa8fda Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 10:25:47 +0200 Subject: [PATCH 01/11] pull in vendored menubar lib --- resources/js/libs/menubar/Menubar.d.ts | 73 ++++ resources/js/libs/menubar/Menubar.js | 380 ++++++++++++++++++ resources/js/libs/menubar/Menubar.spec.d.ts | 1 + resources/js/libs/menubar/Menubar.spec.js | 40 ++ resources/js/libs/menubar/README.md | 19 + resources/js/libs/menubar/index.d.ts | 18 + resources/js/libs/menubar/index.js | 39 ++ resources/js/libs/menubar/types.d.ts | 84 ++++ resources/js/libs/menubar/types.js | 2 + .../js/libs/menubar/util/cleanOptions.d.ts | 11 + .../js/libs/menubar/util/cleanOptions.js | 73 ++++ .../libs/menubar/util/cleanOptions.spec.d.ts | 1 + .../js/libs/menubar/util/cleanOptions.spec.js | 74 ++++ .../libs/menubar/util/getWindowPosition.d.ts | 23 ++ .../js/libs/menubar/util/getWindowPosition.js | 88 ++++ 15 files changed, 926 insertions(+) create mode 100644 resources/js/libs/menubar/Menubar.d.ts create mode 100644 resources/js/libs/menubar/Menubar.js create mode 100644 resources/js/libs/menubar/Menubar.spec.d.ts create mode 100644 resources/js/libs/menubar/Menubar.spec.js create mode 100644 resources/js/libs/menubar/README.md create mode 100644 resources/js/libs/menubar/index.d.ts create mode 100644 resources/js/libs/menubar/index.js create mode 100644 resources/js/libs/menubar/types.d.ts create mode 100644 resources/js/libs/menubar/types.js create mode 100644 resources/js/libs/menubar/util/cleanOptions.d.ts create mode 100644 resources/js/libs/menubar/util/cleanOptions.js create mode 100644 resources/js/libs/menubar/util/cleanOptions.spec.d.ts create mode 100644 resources/js/libs/menubar/util/cleanOptions.spec.js create mode 100644 resources/js/libs/menubar/util/getWindowPosition.d.ts create mode 100644 resources/js/libs/menubar/util/getWindowPosition.js diff --git a/resources/js/libs/menubar/Menubar.d.ts b/resources/js/libs/menubar/Menubar.d.ts new file mode 100644 index 00000000..b95d44a6 --- /dev/null +++ b/resources/js/libs/menubar/Menubar.d.ts @@ -0,0 +1,73 @@ +/// +import { EventEmitter } from 'events'; +import { BrowserWindow, Tray } from 'electron'; +import Positioner from 'electron-positioner'; +import type { Options } from './types.js'; +/** + * The main Menubar class. + * + * @noInheritDoc + */ +export declare class Menubar extends EventEmitter { + private _app; + private _browserWindow?; + private _blurTimeout; + private _isVisible; + private _cachedBounds?; + private _options; + private _positioner; + private _tray?; + constructor(app: Electron.App, options?: Partial); + /** + * The Electron [App](https://electronjs.org/docs/api/app) + * instance. + */ + get app(): Electron.App; + /** + * The [electron-positioner](https://github.com/jenslind/electron-positioner) + * instance. + */ + get positioner(): Positioner; + /** + * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. + */ + get tray(): Tray; + /** + * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) + * instance, if it's present. + */ + get window(): BrowserWindow | undefined; + /** + * Retrieve a menubar option. + * + * @param key - The option key to retrieve, see {@link Options}. + */ + getOption(key: K): Options[K]; + /** + * Hide the menubar window. + */ + hideWindow(): void; + /** + * Change an option after menubar is created. + * + * @param key - The option key to modify, see {@link Options}. + * @param value - The value to set. + */ + setOption(key: K, value: Options[K]): void; + /** + * Show the menubar window. + * + * @param trayPos - The bounds to show the window in. + */ + showWindow(trayPos?: Electron.Rectangle): Promise; + private appReady; + /** + * Callback on tray icon click or double-click. + * + * @param e + * @param bounds + */ + private clicked; + private createWindow; + private windowClear; +} diff --git a/resources/js/libs/menubar/Menubar.js b/resources/js/libs/menubar/Menubar.js new file mode 100644 index 00000000..e8a9ce23 --- /dev/null +++ b/resources/js/libs/menubar/Menubar.js @@ -0,0 +1,380 @@ +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Menubar = void 0; +var events_1 = require("events"); +var fs_1 = __importDefault(require("fs")); +var path_1 = __importDefault(require("path")); +var electron_1 = require("electron"); +var electron_positioner_1 = __importDefault(require("electron-positioner")); +var cleanOptions_1 = require("./util/cleanOptions"); +var getWindowPosition_1 = require("./util/getWindowPosition"); +/** + * The main Menubar class. + * + * @noInheritDoc + */ +var Menubar = /** @class */ (function (_super) { + __extends(Menubar, _super); + function Menubar(app, options) { + var _this = _super.call(this) || this; + _this._blurTimeout = null; // track blur events with timeout + _this._app = app; + _this._options = (0, cleanOptions_1.cleanOptions)(options); + _this._isVisible = false; + if (app.isReady()) { + // See https://github.com/maxogden/menubar/pull/151 + process.nextTick(function () { + return _this.appReady().catch(function (err) { return console.error('menubar: ', err); }); + }); + } + else { + app.on('ready', function () { + _this.appReady().catch(function (err) { return console.error('menubar: ', err); }); + }); + } + return _this; + } + Object.defineProperty(Menubar.prototype, "app", { + /** + * The Electron [App](https://electronjs.org/docs/api/app) + * instance. + */ + get: function () { + return this._app; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Menubar.prototype, "positioner", { + /** + * The [electron-positioner](https://github.com/jenslind/electron-positioner) + * instance. + */ + get: function () { + if (!this._positioner) { + throw new Error('Please access `this.positioner` after the `after-create-window` event has fired.'); + } + return this._positioner; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Menubar.prototype, "tray", { + /** + * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. + */ + get: function () { + if (!this._tray) { + throw new Error('Please access `this.tray` after the `ready` event has fired.'); + } + return this._tray; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Menubar.prototype, "window", { + /** + * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) + * instance, if it's present. + */ + get: function () { + return this._browserWindow; + }, + enumerable: false, + configurable: true + }); + /** + * Retrieve a menubar option. + * + * @param key - The option key to retrieve, see {@link Options}. + */ + Menubar.prototype.getOption = function (key) { + return this._options[key]; + }; + /** + * Hide the menubar window. + */ + Menubar.prototype.hideWindow = function () { + if (!this._browserWindow || !this._isVisible) { + return; + } + this.emit('hide'); + this._browserWindow.hide(); + this.emit('after-hide'); + this._isVisible = false; + if (this._blurTimeout) { + clearTimeout(this._blurTimeout); + this._blurTimeout = null; + } + }; + /** + * Change an option after menubar is created. + * + * @param key - The option key to modify, see {@link Options}. + * @param value - The value to set. + */ + Menubar.prototype.setOption = function (key, value) { + this._options[key] = value; + }; + /** + * Show the menubar window. + * + * @param trayPos - The bounds to show the window in. + */ + Menubar.prototype.showWindow = function (trayPos) { + return __awaiter(this, void 0, void 0, function () { + var noBoundsPosition, position, x, y; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (!this.tray) { + throw new Error('Tray should have been instantiated by now'); + } + if (!!this._browserWindow) return [3 /*break*/, 2]; + return [4 /*yield*/, this.createWindow()]; + case 1: + _a.sent(); + _a.label = 2; + case 2: + // Use guard for TypeScript, to avoid ! everywhere + if (!this._browserWindow) { + throw new Error('Window has been initialized just above. qed.'); + } + // 'Windows' taskbar: sync windows position each time before showing + // https://github.com/maxogden/menubar/issues/232 + if (['win32', 'linux'].includes(process.platform)) { + // Fill in this._options.windowPosition when taskbar position is available + this._options.windowPosition = (0, getWindowPosition_1.getWindowPosition)(this.tray); + } + this.emit('show'); + if (trayPos && trayPos.x !== 0) { + // Cache the bounds + this._cachedBounds = trayPos; + } + else if (this._cachedBounds) { + // Cached value will be used if showWindow is called without bounds data + trayPos = this._cachedBounds; + } + else if (this.tray.getBounds) { + // Get the current tray bounds + trayPos = this.tray.getBounds(); + } + noBoundsPosition = undefined; + if ((trayPos === undefined || trayPos.x === 0) && + this._options.windowPosition && + this._options.windowPosition.startsWith('tray')) { + noBoundsPosition = + process.platform === 'win32' ? 'bottomRight' : 'topRight'; + } + position = this.positioner.calculate(this._options.windowPosition || noBoundsPosition, trayPos); + x = this._options.browserWindow.x !== undefined + ? this._options.browserWindow.x + : position.x; + y = this._options.browserWindow.y !== undefined + ? this._options.browserWindow.y + : position.y; + // `.setPosition` crashed on non-integers + // https://github.com/maxogden/menubar/issues/233 + this._browserWindow.setPosition(Math.round(x), Math.round(y)); + this._browserWindow.show(); + this._isVisible = true; + this.emit('after-show'); + return [2 /*return*/]; + } + }); + }); + }; + Menubar.prototype.appReady = function () { + return __awaiter(this, void 0, void 0, function () { + var trayImage, defaultClickEvent; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (this.app.dock && !this._options.showDockIcon) { + this.app.dock.hide(); + } + if (this._options.activateWithApp) { + this.app.on('activate', function (_event, hasVisibleWindows) { + if (!hasVisibleWindows) { + _this.showWindow().catch(console.error); + } + }); + } + trayImage = this._options.icon || path_1.default.join(this._options.dir, 'IconTemplate.png'); + if (typeof trayImage === 'string' && !fs_1.default.existsSync(trayImage)) { + trayImage = path_1.default.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon + } + defaultClickEvent = this._options.showOnRightClick + ? 'right-click' + : 'click'; + this._tray = this._options.tray || new electron_1.Tray(trayImage); + // Type guards for TS not to complain + if (!this.tray) { + throw new Error('Tray has been initialized above'); + } + this.tray.on(defaultClickEvent, this.clicked.bind(this)); + this.tray.on('double-click', this.clicked.bind(this)); + this.tray.setToolTip(this._options.tooltip); + if (!this._options.windowPosition) { + this._options.windowPosition = (0, getWindowPosition_1.getWindowPosition)(this.tray); + } + if (!this._options.preloadWindow) return [3 /*break*/, 2]; + return [4 /*yield*/, this.createWindow()]; + case 1: + _a.sent(); + _a.label = 2; + case 2: + this.emit('ready'); + return [2 /*return*/]; + } + }); + }); + }; + /** + * Callback on tray icon click or double-click. + * + * @param e + * @param bounds + */ + Menubar.prototype.clicked = function (event, bounds) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { + return [2 /*return*/, this.hideWindow()]; + } + // if blur was invoked clear timeout + if (this._blurTimeout) { + clearInterval(this._blurTimeout); + } + if (this._browserWindow && this._isVisible) { + return [2 /*return*/, this.hideWindow()]; + } + this._cachedBounds = bounds || this._cachedBounds; + return [4 /*yield*/, this.showWindow(this._cachedBounds)]; + case 1: + _a.sent(); + return [2 /*return*/]; + } + }); + }); + }; + Menubar.prototype.createWindow = function () { + return __awaiter(this, void 0, void 0, function () { + var defaults; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.emit('create-window'); + defaults = { + show: false, + frame: false, // Remove window frame + }; + this._browserWindow = new electron_1.BrowserWindow(__assign(__assign({}, defaults), this._options.browserWindow)); + this._positioner = new electron_positioner_1.default(this._browserWindow); + this._browserWindow.on('blur', function () { + if (!_this._browserWindow) { + return; + } + // hack to close if icon clicked when open + _this._browserWindow.isAlwaysOnTop() + ? _this.emit('focus-lost') + : (_this._blurTimeout = setTimeout(function () { + _this.hideWindow(); + }, 100)); + }); + if (this._options.showOnAllWorkspaces !== false) { + // https://github.com/electron/electron/issues/37832#issuecomment-1497882944 + this._browserWindow.setVisibleOnAllWorkspaces(true, { + skipTransformProcessType: true, // Avoid damaging the original visible state of app.dock + }); + } + this._browserWindow.on('close', this.windowClear.bind(this)); + this.emit('before-load'); + if (!(this._options.index !== false)) return [3 /*break*/, 2]; + return [4 /*yield*/, this._browserWindow.loadURL(this._options.index, this._options.loadUrlOptions)]; + case 1: + _a.sent(); + _a.label = 2; + case 2: + this.emit('after-create-window'); + return [2 /*return*/]; + } + }); + }); + }; + Menubar.prototype.windowClear = function () { + this._browserWindow = undefined; + this.emit('after-close'); + }; + return Menubar; +}(events_1.EventEmitter)); +exports.Menubar = Menubar; diff --git a/resources/js/libs/menubar/Menubar.spec.d.ts b/resources/js/libs/menubar/Menubar.spec.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/resources/js/libs/menubar/Menubar.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/resources/js/libs/menubar/Menubar.spec.js b/resources/js/libs/menubar/Menubar.spec.js new file mode 100644 index 00000000..11d875a4 --- /dev/null +++ b/resources/js/libs/menubar/Menubar.spec.js @@ -0,0 +1,40 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var electron_1 = require("electron"); +var Menubar_1 = require("./Menubar"); +describe('Menubar', function () { + var mb; + beforeEach(function () { + mb = new Menubar_1.Menubar(electron_1.app, { preloadWindow: true }); + }); + it('should have property `app`', function () { + expect(mb.app).toBeDefined(); + }); + it('should have property `positioner`', function () { + expect(function () { return mb.positioner; }).toThrow(); + return new Promise(function (resolve) { + mb.on('after-create-window', function () { + expect(mb.positioner).toBeDefined(); + resolve(); + }); + }); + }); + it('should have property `tray`', function () { + expect(function () { return mb.tray; }).toThrow(); + return new Promise(function (resolve) { + mb.on('ready', function () { + expect(mb.tray).toBeInstanceOf(electron_1.Tray); + resolve(); + }); + }); + }); + it('should have property `window`', function () { + expect(mb.window).toBeUndefined(); + return new Promise(function (resolve) { + mb.on('ready', function () { + expect(mb.window).toBeInstanceOf(electron_1.BrowserWindow); + resolve(); + }); + }); + }); +}); diff --git a/resources/js/libs/menubar/README.md b/resources/js/libs/menubar/README.md new file mode 100644 index 00000000..99c7681c --- /dev/null +++ b/resources/js/libs/menubar/README.md @@ -0,0 +1,19 @@ +# Menubar Library + +This is a vendored copy of the [menubar](https://github.com/max-mapper/menubar) library, originally created by max-mapper. + +This library is pulled in from the https://github.com/max-mapper/menubar repository. The package sadly is not actively maintained, preventing our ability to update Electron dependencies in a timely manner. + +We decided to pull the lib in directly instead of maintaining a fork to: + +- Control our dependency update timeline +- Ensure compatibility with newer Electron versions +- Maintain stability for NativePHP desktop applications + +## About Menubar + +Menubar is a high-level Electron library for creating desktop menubar applications. It provides boilerplate for setting up a menubar application using Electron. + +## NativePHP Integration + +This vendored copy is specifically maintained for use within the NativePHP Electron backend, enabling PHP developers to create native desktop applications with menubar functionality. diff --git a/resources/js/libs/menubar/index.d.ts b/resources/js/libs/menubar/index.d.ts new file mode 100644 index 00000000..a151f206 --- /dev/null +++ b/resources/js/libs/menubar/index.d.ts @@ -0,0 +1,18 @@ +/** + * Entry point of menubar + * @example + * ```typescript + * import { menubar } from 'menubar'; + * ``` + */ +import { Menubar } from './Menubar.js'; +import type { Options } from './types.js'; +export * from './util/getWindowPosition.js'; +export { Menubar }; +/** + * Factory function to create a menubar application + * + * @param options - Options for creating a menubar application, see + * {@link Options} + */ +export declare function menubar(options?: Partial): Menubar; diff --git a/resources/js/libs/menubar/index.js b/resources/js/libs/menubar/index.js new file mode 100644 index 00000000..b4dc6d3b --- /dev/null +++ b/resources/js/libs/menubar/index.js @@ -0,0 +1,39 @@ +"use strict"; +/** + * Entry point of menubar + * @example + * ```typescript + * import { menubar } from 'menubar'; + * ``` + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.menubar = exports.Menubar = void 0; +/** */ +var electron_1 = require("electron"); +var Menubar_1 = require("./Menubar"); +Object.defineProperty(exports, "Menubar", { enumerable: true, get: function () { return Menubar_1.Menubar; } }); +__exportStar(require("./util/getWindowPosition"), exports); +/** + * Factory function to create a menubar application + * + * @param options - Options for creating a menubar application, see + * {@link Options} + */ +function menubar(options) { + return new Menubar_1.Menubar(electron_1.app, options); +} +exports.menubar = menubar; diff --git a/resources/js/libs/menubar/types.d.ts b/resources/js/libs/menubar/types.d.ts new file mode 100644 index 00000000..238a0f02 --- /dev/null +++ b/resources/js/libs/menubar/types.d.ts @@ -0,0 +1,84 @@ +import type { BrowserWindowConstructorOptions, LoadURLOptions, Tray } from 'electron'; +/** + * Options for creating a menubar application + */ +export interface Options { + /** + * Listen on `app.on('activate')` to open menubar when app is activated. + * @default `true` + */ + activateWithApp?: boolean; + /** + * An Electron BrowserWindow instance, or an options object to be passed into + * the BrowserWindow constructor. + * @example + * ```typescript + * const options = { height: 640, width: 480 }; + * + * const mb = new Menubar({ + * browserWindow: options + * }); + * ``` + */ + browserWindow: BrowserWindowConstructorOptions; + /** + * The app source directory. + */ + dir: string; + /** + * The png icon to use for the menubar. A good size to start with is 20x20. + * To support retina, supply a 2x sized image (e.g. 40x40) with @2x added to + * the end of the name, so icon.png and icon@2x.png and Electron will + * automatically use your @2x version on retina screens. + */ + icon?: string | Electron.NativeImage; + /** + * The URL to load the menubar's browserWindow with. The url can be a remote + * address (e.g. `http://`) or a path to a local HTML file using the + * `file://` protocol. If false, then menubar won't call `loadURL` on + * start. + * @default `file:// + options.dir + index.html` + * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options + */ + index: string | false; + /** + * The options passed when loading the index URL in the menubar's + * browserWindow. Everything browserWindow.loadURL supports is supported; + * this object is simply passed onto browserWindow.loadURL + * @default `{}` + * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options + */ + loadUrlOptions?: LoadURLOptions; + /** + * Create BrowserWindow instance before it is used -- increasing resource + * usage, but making the click on the menubar load faster. + */ + preloadWindow?: boolean; + /** + * Configure the visibility of the application dock icon, macOS only. Calls + * [`app.dock.hide`](https://electronjs.org/docs/api/app#appdockhide-macos). + */ + showDockIcon?: boolean; + /** + * Makes the window available on all OS X workspaces. Calls + * [`setVisibleOnAllWorkspaces`](https://electronjs.org/docs/api/browser-window#winsetvisibleonallworkspacesvisible-options). + */ + showOnAllWorkspaces?: boolean; + /** + * Show the window on 'right-click' event instead of regular 'click'. + */ + showOnRightClick?: boolean; + /** + * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip). + */ + tooltip: string; + /** + * An electron Tray instance. If provided, `options.icon` will be ignored. + */ + tray?: Tray; + /** + * Sets the window position (x and y will still override this), check + * electron-positioner docs for valid values. + */ + windowPosition?: 'trayLeft' | 'trayBottomLeft' | 'trayRight' | 'trayBottomRight' | 'trayCenter' | 'trayBottomCenter' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'topCenter' | 'bottomCenter' | 'leftCenter' | 'rightCenter' | 'center'; +} diff --git a/resources/js/libs/menubar/types.js b/resources/js/libs/menubar/types.js new file mode 100644 index 00000000..c8ad2e54 --- /dev/null +++ b/resources/js/libs/menubar/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/resources/js/libs/menubar/util/cleanOptions.d.ts b/resources/js/libs/menubar/util/cleanOptions.d.ts new file mode 100644 index 00000000..5ecb864c --- /dev/null +++ b/resources/js/libs/menubar/util/cleanOptions.d.ts @@ -0,0 +1,11 @@ +/** + * @ignore + */ +import type { Options } from '../types'; +/** + * Take as input some options, and return a sanitized version of it. + * + * @param opts - The options to clean. + * @ignore + */ +export declare function cleanOptions(opts?: Partial): Options; diff --git a/resources/js/libs/menubar/util/cleanOptions.js b/resources/js/libs/menubar/util/cleanOptions.js new file mode 100644 index 00000000..b23bab40 --- /dev/null +++ b/resources/js/libs/menubar/util/cleanOptions.js @@ -0,0 +1,73 @@ +"use strict"; +/** + * @ignore + */ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.cleanOptions = void 0; +/** */ +var path_1 = __importDefault(require("path")); +var url_1 = __importDefault(require("url")); +var electron_1 = require("electron"); +var DEFAULT_WINDOW_HEIGHT = 400; +var DEFAULT_WINDOW_WIDTH = 400; +/** + * Take as input some options, and return a sanitized version of it. + * + * @param opts - The options to clean. + * @ignore + */ +function cleanOptions(opts) { + var options = __assign({}, opts); + if (options.activateWithApp === undefined) { + options.activateWithApp = true; + } + if (!options.dir) { + options.dir = electron_1.app.getAppPath(); + } + if (!path_1.default.isAbsolute(options.dir)) { + options.dir = path_1.default.resolve(options.dir); + } + // Note: options.index can be `false` + if (options.index === undefined) { + options.index = url_1.default.format({ + pathname: path_1.default.join(options.dir, 'index.html'), + protocol: 'file:', + slashes: true, + }); + } + options.loadUrlOptions = options.loadUrlOptions || {}; + options.tooltip = options.tooltip || ''; + // `icon`, `preloadWindow`, `showDockIcon`, `showOnAllWorkspaces`, + // `showOnRightClick` don't need any special treatment + // Now we take care of `browserWindow` + if (!options.browserWindow) { + options.browserWindow = {}; + } + // Set width/height on options to be usable before the window is created + options.browserWindow.width = + // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so + // that users can put a 0 width + options.browserWindow.width !== undefined + ? options.browserWindow.width + : DEFAULT_WINDOW_WIDTH; + options.browserWindow.height = + options.browserWindow.height !== undefined + ? options.browserWindow.height + : DEFAULT_WINDOW_HEIGHT; + return options; +} +exports.cleanOptions = cleanOptions; diff --git a/resources/js/libs/menubar/util/cleanOptions.spec.d.ts b/resources/js/libs/menubar/util/cleanOptions.spec.d.ts new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/resources/js/libs/menubar/util/cleanOptions.spec.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/resources/js/libs/menubar/util/cleanOptions.spec.js b/resources/js/libs/menubar/util/cleanOptions.spec.js new file mode 100644 index 00000000..45788802 --- /dev/null +++ b/resources/js/libs/menubar/util/cleanOptions.spec.js @@ -0,0 +1,74 @@ +"use strict"; +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var path = __importStar(require("path")); +var electron_1 = require("../__mocks__/electron"); +var cleanOptions_1 = require("./cleanOptions"); +var DEFAULT_OPTIONS = { + activateWithApp: true, + browserWindow: { + height: 400, + width: 400, + }, + dir: path.resolve(electron_1.MOCK_APP_GETAPPPATH), + index: "file://".concat(path.join(path.resolve(electron_1.MOCK_APP_GETAPPPATH), 'index.html')), + loadUrlOptions: {}, + tooltip: '', +}; +describe('cleanOptions', function () { + it('should handle undefined', function () { + expect((0, cleanOptions_1.cleanOptions)(undefined)).toEqual(DEFAULT_OPTIONS); + }); + it('should handle a dir string with relative path', function () { + expect((0, cleanOptions_1.cleanOptions)({ dir: 'MY_RELATIVE_PATH' })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { dir: path.resolve('MY_RELATIVE_PATH'), index: "file://".concat(path.join(path.resolve('MY_RELATIVE_PATH'), 'index.html')) })); + }); + it('should handle a dir string with absolute path', function () { + expect((0, cleanOptions_1.cleanOptions)({ dir: '/home/me/MY_ABSOLUTE_PATH' })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { dir: '/home/me/MY_ABSOLUTE_PATH', index: 'file:///home/me/MY_ABSOLUTE_PATH/index.html' })); + }); + it('should handle a false index', function () { + expect((0, cleanOptions_1.cleanOptions)({ index: false })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { index: false })); + }); + it('should handle an object with multiple fields', function () { + expect((0, cleanOptions_1.cleanOptions)({ + browserWindow: { + height: 100, + }, + index: 'file:///home/abc/index.html', + showDockIcon: true, + windowPosition: 'trayCenter', + })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { browserWindow: __assign(__assign({}, DEFAULT_OPTIONS.browserWindow), { height: 100 }), index: 'file:///home/abc/index.html', showDockIcon: true, windowPosition: 'trayCenter' })); + }); +}); diff --git a/resources/js/libs/menubar/util/getWindowPosition.d.ts b/resources/js/libs/menubar/util/getWindowPosition.d.ts new file mode 100644 index 00000000..9b9d04a9 --- /dev/null +++ b/resources/js/libs/menubar/util/getWindowPosition.d.ts @@ -0,0 +1,23 @@ +/** + * Utilities to get taskbar position and consequently menubar's position + */ +/** */ +import { type Tray } from 'electron'; +type TaskbarLocation = 'top' | 'bottom' | 'left' | 'right'; +/** + * Determine taskbard location: "top", "bottom", "left" or "right". + * + * Only tested on Windows for now, and only used in Windows. + * + * @param tray - The Electron Tray instance. + */ +export declare function taskbarLocation(tray: Tray): TaskbarLocation; +type WindowPosition = 'trayCenter' | 'topRight' | 'trayBottomCenter' | 'bottomLeft' | 'bottomRight'; +/** + * Depending on where the taskbar is, determine where the window should be + * positioned. + * + * @param tray - The Electron Tray instance. + */ +export declare function getWindowPosition(tray: Tray): WindowPosition; +export {}; diff --git a/resources/js/libs/menubar/util/getWindowPosition.js b/resources/js/libs/menubar/util/getWindowPosition.js new file mode 100644 index 00000000..c568ab54 --- /dev/null +++ b/resources/js/libs/menubar/util/getWindowPosition.js @@ -0,0 +1,88 @@ +"use strict"; +/** + * Utilities to get taskbar position and consequently menubar's position + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getWindowPosition = exports.taskbarLocation = void 0; +/** */ +var electron_1 = require("electron"); +var isLinux = process.platform === 'linux'; +var trayToScreenRects = function (tray) { + // There may be more than one screen, so we need to figure out on which screen our tray icon lives. + var _a = electron_1.screen.getDisplayMatching(tray.getBounds()), workArea = _a.workArea, screenBounds = _a.bounds; + workArea.x -= screenBounds.x; + workArea.y -= screenBounds.y; + return [screenBounds, workArea]; +}; +/** + * Determine taskbard location: "top", "bottom", "left" or "right". + * + * Only tested on Windows for now, and only used in Windows. + * + * @param tray - The Electron Tray instance. + */ +function taskbarLocation(tray) { + var _a = trayToScreenRects(tray), screenBounds = _a[0], workArea = _a[1]; + // TASKBAR LEFT + if (workArea.x > 0) { + // Most likely Ubuntu hence assuming the window should be on top + if (isLinux && workArea.y > 0) + return 'top'; + // The workspace starts more on the right + return 'left'; + } + // TASKBAR TOP + if (workArea.y > 0) { + return 'top'; + } + // TASKBAR RIGHT + // Here both workArea.y and workArea.x are 0 so we can no longer leverage them. + // We can use the workarea and display width though. + // Determine taskbar location + if (workArea.width < screenBounds.width) { + // The taskbar is either on the left or right, but since the LEFT case was handled above, + // we can be sure we're dealing with a right taskbar + return 'right'; + } + // TASKBAR BOTTOM + // Since all the other cases were handled, we can be sure we're dealing with a bottom taskbar + return 'bottom'; +} +exports.taskbarLocation = taskbarLocation; +/** + * Depending on where the taskbar is, determine where the window should be + * positioned. + * + * @param tray - The Electron Tray instance. + */ +function getWindowPosition(tray) { + switch (process.platform) { + // macOS + // Supports top taskbars + case 'darwin': + return 'trayCenter'; + // Linux + // Windows + // Supports top/bottom/left/right taskbar + case 'linux': + case 'win32': { + var traySide = taskbarLocation(tray); + // Assign position for menubar + if (traySide === 'top') { + return isLinux ? 'topRight' : 'trayCenter'; + } + if (traySide === 'bottom') { + return 'bottomRight'; + } + if (traySide === 'left') { + return 'bottomLeft'; + } + if (traySide === 'right') { + return 'bottomRight'; + } + } + } + // When we really don't know, we just show the menubar on the top-right + return 'topRight'; +} +exports.getWindowPosition = getWindowPosition; From 5edc1ad047be6319d4e5c2ece7b39f4585cf4470 Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 10:26:09 +0200 Subject: [PATCH 02/11] swap import with vendored lib --- resources/js/electron-plugin/src/server/api/menuBar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/electron-plugin/src/server/api/menuBar.ts b/resources/js/electron-plugin/src/server/api/menuBar.ts index 90b3b48b..18a43445 100644 --- a/resources/js/electron-plugin/src/server/api/menuBar.ts +++ b/resources/js/electron-plugin/src/server/api/menuBar.ts @@ -2,7 +2,7 @@ import express from "express"; import { app, Menu, Tray } from "electron"; import { compileMenu } from "./helper/index.js"; import state from "../state.js"; -import { menubar } from "menubar"; +import { menubar } from "../../../../libs/menubar/index.js"; import { notifyLaravel } from "../utils.js"; import { fileURLToPath } from 'url' import { enable } from "@electron/remote/main/index.js"; From b45c3deeeb5308301c38249e5e298a54e1801c5f Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 10:43:01 +0200 Subject: [PATCH 03/11] pull in menubar's positioner dependency --- resources/js/libs/menubar/Menubar.d.ts | 2 +- resources/js/libs/positioner/README.md | 5 + resources/js/libs/positioner/index.js | 168 +++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 resources/js/libs/positioner/README.md create mode 100644 resources/js/libs/positioner/index.js diff --git a/resources/js/libs/menubar/Menubar.d.ts b/resources/js/libs/menubar/Menubar.d.ts index b95d44a6..f77b64f2 100644 --- a/resources/js/libs/menubar/Menubar.d.ts +++ b/resources/js/libs/menubar/Menubar.d.ts @@ -1,7 +1,7 @@ /// import { EventEmitter } from 'events'; import { BrowserWindow, Tray } from 'electron'; -import Positioner from 'electron-positioner'; +import Positioner from '../positioner/index.js'; import type { Options } from './types.js'; /** * The main Menubar class. diff --git a/resources/js/libs/positioner/README.md b/resources/js/libs/positioner/README.md new file mode 100644 index 00000000..b901efd3 --- /dev/null +++ b/resources/js/libs/positioner/README.md @@ -0,0 +1,5 @@ +# Electron Positioner Library + +This is a vendored copy of the [electron-positioner](https://github.com/jenslind/electron-positioner) library. Which is the `menubar` vendored lib's only dependency. + +The lib has not been updated for a long time. Since we're vendoring `menubar` we've decided to pull this in too, instead of depending on another unmaintained library in package.json. diff --git a/resources/js/libs/positioner/index.js b/resources/js/libs/positioner/index.js new file mode 100644 index 00000000..f7311a37 --- /dev/null +++ b/resources/js/libs/positioner/index.js @@ -0,0 +1,168 @@ +"use strict"; + +module.exports = class Positioner { + constructor(browserWindow) { + this.browserWindow = browserWindow; + this.electronScreen = require("electron").screen; + } + + _getCoords(position, trayPosition) { + let screenSize = this._getScreenSize(trayPosition); + let windowSize = this._getWindowSize(); + + if (trayPosition === undefined) trayPosition = {}; + + // Positions + let positions = { + trayLeft: { + x: Math.floor(trayPosition.x), + y: screenSize.y, + }, + trayBottomLeft: { + x: Math.floor(trayPosition.x), + y: Math.floor( + screenSize.height - (windowSize[1] - screenSize.y), + ), + }, + trayRight: { + x: Math.floor( + trayPosition.x - windowSize[0] + trayPosition.width, + ), + y: screenSize.y, + }, + trayBottomRight: { + x: Math.floor( + trayPosition.x - windowSize[0] + trayPosition.width, + ), + y: Math.floor( + screenSize.height - (windowSize[1] - screenSize.y), + ), + }, + trayCenter: { + x: Math.floor( + trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2, + ), + y: screenSize.y, + }, + trayBottomCenter: { + x: Math.floor( + trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2, + ), + y: Math.floor( + screenSize.height - (windowSize[1] - screenSize.y), + ), + }, + topLeft: { + x: screenSize.x, + y: screenSize.y, + }, + topRight: { + x: Math.floor( + screenSize.x + (screenSize.width - windowSize[0]), + ), + y: screenSize.y, + }, + bottomLeft: { + x: screenSize.x, + y: Math.floor( + screenSize.height - (windowSize[1] - screenSize.y), + ), + }, + bottomRight: { + x: Math.floor( + screenSize.x + (screenSize.width - windowSize[0]), + ), + y: Math.floor( + screenSize.height - (windowSize[1] - screenSize.y), + ), + }, + topCenter: { + x: Math.floor( + screenSize.x + (screenSize.width / 2 - windowSize[0] / 2), + ), + y: screenSize.y, + }, + bottomCenter: { + x: Math.floor( + screenSize.x + (screenSize.width / 2 - windowSize[0] / 2), + ), + y: Math.floor( + screenSize.height - (windowSize[1] - screenSize.y), + ), + }, + leftCenter: { + x: screenSize.x, + y: + screenSize.y + + Math.floor(screenSize.height / 2) - + Math.floor(windowSize[1] / 2), + }, + rightCenter: { + x: Math.floor( + screenSize.x + (screenSize.width - windowSize[0]), + ), + y: + screenSize.y + + Math.floor(screenSize.height / 2) - + Math.floor(windowSize[1] / 2), + }, + center: { + x: Math.floor( + screenSize.x + (screenSize.width / 2 - windowSize[0] / 2), + ), + y: Math.floor( + (screenSize.height + screenSize.y) / 2 - windowSize[1] / 2, + ), + }, + }; + + // Default to right if the window is bigger than the space left. + // Because on Windows the window might get out of bounds and dissappear. + if (position.substr(0, 4) === "tray") { + if ( + positions[position].x + windowSize[0] > + screenSize.width + screenSize.x + ) { + return { + x: positions["topRight"].x, + y: positions[position].y, + }; + } + } + + return positions[position]; + } + + _getWindowSize() { + return this.browserWindow.getSize(); + } + + _getScreenSize(trayPosition) { + if (trayPosition) { + return this.electronScreen.getDisplayMatching(trayPosition) + .workArea; + } else { + return this.electronScreen.getDisplayNearestPoint( + this.electronScreen.getCursorScreenPoint(), + ).workArea; + } + } + + move(position, trayPos) { + // Get positions coords + var coords = this._getCoords(position, trayPos); + + // Set the windows position + this.browserWindow.setPosition(coords.x, coords.y); + } + + calculate(position, trayPos) { + // Get positions coords + var coords = this._getCoords(position, trayPos); + + return { + x: coords.x, + y: coords.y, + }; + } +}; From dd2380c15450e7d23d3187ee8fb1013672d416f6 Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 10:44:13 +0200 Subject: [PATCH 04/11] remove menubar dependency --- resources/js/package-lock.json | 25 +------ resources/js/package.json | 1 - resources/js/yarn.lock | 117 ++++++++++++++++++++++++++++----- 3 files changed, 103 insertions(+), 40 deletions(-) diff --git a/resources/js/package-lock.json b/resources/js/package-lock.json index b1ed4a29..6b5fea11 100644 --- a/resources/js/package-lock.json +++ b/resources/js/package-lock.json @@ -22,7 +22,6 @@ "fs-extra": "^11.2.0", "get-port": "^7.1.0", "kill-sync": "^1.0.3", - "menubar": "^9.5.1", "nodemon": "^3.1.9", "ps-node": "^0.1.6", "tree-kill": "^1.2.2", @@ -5515,9 +5514,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001739", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz", - "integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==", + "version": "1.0.30001741", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", + "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", "dev": true, "funding": [ { @@ -6825,12 +6824,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/electron-positioner": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/electron-positioner/-/electron-positioner-4.1.0.tgz", - "integrity": "sha512-726DfbI9ZNoCg+Fcu6XLuTKTnzf+6nFqv7h+K/V6Ug7IbaPMI7s9S8URnGtWFCy5N5PL4HSzRFF2mXuinftDdg==", - "license": "MIT" - }, "node_modules/electron-publish": { "version": "25.1.7", "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz", @@ -9768,18 +9761,6 @@ "node": ">= 0.8" } }, - "node_modules/menubar": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/menubar/-/menubar-9.5.1.tgz", - "integrity": "sha512-swfgKal+DTgJINay36X+LGBSqyFKS4d9FyJ2w0s/4MtO7/UGplEZqluLTnq4xgLNxNjMWhXycOELP+rRYpTagA==", - "license": "BSD-2-Clause", - "dependencies": { - "electron-positioner": "^4.1.0" - }, - "peerDependencies": { - "electron": ">=9.0.0 <33.0.0" - } - }, "node_modules/meow": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", diff --git a/resources/js/package.json b/resources/js/package.json index 30d691ee..779a5fbe 100644 --- a/resources/js/package.json +++ b/resources/js/package.json @@ -51,7 +51,6 @@ "fs-extra": "^11.2.0", "get-port": "^7.1.0", "kill-sync": "^1.0.3", - "menubar": "^9.5.1", "nodemon": "^3.1.9", "ps-node": "^0.1.6", "tree-kill": "^1.2.2", diff --git a/resources/js/yarn.lock b/resources/js/yarn.lock index d296defe..c99d976d 100644 --- a/resources/js/yarn.lock +++ b/resources/js/yarn.lock @@ -1047,10 +1047,10 @@ resolved "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== -"@esbuild/linux-x64@0.25.9": +"@esbuild/darwin-arm64@0.25.9": version "0.25.9" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz" - integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz" + integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.1", "@eslint-community/eslint-utils@^4.7.0": version "4.8.0" @@ -1273,15 +1273,10 @@ resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@rollup/rollup-linux-x64-gnu@4.50.0": +"@rollup/rollup-darwin-arm64@4.50.0": version "4.50.0" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz" - integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== - -"@rollup/rollup-linux-x64-musl@4.50.0": - version "4.50.0" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz" - integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz" + integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== "@rushstack/eslint-patch@^1.10.4": version "1.12.0" @@ -1465,6 +1460,14 @@ resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== +"@types/plist@^3.0.1": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz" + integrity sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA== + dependencies: + "@types/node" "*" + xmlbuilder ">=11.0.1" + "@types/ps-node@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@types/ps-node/-/ps-node-0.1.3.tgz" @@ -1504,6 +1507,11 @@ "@types/node" "*" "@types/send" "*" +"@types/verror@^1.10.3": + version "1.10.11" + resolved "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz" + integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg== + "@types/yauzl@^2.9.1": version "2.10.3" resolved "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz" @@ -1764,7 +1772,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1955,6 +1963,11 @@ array-union@^2.1.0: resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz" @@ -2129,7 +2142,7 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.5.0: +buffer@^5.1.0, buffer@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2349,6 +2362,14 @@ cli-spinners@^2.5.0: resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-truncate@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz" @@ -2506,7 +2527,7 @@ core-js-compat@^3.40.0, core-js-compat@^3.43.0: dependencies: browserslist "^4.25.3" -core-util-is@~1.0.0: +core-util-is@~1.0.0, core-util-is@1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== @@ -2526,6 +2547,13 @@ crc-32@^1.2.0: resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" + crc32-stream@^4.0.2: version "4.0.3" resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz" @@ -2694,6 +2722,20 @@ dmg-builder@25.1.8: optionalDependencies: dmg-license "^1.0.11" +dmg-license@^1.0.11: + version "1.0.11" + resolved "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz" + integrity sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q== + dependencies: + "@types/plist" "^3.0.1" + "@types/verror" "^1.10.3" + ajv "^6.10.0" + crc "^3.8.0" + iconv-corefoundation "^1.1.7" + plist "^3.0.4" + smart-buffer "^4.0.2" + verror "^1.10.0" + dot-prop@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz" @@ -3240,6 +3282,11 @@ extract-zip@^2.0.0, extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -3487,6 +3534,11 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -3854,6 +3906,14 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +iconv-corefoundation@^1.1.7: + version "1.1.7" + resolved "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz" + integrity sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ== + dependencies: + cli-truncate "^2.1.0" + node-addon-api "^1.6.3" + iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" @@ -4724,6 +4784,11 @@ node-abi@^3.45.0: dependencies: semver "^7.3.5" +node-addon-api@^1.6.3: + version "1.7.2" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz" + integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== + node-api-version@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz" @@ -5021,7 +5086,7 @@ pify@^4.0.1: resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -plist@^3.0.5, plist@^3.1.0: +plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -5670,6 +5735,15 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" @@ -5687,7 +5761,7 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -smart-buffer@^4.2.0: +smart-buffer@^4.0.2, smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== @@ -6377,6 +6451,15 @@ vary@^1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +verror@^1.10.0: + version "1.10.1" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz" + integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vite-node@3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz" @@ -6522,7 +6605,7 @@ write-file-atomic@^5.0.1: imurmurhash "^0.1.4" signal-exit "^4.0.1" -xmlbuilder@^15.1.1: +xmlbuilder@^15.1.1, xmlbuilder@>=11.0.1: version "15.1.1" resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== From 29036646aa94682787a3b71be21e0ea4de9efd2e Mon Sep 17 00:00:00 2001 From: gwleuverink <17123491+gwleuverink@users.noreply.github.com> Date: Fri, 5 Sep 2025 08:47:47 +0000 Subject: [PATCH 05/11] Build plugin --- .../dist/server/api/menuBar.js | 2 +- resources/js/yarn.lock | 137 +++--------------- 2 files changed, 22 insertions(+), 117 deletions(-) diff --git a/resources/js/electron-plugin/dist/server/api/menuBar.js b/resources/js/electron-plugin/dist/server/api/menuBar.js index 21ee49d4..489f04a8 100644 --- a/resources/js/electron-plugin/dist/server/api/menuBar.js +++ b/resources/js/electron-plugin/dist/server/api/menuBar.js @@ -2,7 +2,7 @@ import express from "express"; import { app, Menu, Tray } from "electron"; import { compileMenu } from "./helper/index.js"; import state from "../state.js"; -import { menubar } from "menubar"; +import { menubar } from "../../../../libs/menubar/index.js"; import { notifyLaravel } from "../utils.js"; import { fileURLToPath } from 'url'; import { enable } from "@electron/remote/main/index.js"; diff --git a/resources/js/yarn.lock b/resources/js/yarn.lock index c99d976d..3634f789 100644 --- a/resources/js/yarn.lock +++ b/resources/js/yarn.lock @@ -1047,10 +1047,10 @@ resolved "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== -"@esbuild/darwin-arm64@0.25.9": +"@esbuild/linux-x64@0.25.9": version "0.25.9" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz" - integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz" + integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.1", "@eslint-community/eslint-utils@^4.7.0": version "4.8.0" @@ -1273,10 +1273,15 @@ resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@rollup/rollup-darwin-arm64@4.50.0": +"@rollup/rollup-linux-x64-gnu@4.50.0": version "4.50.0" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz" - integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz" + integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== + +"@rollup/rollup-linux-x64-musl@4.50.0": + version "4.50.0" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz" + integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== "@rushstack/eslint-patch@^1.10.4": version "1.12.0" @@ -1460,14 +1465,6 @@ resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== -"@types/plist@^3.0.1": - version "3.0.5" - resolved "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz" - integrity sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA== - dependencies: - "@types/node" "*" - xmlbuilder ">=11.0.1" - "@types/ps-node@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@types/ps-node/-/ps-node-0.1.3.tgz" @@ -1507,11 +1504,6 @@ "@types/node" "*" "@types/send" "*" -"@types/verror@^1.10.3": - version "1.10.11" - resolved "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz" - integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg== - "@types/yauzl@^2.9.1": version "2.10.3" resolved "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz" @@ -1772,7 +1764,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: +ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1963,11 +1955,6 @@ array-union@^2.1.0: resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz" @@ -2142,7 +2129,7 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.1.0, buffer@^5.5.0: +buffer@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2275,9 +2262,9 @@ callsites@^3.0.0: integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== caniuse-lite@^1.0.30001737: - version "1.0.30001739" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz" - integrity sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA== + version "1.0.30001741" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz" + integrity sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw== chai@^5.2.0: version "5.3.3" @@ -2362,14 +2349,6 @@ cli-spinners@^2.5.0: resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - cli-truncate@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz" @@ -2527,7 +2506,7 @@ core-js-compat@^3.40.0, core-js-compat@^3.43.0: dependencies: browserslist "^4.25.3" -core-util-is@~1.0.0, core-util-is@1.0.2: +core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== @@ -2547,13 +2526,6 @@ crc-32@^1.2.0: resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== -crc@^3.8.0: - version "3.8.0" - resolved "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz" - integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== - dependencies: - buffer "^5.1.0" - crc32-stream@^4.0.2: version "4.0.3" resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz" @@ -2722,20 +2694,6 @@ dmg-builder@25.1.8: optionalDependencies: dmg-license "^1.0.11" -dmg-license@^1.0.11: - version "1.0.11" - resolved "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz" - integrity sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q== - dependencies: - "@types/plist" "^3.0.1" - "@types/verror" "^1.10.3" - ajv "^6.10.0" - crc "^3.8.0" - iconv-corefoundation "^1.1.7" - plist "^3.0.4" - smart-buffer "^4.0.2" - verror "^1.10.0" - dot-prop@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz" @@ -2838,11 +2796,6 @@ electron-is-dev@^3.0.1: resolved "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-3.0.1.tgz" integrity sha512-8TjjAh8Ec51hUi3o4TaU0mD3GMTOESi866oRNavj9A3IQJ7pmv+MJVmdZBFGw4GFT36X7bkqnuDNYvkQgvyI8Q== -electron-positioner@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/electron-positioner/-/electron-positioner-4.1.0.tgz" - integrity sha512-726DfbI9ZNoCg+Fcu6XLuTKTnzf+6nFqv7h+K/V6Ug7IbaPMI7s9S8URnGtWFCy5N5PL4HSzRFF2mXuinftDdg== - electron-publish@25.1.7: version "25.1.7" resolved "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz" @@ -2903,7 +2856,7 @@ electron-window-state@^5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@^32.2.7, "electron@>= 13.0.0", electron@>=13.0.0, "electron@>=9.0.0 <33.0.0": +electron@^32.2.7, "electron@>= 13.0.0", electron@>=13.0.0: version "32.3.3" resolved "https://registry.npmjs.org/electron/-/electron-32.3.3.tgz" integrity sha512-7FT8tDg+MueAw8dBn5LJqDvlM4cZkKJhXfgB3w7P5gvSoUQVAY6LIQcXJxgL+vw2rIRY/b9ak7ZBFbCMF2Bk4w== @@ -3282,11 +3235,6 @@ extract-zip@^2.0.0, extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -3534,11 +3482,6 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -3906,14 +3849,6 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-corefoundation@^1.1.7: - version "1.1.7" - resolved "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz" - integrity sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ== - dependencies: - cli-truncate "^2.1.0" - node-addon-api "^1.6.3" - iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" @@ -4501,13 +4436,6 @@ media-typer@^1.1.0: resolved "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz" integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== -menubar@^9.5.1: - version "9.5.1" - resolved "https://registry.npmjs.org/menubar/-/menubar-9.5.1.tgz" - integrity sha512-swfgKal+DTgJINay36X+LGBSqyFKS4d9FyJ2w0s/4MtO7/UGplEZqluLTnq4xgLNxNjMWhXycOELP+rRYpTagA== - dependencies: - electron-positioner "^4.1.0" - meow@^13.2.0: version "13.2.0" resolved "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz" @@ -4784,11 +4712,6 @@ node-abi@^3.45.0: dependencies: semver "^7.3.5" -node-addon-api@^1.6.3: - version "1.7.2" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz" - integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== - node-api-version@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz" @@ -5086,7 +5009,7 @@ pify@^4.0.1: resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: +plist@^3.0.5, plist@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -5735,15 +5658,6 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" @@ -5761,7 +5675,7 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -smart-buffer@^4.0.2, smart-buffer@^4.2.0: +smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== @@ -6451,15 +6365,6 @@ vary@^1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -verror@^1.10.0: - version "1.10.1" - resolved "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz" - integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - vite-node@3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz" @@ -6605,7 +6510,7 @@ write-file-atomic@^5.0.1: imurmurhash "^0.1.4" signal-exit "^4.0.1" -xmlbuilder@^15.1.1, xmlbuilder@>=11.0.1: +xmlbuilder@^15.1.1: version "15.1.1" resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== From 905e071e31dcffb71df261d5c748518015648530 Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 12:53:30 +0200 Subject: [PATCH 06/11] replace with original ts files --- resources/js/libs/menubar/Menubar.d.ts | 73 ---- resources/js/libs/menubar/Menubar.js | 380 ------------------ resources/js/libs/menubar/Menubar.spec.d.ts | 1 - resources/js/libs/menubar/Menubar.spec.js | 40 -- resources/js/libs/menubar/Menubar.spec.ts | 45 +++ resources/js/libs/menubar/Menubar.ts | 326 +++++++++++++++ resources/js/libs/menubar/README.md | 19 - resources/js/libs/menubar/ambient.d.ts | 11 + resources/js/libs/menubar/index.js | 39 -- .../js/libs/menubar/{index.d.ts => index.ts} | 11 +- resources/js/libs/menubar/types.d.ts | 84 ---- resources/js/libs/menubar/types.js | 2 - resources/js/libs/menubar/types.ts | 104 +++++ .../js/libs/menubar/util/cleanOptions.d.ts | 11 - .../js/libs/menubar/util/cleanOptions.js | 73 ---- .../libs/menubar/util/cleanOptions.spec.d.ts | 1 - .../js/libs/menubar/util/cleanOptions.spec.js | 74 ---- .../js/libs/menubar/util/cleanOptions.spec.ts | 70 ++++ .../js/libs/menubar/util/cleanOptions.ts | 67 +++ .../libs/menubar/util/getWindowPosition.d.ts | 23 -- .../js/libs/menubar/util/getWindowPosition.js | 88 ---- .../js/libs/menubar/util/getWindowPosition.ts | 107 +++++ 22 files changed, 740 insertions(+), 909 deletions(-) delete mode 100644 resources/js/libs/menubar/Menubar.d.ts delete mode 100644 resources/js/libs/menubar/Menubar.js delete mode 100644 resources/js/libs/menubar/Menubar.spec.d.ts delete mode 100644 resources/js/libs/menubar/Menubar.spec.js create mode 100644 resources/js/libs/menubar/Menubar.spec.ts create mode 100644 resources/js/libs/menubar/Menubar.ts delete mode 100644 resources/js/libs/menubar/README.md create mode 100644 resources/js/libs/menubar/ambient.d.ts delete mode 100644 resources/js/libs/menubar/index.js rename resources/js/libs/menubar/{index.d.ts => index.ts} (73%) delete mode 100644 resources/js/libs/menubar/types.d.ts delete mode 100644 resources/js/libs/menubar/types.js create mode 100644 resources/js/libs/menubar/types.ts delete mode 100644 resources/js/libs/menubar/util/cleanOptions.d.ts delete mode 100644 resources/js/libs/menubar/util/cleanOptions.js delete mode 100644 resources/js/libs/menubar/util/cleanOptions.spec.d.ts delete mode 100644 resources/js/libs/menubar/util/cleanOptions.spec.js create mode 100644 resources/js/libs/menubar/util/cleanOptions.spec.ts create mode 100644 resources/js/libs/menubar/util/cleanOptions.ts delete mode 100644 resources/js/libs/menubar/util/getWindowPosition.d.ts delete mode 100644 resources/js/libs/menubar/util/getWindowPosition.js create mode 100644 resources/js/libs/menubar/util/getWindowPosition.ts diff --git a/resources/js/libs/menubar/Menubar.d.ts b/resources/js/libs/menubar/Menubar.d.ts deleted file mode 100644 index f77b64f2..00000000 --- a/resources/js/libs/menubar/Menubar.d.ts +++ /dev/null @@ -1,73 +0,0 @@ -/// -import { EventEmitter } from 'events'; -import { BrowserWindow, Tray } from 'electron'; -import Positioner from '../positioner/index.js'; -import type { Options } from './types.js'; -/** - * The main Menubar class. - * - * @noInheritDoc - */ -export declare class Menubar extends EventEmitter { - private _app; - private _browserWindow?; - private _blurTimeout; - private _isVisible; - private _cachedBounds?; - private _options; - private _positioner; - private _tray?; - constructor(app: Electron.App, options?: Partial); - /** - * The Electron [App](https://electronjs.org/docs/api/app) - * instance. - */ - get app(): Electron.App; - /** - * The [electron-positioner](https://github.com/jenslind/electron-positioner) - * instance. - */ - get positioner(): Positioner; - /** - * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. - */ - get tray(): Tray; - /** - * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) - * instance, if it's present. - */ - get window(): BrowserWindow | undefined; - /** - * Retrieve a menubar option. - * - * @param key - The option key to retrieve, see {@link Options}. - */ - getOption(key: K): Options[K]; - /** - * Hide the menubar window. - */ - hideWindow(): void; - /** - * Change an option after menubar is created. - * - * @param key - The option key to modify, see {@link Options}. - * @param value - The value to set. - */ - setOption(key: K, value: Options[K]): void; - /** - * Show the menubar window. - * - * @param trayPos - The bounds to show the window in. - */ - showWindow(trayPos?: Electron.Rectangle): Promise; - private appReady; - /** - * Callback on tray icon click or double-click. - * - * @param e - * @param bounds - */ - private clicked; - private createWindow; - private windowClear; -} diff --git a/resources/js/libs/menubar/Menubar.js b/resources/js/libs/menubar/Menubar.js deleted file mode 100644 index e8a9ce23..00000000 --- a/resources/js/libs/menubar/Menubar.js +++ /dev/null @@ -1,380 +0,0 @@ -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Menubar = void 0; -var events_1 = require("events"); -var fs_1 = __importDefault(require("fs")); -var path_1 = __importDefault(require("path")); -var electron_1 = require("electron"); -var electron_positioner_1 = __importDefault(require("electron-positioner")); -var cleanOptions_1 = require("./util/cleanOptions"); -var getWindowPosition_1 = require("./util/getWindowPosition"); -/** - * The main Menubar class. - * - * @noInheritDoc - */ -var Menubar = /** @class */ (function (_super) { - __extends(Menubar, _super); - function Menubar(app, options) { - var _this = _super.call(this) || this; - _this._blurTimeout = null; // track blur events with timeout - _this._app = app; - _this._options = (0, cleanOptions_1.cleanOptions)(options); - _this._isVisible = false; - if (app.isReady()) { - // See https://github.com/maxogden/menubar/pull/151 - process.nextTick(function () { - return _this.appReady().catch(function (err) { return console.error('menubar: ', err); }); - }); - } - else { - app.on('ready', function () { - _this.appReady().catch(function (err) { return console.error('menubar: ', err); }); - }); - } - return _this; - } - Object.defineProperty(Menubar.prototype, "app", { - /** - * The Electron [App](https://electronjs.org/docs/api/app) - * instance. - */ - get: function () { - return this._app; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Menubar.prototype, "positioner", { - /** - * The [electron-positioner](https://github.com/jenslind/electron-positioner) - * instance. - */ - get: function () { - if (!this._positioner) { - throw new Error('Please access `this.positioner` after the `after-create-window` event has fired.'); - } - return this._positioner; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Menubar.prototype, "tray", { - /** - * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. - */ - get: function () { - if (!this._tray) { - throw new Error('Please access `this.tray` after the `ready` event has fired.'); - } - return this._tray; - }, - enumerable: false, - configurable: true - }); - Object.defineProperty(Menubar.prototype, "window", { - /** - * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) - * instance, if it's present. - */ - get: function () { - return this._browserWindow; - }, - enumerable: false, - configurable: true - }); - /** - * Retrieve a menubar option. - * - * @param key - The option key to retrieve, see {@link Options}. - */ - Menubar.prototype.getOption = function (key) { - return this._options[key]; - }; - /** - * Hide the menubar window. - */ - Menubar.prototype.hideWindow = function () { - if (!this._browserWindow || !this._isVisible) { - return; - } - this.emit('hide'); - this._browserWindow.hide(); - this.emit('after-hide'); - this._isVisible = false; - if (this._blurTimeout) { - clearTimeout(this._blurTimeout); - this._blurTimeout = null; - } - }; - /** - * Change an option after menubar is created. - * - * @param key - The option key to modify, see {@link Options}. - * @param value - The value to set. - */ - Menubar.prototype.setOption = function (key, value) { - this._options[key] = value; - }; - /** - * Show the menubar window. - * - * @param trayPos - The bounds to show the window in. - */ - Menubar.prototype.showWindow = function (trayPos) { - return __awaiter(this, void 0, void 0, function () { - var noBoundsPosition, position, x, y; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (!this.tray) { - throw new Error('Tray should have been instantiated by now'); - } - if (!!this._browserWindow) return [3 /*break*/, 2]; - return [4 /*yield*/, this.createWindow()]; - case 1: - _a.sent(); - _a.label = 2; - case 2: - // Use guard for TypeScript, to avoid ! everywhere - if (!this._browserWindow) { - throw new Error('Window has been initialized just above. qed.'); - } - // 'Windows' taskbar: sync windows position each time before showing - // https://github.com/maxogden/menubar/issues/232 - if (['win32', 'linux'].includes(process.platform)) { - // Fill in this._options.windowPosition when taskbar position is available - this._options.windowPosition = (0, getWindowPosition_1.getWindowPosition)(this.tray); - } - this.emit('show'); - if (trayPos && trayPos.x !== 0) { - // Cache the bounds - this._cachedBounds = trayPos; - } - else if (this._cachedBounds) { - // Cached value will be used if showWindow is called without bounds data - trayPos = this._cachedBounds; - } - else if (this.tray.getBounds) { - // Get the current tray bounds - trayPos = this.tray.getBounds(); - } - noBoundsPosition = undefined; - if ((trayPos === undefined || trayPos.x === 0) && - this._options.windowPosition && - this._options.windowPosition.startsWith('tray')) { - noBoundsPosition = - process.platform === 'win32' ? 'bottomRight' : 'topRight'; - } - position = this.positioner.calculate(this._options.windowPosition || noBoundsPosition, trayPos); - x = this._options.browserWindow.x !== undefined - ? this._options.browserWindow.x - : position.x; - y = this._options.browserWindow.y !== undefined - ? this._options.browserWindow.y - : position.y; - // `.setPosition` crashed on non-integers - // https://github.com/maxogden/menubar/issues/233 - this._browserWindow.setPosition(Math.round(x), Math.round(y)); - this._browserWindow.show(); - this._isVisible = true; - this.emit('after-show'); - return [2 /*return*/]; - } - }); - }); - }; - Menubar.prototype.appReady = function () { - return __awaiter(this, void 0, void 0, function () { - var trayImage, defaultClickEvent; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (this.app.dock && !this._options.showDockIcon) { - this.app.dock.hide(); - } - if (this._options.activateWithApp) { - this.app.on('activate', function (_event, hasVisibleWindows) { - if (!hasVisibleWindows) { - _this.showWindow().catch(console.error); - } - }); - } - trayImage = this._options.icon || path_1.default.join(this._options.dir, 'IconTemplate.png'); - if (typeof trayImage === 'string' && !fs_1.default.existsSync(trayImage)) { - trayImage = path_1.default.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon - } - defaultClickEvent = this._options.showOnRightClick - ? 'right-click' - : 'click'; - this._tray = this._options.tray || new electron_1.Tray(trayImage); - // Type guards for TS not to complain - if (!this.tray) { - throw new Error('Tray has been initialized above'); - } - this.tray.on(defaultClickEvent, this.clicked.bind(this)); - this.tray.on('double-click', this.clicked.bind(this)); - this.tray.setToolTip(this._options.tooltip); - if (!this._options.windowPosition) { - this._options.windowPosition = (0, getWindowPosition_1.getWindowPosition)(this.tray); - } - if (!this._options.preloadWindow) return [3 /*break*/, 2]; - return [4 /*yield*/, this.createWindow()]; - case 1: - _a.sent(); - _a.label = 2; - case 2: - this.emit('ready'); - return [2 /*return*/]; - } - }); - }); - }; - /** - * Callback on tray icon click or double-click. - * - * @param e - * @param bounds - */ - Menubar.prototype.clicked = function (event, bounds) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { - return [2 /*return*/, this.hideWindow()]; - } - // if blur was invoked clear timeout - if (this._blurTimeout) { - clearInterval(this._blurTimeout); - } - if (this._browserWindow && this._isVisible) { - return [2 /*return*/, this.hideWindow()]; - } - this._cachedBounds = bounds || this._cachedBounds; - return [4 /*yield*/, this.showWindow(this._cachedBounds)]; - case 1: - _a.sent(); - return [2 /*return*/]; - } - }); - }); - }; - Menubar.prototype.createWindow = function () { - return __awaiter(this, void 0, void 0, function () { - var defaults; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.emit('create-window'); - defaults = { - show: false, - frame: false, // Remove window frame - }; - this._browserWindow = new electron_1.BrowserWindow(__assign(__assign({}, defaults), this._options.browserWindow)); - this._positioner = new electron_positioner_1.default(this._browserWindow); - this._browserWindow.on('blur', function () { - if (!_this._browserWindow) { - return; - } - // hack to close if icon clicked when open - _this._browserWindow.isAlwaysOnTop() - ? _this.emit('focus-lost') - : (_this._blurTimeout = setTimeout(function () { - _this.hideWindow(); - }, 100)); - }); - if (this._options.showOnAllWorkspaces !== false) { - // https://github.com/electron/electron/issues/37832#issuecomment-1497882944 - this._browserWindow.setVisibleOnAllWorkspaces(true, { - skipTransformProcessType: true, // Avoid damaging the original visible state of app.dock - }); - } - this._browserWindow.on('close', this.windowClear.bind(this)); - this.emit('before-load'); - if (!(this._options.index !== false)) return [3 /*break*/, 2]; - return [4 /*yield*/, this._browserWindow.loadURL(this._options.index, this._options.loadUrlOptions)]; - case 1: - _a.sent(); - _a.label = 2; - case 2: - this.emit('after-create-window'); - return [2 /*return*/]; - } - }); - }); - }; - Menubar.prototype.windowClear = function () { - this._browserWindow = undefined; - this.emit('after-close'); - }; - return Menubar; -}(events_1.EventEmitter)); -exports.Menubar = Menubar; diff --git a/resources/js/libs/menubar/Menubar.spec.d.ts b/resources/js/libs/menubar/Menubar.spec.d.ts deleted file mode 100644 index cb0ff5c3..00000000 --- a/resources/js/libs/menubar/Menubar.spec.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/resources/js/libs/menubar/Menubar.spec.js b/resources/js/libs/menubar/Menubar.spec.js deleted file mode 100644 index 11d875a4..00000000 --- a/resources/js/libs/menubar/Menubar.spec.js +++ /dev/null @@ -1,40 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -var electron_1 = require("electron"); -var Menubar_1 = require("./Menubar"); -describe('Menubar', function () { - var mb; - beforeEach(function () { - mb = new Menubar_1.Menubar(electron_1.app, { preloadWindow: true }); - }); - it('should have property `app`', function () { - expect(mb.app).toBeDefined(); - }); - it('should have property `positioner`', function () { - expect(function () { return mb.positioner; }).toThrow(); - return new Promise(function (resolve) { - mb.on('after-create-window', function () { - expect(mb.positioner).toBeDefined(); - resolve(); - }); - }); - }); - it('should have property `tray`', function () { - expect(function () { return mb.tray; }).toThrow(); - return new Promise(function (resolve) { - mb.on('ready', function () { - expect(mb.tray).toBeInstanceOf(electron_1.Tray); - resolve(); - }); - }); - }); - it('should have property `window`', function () { - expect(mb.window).toBeUndefined(); - return new Promise(function (resolve) { - mb.on('ready', function () { - expect(mb.window).toBeInstanceOf(electron_1.BrowserWindow); - resolve(); - }); - }); - }); -}); diff --git a/resources/js/libs/menubar/Menubar.spec.ts b/resources/js/libs/menubar/Menubar.spec.ts new file mode 100644 index 00000000..fb641fd5 --- /dev/null +++ b/resources/js/libs/menubar/Menubar.spec.ts @@ -0,0 +1,45 @@ +import { BrowserWindow, Tray, app } from 'electron'; + +import { Menubar } from './Menubar'; + +describe('Menubar', () => { + let mb: Menubar | undefined; + + beforeEach(() => { + mb = new Menubar(app, { preloadWindow: true }); + }); + + it('should have property `app`', () => { + expect(mb!.app).toBeDefined(); + }); + + it('should have property `positioner`', () => { + expect(() => mb!.positioner as unknown).toThrow(); + return new Promise((resolve) => { + mb!.on('after-create-window', () => { + expect(mb!.positioner).toBeDefined(); + resolve(); + }); + }); + }); + + it('should have property `tray`', () => { + expect(() => mb!.tray).toThrow(); + return new Promise((resolve) => { + mb!.on('ready', () => { + expect(mb!.tray).toBeInstanceOf(Tray); + resolve(); + }); + }); + }); + + it('should have property `window`', () => { + expect(mb!.window).toBeUndefined(); + return new Promise((resolve) => { + mb!.on('ready', () => { + expect(mb!.window).toBeInstanceOf(BrowserWindow); + resolve(); + }); + }); + }); +}); diff --git a/resources/js/libs/menubar/Menubar.ts b/resources/js/libs/menubar/Menubar.ts new file mode 100644 index 00000000..71fb39d5 --- /dev/null +++ b/resources/js/libs/menubar/Menubar.ts @@ -0,0 +1,326 @@ +import { EventEmitter } from 'events'; +import fs from 'fs'; +import path from 'path'; +import { BrowserWindow, Tray } from 'electron'; +import Positioner from '../positioner/index.js'; + +import type { Options } from './types.js'; +import { cleanOptions } from './util/cleanOptions.js'; +import { getWindowPosition } from './util/getWindowPosition.js'; + +/** + * The main Menubar class. + * + * @noInheritDoc + */ +export class Menubar extends EventEmitter { + private _app: Electron.App; + private _browserWindow?: BrowserWindow; + private _blurTimeout: NodeJS.Timeout | null = null; // track blur events with timeout + private _isVisible: boolean; // track visibility + private _cachedBounds?: Electron.Rectangle; // _cachedBounds are needed for double-clicked event + private _options: Options; + private _positioner: Positioner | undefined; + private _tray?: Tray; + + constructor(app: Electron.App, options?: Partial) { + super(); + this._app = app; + this._options = cleanOptions(options); + this._isVisible = false; + + if (app.isReady()) { + // See https://github.com/maxogden/menubar/pull/151 + process.nextTick(() => + this.appReady().catch((err) => console.error('menubar: ', err)), + ); + } else { + app.on('ready', () => { + this.appReady().catch((err) => console.error('menubar: ', err)); + }); + } + } + + /** + * The Electron [App](https://electronjs.org/docs/api/app) + * instance. + */ + get app(): Electron.App { + return this._app; + } + + /** + * The [electron-positioner](https://github.com/jenslind/electron-positioner) + * instance. + */ + get positioner(): Positioner { + if (!this._positioner) { + throw new Error( + 'Please access `this.positioner` after the `after-create-window` event has fired.', + ); + } + + return this._positioner; + } + + /** + * The Electron [Tray](https://electronjs.org/docs/api/tray) instance. + */ + get tray(): Tray { + if (!this._tray) { + throw new Error( + 'Please access `this.tray` after the `ready` event has fired.', + ); + } + + return this._tray; + } + + /** + * The Electron [BrowserWindow](https://electronjs.org/docs/api/browser-window) + * instance, if it's present. + */ + get window(): BrowserWindow | undefined { + return this._browserWindow; + } + + /** + * Retrieve a menubar option. + * + * @param key - The option key to retrieve, see {@link Options}. + */ + getOption(key: K): Options[K] { + return this._options[key]; + } + + /** + * Hide the menubar window. + */ + hideWindow(): void { + if (!this._browserWindow || !this._isVisible) { + return; + } + this.emit('hide'); + this._browserWindow.hide(); + this.emit('after-hide'); + this._isVisible = false; + if (this._blurTimeout) { + clearTimeout(this._blurTimeout); + this._blurTimeout = null; + } + } + + /** + * Change an option after menubar is created. + * + * @param key - The option key to modify, see {@link Options}. + * @param value - The value to set. + */ + setOption(key: K, value: Options[K]): void { + this._options[key] = value; + } + + /** + * Show the menubar window. + * + * @param trayPos - The bounds to show the window in. + */ + async showWindow(trayPos?: Electron.Rectangle): Promise { + if (!this.tray) { + throw new Error('Tray should have been instantiated by now'); + } + + if (!this._browserWindow) { + await this.createWindow(); + } + + // Use guard for TypeScript, to avoid ! everywhere + if (!this._browserWindow) { + throw new Error('Window has been initialized just above. qed.'); + } + + // 'Windows' taskbar: sync windows position each time before showing + // https://github.com/maxogden/menubar/issues/232 + if (['win32', 'linux'].includes(process.platform)) { + // Fill in this._options.windowPosition when taskbar position is available + this._options.windowPosition = getWindowPosition(this.tray); + } + + this.emit('show'); + + if (trayPos && trayPos.x !== 0) { + // Cache the bounds + this._cachedBounds = trayPos; + } else if (this._cachedBounds) { + // Cached value will be used if showWindow is called without bounds data + trayPos = this._cachedBounds; + } else if (this.tray.getBounds) { + // Get the current tray bounds + trayPos = this.tray.getBounds(); + } + + // Default the window to the right if `trayPos` bounds are undefined or null. + let noBoundsPosition = undefined; + if ( + (trayPos === undefined || trayPos.x === 0) && + this._options.windowPosition && + this._options.windowPosition.startsWith('tray') + ) { + noBoundsPosition = + process.platform === 'win32' ? 'bottomRight' : 'topRight'; + } + + const position = this.positioner.calculate( + this._options.windowPosition || noBoundsPosition, + trayPos, + ) as { x: number; y: number }; + + // Not using `||` because x and y can be zero. + const x = + this._options.browserWindow.x !== undefined + ? this._options.browserWindow.x + : position.x; + const y = + this._options.browserWindow.y !== undefined + ? this._options.browserWindow.y + : position.y; + + // `.setPosition` crashed on non-integers + // https://github.com/maxogden/menubar/issues/233 + this._browserWindow.setPosition(Math.round(x), Math.round(y)); + this._browserWindow.show(); + this._isVisible = true; + this.emit('after-show'); + return; + } + + private async appReady(): Promise { + if (this.app.dock && !this._options.showDockIcon) { + this.app.dock.hide(); + } + + if (this._options.activateWithApp) { + this.app.on('activate', (_event, hasVisibleWindows) => { + if (!hasVisibleWindows) { + this.showWindow().catch(console.error); + } + }); + } + + let trayImage = + this._options.icon || path.join(this._options.dir, 'IconTemplate.png'); + if (typeof trayImage === 'string' && !fs.existsSync(trayImage)) { + trayImage = path.join(__dirname, '..', 'assets', 'IconTemplate.png'); // Default cat icon + } + + const defaultClickEvent = this._options.showOnRightClick + ? 'right-click' + : 'click'; + + this._tray = this._options.tray || new Tray(trayImage); + // Type guards for TS not to complain + if (!this.tray) { + throw new Error('Tray has been initialized above'); + } + this.tray.on( + defaultClickEvent as Parameters[0], + this.clicked.bind(this), + ); + this.tray.on('double-click', this.clicked.bind(this)); + this.tray.setToolTip(this._options.tooltip); + + if (!this._options.windowPosition) { + this._options.windowPosition = getWindowPosition(this.tray); + } + + if (this._options.preloadWindow) { + await this.createWindow(); + } + + this.emit('ready'); + } + + /** + * Callback on tray icon click or double-click. + * + * @param e + * @param bounds + */ + private async clicked( + event?: Electron.KeyboardEvent, + bounds?: Electron.Rectangle, + ): Promise { + if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { + return this.hideWindow(); + } + + // if blur was invoked clear timeout + if (this._blurTimeout) { + clearInterval(this._blurTimeout); + } + + if (this._browserWindow && this._isVisible) { + return this.hideWindow(); + } + + this._cachedBounds = bounds || this._cachedBounds; + await this.showWindow(this._cachedBounds); + } + + private async createWindow(): Promise { + this.emit('create-window'); + + // We add some default behavior for menubar's browserWindow, to make it + // look like a menubar + const defaults = { + show: false, // Don't show it at first + frame: false, // Remove window frame + }; + + this._browserWindow = new BrowserWindow({ + ...defaults, + ...this._options.browserWindow, + }); + + this._positioner = new Positioner(this._browserWindow); + + this._browserWindow.on('blur', () => { + if (!this._browserWindow) { + return; + } + + // hack to close if icon clicked when open + this._browserWindow.isAlwaysOnTop() + ? this.emit('focus-lost') + : (this._blurTimeout = setTimeout(() => { + this.hideWindow(); + }, 100)); + }); + + if (this._options.showOnAllWorkspaces !== false) { + // https://github.com/electron/electron/issues/37832#issuecomment-1497882944 + this._browserWindow.setVisibleOnAllWorkspaces(true, { + skipTransformProcessType: true, // Avoid damaging the original visible state of app.dock + }); + } + + this._browserWindow.on('close', this.windowClear.bind(this)); + + this.emit('before-load'); + + // If the user explicity set options.index to false, we don't loadURL + // https://github.com/maxogden/menubar/issues/255 + if (this._options.index !== false) { + await this._browserWindow.loadURL( + this._options.index, + this._options.loadUrlOptions, + ); + } + this.emit('after-create-window'); + } + + private windowClear(): void { + this._browserWindow = undefined; + this.emit('after-close'); + } +} diff --git a/resources/js/libs/menubar/README.md b/resources/js/libs/menubar/README.md deleted file mode 100644 index 99c7681c..00000000 --- a/resources/js/libs/menubar/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Menubar Library - -This is a vendored copy of the [menubar](https://github.com/max-mapper/menubar) library, originally created by max-mapper. - -This library is pulled in from the https://github.com/max-mapper/menubar repository. The package sadly is not actively maintained, preventing our ability to update Electron dependencies in a timely manner. - -We decided to pull the lib in directly instead of maintaining a fork to: - -- Control our dependency update timeline -- Ensure compatibility with newer Electron versions -- Maintain stability for NativePHP desktop applications - -## About Menubar - -Menubar is a high-level Electron library for creating desktop menubar applications. It provides boilerplate for setting up a menubar application using Electron. - -## NativePHP Integration - -This vendored copy is specifically maintained for use within the NativePHP Electron backend, enabling PHP developers to create native desktop applications with menubar functionality. diff --git a/resources/js/libs/menubar/ambient.d.ts b/resources/js/libs/menubar/ambient.d.ts new file mode 100644 index 00000000..2ff6872e --- /dev/null +++ b/resources/js/libs/menubar/ambient.d.ts @@ -0,0 +1,11 @@ +// TODO https://github.com/jenslind/electron-positioner/issues/15 +declare module 'electron-positioner' { + export default class { + constructor(window: Electron.BrowserWindow); + + calculate( + position?: string, + rectangle?: Electron.Rectangle, + ): { x: number; y: number }; + } +} diff --git a/resources/js/libs/menubar/index.js b/resources/js/libs/menubar/index.js deleted file mode 100644 index b4dc6d3b..00000000 --- a/resources/js/libs/menubar/index.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -/** - * Entry point of menubar - * @example - * ```typescript - * import { menubar } from 'menubar'; - * ``` - */ -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.menubar = exports.Menubar = void 0; -/** */ -var electron_1 = require("electron"); -var Menubar_1 = require("./Menubar"); -Object.defineProperty(exports, "Menubar", { enumerable: true, get: function () { return Menubar_1.Menubar; } }); -__exportStar(require("./util/getWindowPosition"), exports); -/** - * Factory function to create a menubar application - * - * @param options - Options for creating a menubar application, see - * {@link Options} - */ -function menubar(options) { - return new Menubar_1.Menubar(electron_1.app, options); -} -exports.menubar = menubar; diff --git a/resources/js/libs/menubar/index.d.ts b/resources/js/libs/menubar/index.ts similarity index 73% rename from resources/js/libs/menubar/index.d.ts rename to resources/js/libs/menubar/index.ts index a151f206..6eba24dd 100644 --- a/resources/js/libs/menubar/index.d.ts +++ b/resources/js/libs/menubar/index.ts @@ -5,14 +5,23 @@ * import { menubar } from 'menubar'; * ``` */ + +/** */ + +import { app } from 'electron'; + import { Menubar } from './Menubar.js'; import type { Options } from './types.js'; + export * from './util/getWindowPosition.js'; export { Menubar }; + /** * Factory function to create a menubar application * * @param options - Options for creating a menubar application, see * {@link Options} */ -export declare function menubar(options?: Partial): Menubar; +export function menubar(options?: Partial): Menubar { + return new Menubar(app, options); +} diff --git a/resources/js/libs/menubar/types.d.ts b/resources/js/libs/menubar/types.d.ts deleted file mode 100644 index 238a0f02..00000000 --- a/resources/js/libs/menubar/types.d.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { BrowserWindowConstructorOptions, LoadURLOptions, Tray } from 'electron'; -/** - * Options for creating a menubar application - */ -export interface Options { - /** - * Listen on `app.on('activate')` to open menubar when app is activated. - * @default `true` - */ - activateWithApp?: boolean; - /** - * An Electron BrowserWindow instance, or an options object to be passed into - * the BrowserWindow constructor. - * @example - * ```typescript - * const options = { height: 640, width: 480 }; - * - * const mb = new Menubar({ - * browserWindow: options - * }); - * ``` - */ - browserWindow: BrowserWindowConstructorOptions; - /** - * The app source directory. - */ - dir: string; - /** - * The png icon to use for the menubar. A good size to start with is 20x20. - * To support retina, supply a 2x sized image (e.g. 40x40) with @2x added to - * the end of the name, so icon.png and icon@2x.png and Electron will - * automatically use your @2x version on retina screens. - */ - icon?: string | Electron.NativeImage; - /** - * The URL to load the menubar's browserWindow with. The url can be a remote - * address (e.g. `http://`) or a path to a local HTML file using the - * `file://` protocol. If false, then menubar won't call `loadURL` on - * start. - * @default `file:// + options.dir + index.html` - * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options - */ - index: string | false; - /** - * The options passed when loading the index URL in the menubar's - * browserWindow. Everything browserWindow.loadURL supports is supported; - * this object is simply passed onto browserWindow.loadURL - * @default `{}` - * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options - */ - loadUrlOptions?: LoadURLOptions; - /** - * Create BrowserWindow instance before it is used -- increasing resource - * usage, but making the click on the menubar load faster. - */ - preloadWindow?: boolean; - /** - * Configure the visibility of the application dock icon, macOS only. Calls - * [`app.dock.hide`](https://electronjs.org/docs/api/app#appdockhide-macos). - */ - showDockIcon?: boolean; - /** - * Makes the window available on all OS X workspaces. Calls - * [`setVisibleOnAllWorkspaces`](https://electronjs.org/docs/api/browser-window#winsetvisibleonallworkspacesvisible-options). - */ - showOnAllWorkspaces?: boolean; - /** - * Show the window on 'right-click' event instead of regular 'click'. - */ - showOnRightClick?: boolean; - /** - * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip). - */ - tooltip: string; - /** - * An electron Tray instance. If provided, `options.icon` will be ignored. - */ - tray?: Tray; - /** - * Sets the window position (x and y will still override this), check - * electron-positioner docs for valid values. - */ - windowPosition?: 'trayLeft' | 'trayBottomLeft' | 'trayRight' | 'trayBottomRight' | 'trayCenter' | 'trayBottomCenter' | 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' | 'topCenter' | 'bottomCenter' | 'leftCenter' | 'rightCenter' | 'center'; -} diff --git a/resources/js/libs/menubar/types.js b/resources/js/libs/menubar/types.js deleted file mode 100644 index c8ad2e54..00000000 --- a/resources/js/libs/menubar/types.js +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/resources/js/libs/menubar/types.ts b/resources/js/libs/menubar/types.ts new file mode 100644 index 00000000..cf37f654 --- /dev/null +++ b/resources/js/libs/menubar/types.ts @@ -0,0 +1,104 @@ +import type { + BrowserWindowConstructorOptions, + LoadURLOptions, + Tray, +} from 'electron'; + +/** + * Options for creating a menubar application + */ +export interface Options { + /** + * Listen on `app.on('activate')` to open menubar when app is activated. + * @default `true` + */ + activateWithApp?: boolean; + /** + * An Electron BrowserWindow instance, or an options object to be passed into + * the BrowserWindow constructor. + * @example + * ```typescript + * const options = { height: 640, width: 480 }; + * + * const mb = new Menubar({ + * browserWindow: options + * }); + * ``` + */ + browserWindow: BrowserWindowConstructorOptions; + /** + * The app source directory. + */ + dir: string; + /** + * The png icon to use for the menubar. A good size to start with is 20x20. + * To support retina, supply a 2x sized image (e.g. 40x40) with @2x added to + * the end of the name, so icon.png and icon@2x.png and Electron will + * automatically use your @2x version on retina screens. + */ + icon?: string | Electron.NativeImage; + /** + * The URL to load the menubar's browserWindow with. The url can be a remote + * address (e.g. `http://`) or a path to a local HTML file using the + * `file://` protocol. If false, then menubar won't call `loadURL` on + * start. + * @default `file:// + options.dir + index.html` + * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options + */ + index: string | false; + /** + * The options passed when loading the index URL in the menubar's + * browserWindow. Everything browserWindow.loadURL supports is supported; + * this object is simply passed onto browserWindow.loadURL + * @default `{}` + * @see https://electronjs.org/docs/api/browser-window#winloadurlurl-options + */ + loadUrlOptions?: LoadURLOptions; + /** + * Create BrowserWindow instance before it is used -- increasing resource + * usage, but making the click on the menubar load faster. + */ + preloadWindow?: boolean; + /** + * Configure the visibility of the application dock icon, macOS only. Calls + * [`app.dock.hide`](https://electronjs.org/docs/api/app#appdockhide-macos). + */ + showDockIcon?: boolean; + /** + * Makes the window available on all OS X workspaces. Calls + * [`setVisibleOnAllWorkspaces`](https://electronjs.org/docs/api/browser-window#winsetvisibleonallworkspacesvisible-options). + */ + showOnAllWorkspaces?: boolean; + /** + * Show the window on 'right-click' event instead of regular 'click'. + */ + showOnRightClick?: boolean; + /** + * Menubar tray icon tooltip text. Calls [`tray.setTooltip`](https://electronjs.org/docs/api/tray#traysettooltiptooltip). + */ + tooltip: string; + /** + * An electron Tray instance. If provided, `options.icon` will be ignored. + */ + tray?: Tray; + /** + * Sets the window position (x and y will still override this), check + * electron-positioner docs for valid values. + */ + windowPosition?: + | 'trayLeft' + | 'trayBottomLeft' + | 'trayRight' + | 'trayBottomRight' + | 'trayCenter' + | 'trayBottomCenter' + | 'topLeft' + | 'topRight' + | 'bottomLeft' + | 'bottomRight' + | 'topCenter' + | 'bottomCenter' + | 'leftCenter' + | 'rightCenter' + | 'center'; +} diff --git a/resources/js/libs/menubar/util/cleanOptions.d.ts b/resources/js/libs/menubar/util/cleanOptions.d.ts deleted file mode 100644 index 5ecb864c..00000000 --- a/resources/js/libs/menubar/util/cleanOptions.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @ignore - */ -import type { Options } from '../types'; -/** - * Take as input some options, and return a sanitized version of it. - * - * @param opts - The options to clean. - * @ignore - */ -export declare function cleanOptions(opts?: Partial): Options; diff --git a/resources/js/libs/menubar/util/cleanOptions.js b/resources/js/libs/menubar/util/cleanOptions.js deleted file mode 100644 index b23bab40..00000000 --- a/resources/js/libs/menubar/util/cleanOptions.js +++ /dev/null @@ -1,73 +0,0 @@ -"use strict"; -/** - * @ignore - */ -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.cleanOptions = void 0; -/** */ -var path_1 = __importDefault(require("path")); -var url_1 = __importDefault(require("url")); -var electron_1 = require("electron"); -var DEFAULT_WINDOW_HEIGHT = 400; -var DEFAULT_WINDOW_WIDTH = 400; -/** - * Take as input some options, and return a sanitized version of it. - * - * @param opts - The options to clean. - * @ignore - */ -function cleanOptions(opts) { - var options = __assign({}, opts); - if (options.activateWithApp === undefined) { - options.activateWithApp = true; - } - if (!options.dir) { - options.dir = electron_1.app.getAppPath(); - } - if (!path_1.default.isAbsolute(options.dir)) { - options.dir = path_1.default.resolve(options.dir); - } - // Note: options.index can be `false` - if (options.index === undefined) { - options.index = url_1.default.format({ - pathname: path_1.default.join(options.dir, 'index.html'), - protocol: 'file:', - slashes: true, - }); - } - options.loadUrlOptions = options.loadUrlOptions || {}; - options.tooltip = options.tooltip || ''; - // `icon`, `preloadWindow`, `showDockIcon`, `showOnAllWorkspaces`, - // `showOnRightClick` don't need any special treatment - // Now we take care of `browserWindow` - if (!options.browserWindow) { - options.browserWindow = {}; - } - // Set width/height on options to be usable before the window is created - options.browserWindow.width = - // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so - // that users can put a 0 width - options.browserWindow.width !== undefined - ? options.browserWindow.width - : DEFAULT_WINDOW_WIDTH; - options.browserWindow.height = - options.browserWindow.height !== undefined - ? options.browserWindow.height - : DEFAULT_WINDOW_HEIGHT; - return options; -} -exports.cleanOptions = cleanOptions; diff --git a/resources/js/libs/menubar/util/cleanOptions.spec.d.ts b/resources/js/libs/menubar/util/cleanOptions.spec.d.ts deleted file mode 100644 index cb0ff5c3..00000000 --- a/resources/js/libs/menubar/util/cleanOptions.spec.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/resources/js/libs/menubar/util/cleanOptions.spec.js b/resources/js/libs/menubar/util/cleanOptions.spec.js deleted file mode 100644 index 45788802..00000000 --- a/resources/js/libs/menubar/util/cleanOptions.spec.js +++ /dev/null @@ -1,74 +0,0 @@ -"use strict"; -var __assign = (this && this.__assign) || function () { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var path = __importStar(require("path")); -var electron_1 = require("../__mocks__/electron"); -var cleanOptions_1 = require("./cleanOptions"); -var DEFAULT_OPTIONS = { - activateWithApp: true, - browserWindow: { - height: 400, - width: 400, - }, - dir: path.resolve(electron_1.MOCK_APP_GETAPPPATH), - index: "file://".concat(path.join(path.resolve(electron_1.MOCK_APP_GETAPPPATH), 'index.html')), - loadUrlOptions: {}, - tooltip: '', -}; -describe('cleanOptions', function () { - it('should handle undefined', function () { - expect((0, cleanOptions_1.cleanOptions)(undefined)).toEqual(DEFAULT_OPTIONS); - }); - it('should handle a dir string with relative path', function () { - expect((0, cleanOptions_1.cleanOptions)({ dir: 'MY_RELATIVE_PATH' })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { dir: path.resolve('MY_RELATIVE_PATH'), index: "file://".concat(path.join(path.resolve('MY_RELATIVE_PATH'), 'index.html')) })); - }); - it('should handle a dir string with absolute path', function () { - expect((0, cleanOptions_1.cleanOptions)({ dir: '/home/me/MY_ABSOLUTE_PATH' })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { dir: '/home/me/MY_ABSOLUTE_PATH', index: 'file:///home/me/MY_ABSOLUTE_PATH/index.html' })); - }); - it('should handle a false index', function () { - expect((0, cleanOptions_1.cleanOptions)({ index: false })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { index: false })); - }); - it('should handle an object with multiple fields', function () { - expect((0, cleanOptions_1.cleanOptions)({ - browserWindow: { - height: 100, - }, - index: 'file:///home/abc/index.html', - showDockIcon: true, - windowPosition: 'trayCenter', - })).toEqual(__assign(__assign({}, DEFAULT_OPTIONS), { browserWindow: __assign(__assign({}, DEFAULT_OPTIONS.browserWindow), { height: 100 }), index: 'file:///home/abc/index.html', showDockIcon: true, windowPosition: 'trayCenter' })); - }); -}); diff --git a/resources/js/libs/menubar/util/cleanOptions.spec.ts b/resources/js/libs/menubar/util/cleanOptions.spec.ts new file mode 100644 index 00000000..0beb163e --- /dev/null +++ b/resources/js/libs/menubar/util/cleanOptions.spec.ts @@ -0,0 +1,70 @@ +import * as path from 'path'; + +import { MOCK_APP_GETAPPPATH } from '../__mocks__/electron'; +import { cleanOptions } from './cleanOptions'; + +const DEFAULT_OPTIONS = { + activateWithApp: true, + browserWindow: { + height: 400, + width: 400, + }, + dir: path.resolve(MOCK_APP_GETAPPPATH), + index: `file://${path.join(path.resolve(MOCK_APP_GETAPPPATH), 'index.html')}`, + loadUrlOptions: {}, + tooltip: '', +}; + +describe('cleanOptions', () => { + it('should handle undefined', () => { + expect(cleanOptions(undefined)).toEqual(DEFAULT_OPTIONS); + }); + + it('should handle a dir string with relative path', () => { + expect(cleanOptions({ dir: 'MY_RELATIVE_PATH' })).toEqual({ + ...DEFAULT_OPTIONS, + dir: path.resolve('MY_RELATIVE_PATH'), + index: `file://${path.join( + path.resolve('MY_RELATIVE_PATH'), + 'index.html', + )}`, + }); + }); + + it('should handle a dir string with absolute path', () => { + expect(cleanOptions({ dir: '/home/me/MY_ABSOLUTE_PATH' })).toEqual({ + ...DEFAULT_OPTIONS, + dir: '/home/me/MY_ABSOLUTE_PATH', + index: 'file:///home/me/MY_ABSOLUTE_PATH/index.html', + }); + }); + + it('should handle a false index', () => { + expect(cleanOptions({ index: false })).toEqual({ + ...DEFAULT_OPTIONS, + index: false, + }); + }); + + it('should handle an object with multiple fields', () => { + expect( + cleanOptions({ + browserWindow: { + height: 100, + }, + index: 'file:///home/abc/index.html', + showDockIcon: true, + windowPosition: 'trayCenter', + }), + ).toEqual({ + ...DEFAULT_OPTIONS, + browserWindow: { + ...DEFAULT_OPTIONS.browserWindow, + height: 100, + }, + index: 'file:///home/abc/index.html', + showDockIcon: true, + windowPosition: 'trayCenter', + }); + }); +}); diff --git a/resources/js/libs/menubar/util/cleanOptions.ts b/resources/js/libs/menubar/util/cleanOptions.ts new file mode 100644 index 00000000..d677340d --- /dev/null +++ b/resources/js/libs/menubar/util/cleanOptions.ts @@ -0,0 +1,67 @@ +/** + * @ignore + */ + +/** */ + +import path from 'path'; +import url from 'url'; +import { app } from 'electron'; + +import type { Options } from '../types.js'; + +const DEFAULT_WINDOW_HEIGHT = 400; +const DEFAULT_WINDOW_WIDTH = 400; + +/** + * Take as input some options, and return a sanitized version of it. + * + * @param opts - The options to clean. + * @ignore + */ +export function cleanOptions(opts?: Partial): Options { + const options: Partial = { ...opts }; + + if (options.activateWithApp === undefined) { + options.activateWithApp = true; + } + if (!options.dir) { + options.dir = app.getAppPath(); + } + if (!path.isAbsolute(options.dir)) { + options.dir = path.resolve(options.dir); + } + // Note: options.index can be `false` + if (options.index === undefined) { + options.index = url.format({ + pathname: path.join(options.dir, 'index.html'), + protocol: 'file:', + slashes: true, + }); + } + options.loadUrlOptions = options.loadUrlOptions || {}; + + options.tooltip = options.tooltip || ''; + + // `icon`, `preloadWindow`, `showDockIcon`, `showOnAllWorkspaces`, + // `showOnRightClick` don't need any special treatment + + // Now we take care of `browserWindow` + if (!options.browserWindow) { + options.browserWindow = {}; + } + + // Set width/height on options to be usable before the window is created + options.browserWindow.width = + // Note: not using `options.browserWindow.width || DEFAULT_WINDOW_WIDTH` so + // that users can put a 0 width + options.browserWindow.width !== undefined + ? options.browserWindow.width + : DEFAULT_WINDOW_WIDTH; + options.browserWindow.height = + options.browserWindow.height !== undefined + ? options.browserWindow.height + : DEFAULT_WINDOW_HEIGHT; + + return options as Options; +} diff --git a/resources/js/libs/menubar/util/getWindowPosition.d.ts b/resources/js/libs/menubar/util/getWindowPosition.d.ts deleted file mode 100644 index 9b9d04a9..00000000 --- a/resources/js/libs/menubar/util/getWindowPosition.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Utilities to get taskbar position and consequently menubar's position - */ -/** */ -import { type Tray } from 'electron'; -type TaskbarLocation = 'top' | 'bottom' | 'left' | 'right'; -/** - * Determine taskbard location: "top", "bottom", "left" or "right". - * - * Only tested on Windows for now, and only used in Windows. - * - * @param tray - The Electron Tray instance. - */ -export declare function taskbarLocation(tray: Tray): TaskbarLocation; -type WindowPosition = 'trayCenter' | 'topRight' | 'trayBottomCenter' | 'bottomLeft' | 'bottomRight'; -/** - * Depending on where the taskbar is, determine where the window should be - * positioned. - * - * @param tray - The Electron Tray instance. - */ -export declare function getWindowPosition(tray: Tray): WindowPosition; -export {}; diff --git a/resources/js/libs/menubar/util/getWindowPosition.js b/resources/js/libs/menubar/util/getWindowPosition.js deleted file mode 100644 index c568ab54..00000000 --- a/resources/js/libs/menubar/util/getWindowPosition.js +++ /dev/null @@ -1,88 +0,0 @@ -"use strict"; -/** - * Utilities to get taskbar position and consequently menubar's position - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.getWindowPosition = exports.taskbarLocation = void 0; -/** */ -var electron_1 = require("electron"); -var isLinux = process.platform === 'linux'; -var trayToScreenRects = function (tray) { - // There may be more than one screen, so we need to figure out on which screen our tray icon lives. - var _a = electron_1.screen.getDisplayMatching(tray.getBounds()), workArea = _a.workArea, screenBounds = _a.bounds; - workArea.x -= screenBounds.x; - workArea.y -= screenBounds.y; - return [screenBounds, workArea]; -}; -/** - * Determine taskbard location: "top", "bottom", "left" or "right". - * - * Only tested on Windows for now, and only used in Windows. - * - * @param tray - The Electron Tray instance. - */ -function taskbarLocation(tray) { - var _a = trayToScreenRects(tray), screenBounds = _a[0], workArea = _a[1]; - // TASKBAR LEFT - if (workArea.x > 0) { - // Most likely Ubuntu hence assuming the window should be on top - if (isLinux && workArea.y > 0) - return 'top'; - // The workspace starts more on the right - return 'left'; - } - // TASKBAR TOP - if (workArea.y > 0) { - return 'top'; - } - // TASKBAR RIGHT - // Here both workArea.y and workArea.x are 0 so we can no longer leverage them. - // We can use the workarea and display width though. - // Determine taskbar location - if (workArea.width < screenBounds.width) { - // The taskbar is either on the left or right, but since the LEFT case was handled above, - // we can be sure we're dealing with a right taskbar - return 'right'; - } - // TASKBAR BOTTOM - // Since all the other cases were handled, we can be sure we're dealing with a bottom taskbar - return 'bottom'; -} -exports.taskbarLocation = taskbarLocation; -/** - * Depending on where the taskbar is, determine where the window should be - * positioned. - * - * @param tray - The Electron Tray instance. - */ -function getWindowPosition(tray) { - switch (process.platform) { - // macOS - // Supports top taskbars - case 'darwin': - return 'trayCenter'; - // Linux - // Windows - // Supports top/bottom/left/right taskbar - case 'linux': - case 'win32': { - var traySide = taskbarLocation(tray); - // Assign position for menubar - if (traySide === 'top') { - return isLinux ? 'topRight' : 'trayCenter'; - } - if (traySide === 'bottom') { - return 'bottomRight'; - } - if (traySide === 'left') { - return 'bottomLeft'; - } - if (traySide === 'right') { - return 'bottomRight'; - } - } - } - // When we really don't know, we just show the menubar on the top-right - return 'topRight'; -} -exports.getWindowPosition = getWindowPosition; diff --git a/resources/js/libs/menubar/util/getWindowPosition.ts b/resources/js/libs/menubar/util/getWindowPosition.ts new file mode 100644 index 00000000..a4010a6b --- /dev/null +++ b/resources/js/libs/menubar/util/getWindowPosition.ts @@ -0,0 +1,107 @@ +/** + * Utilities to get taskbar position and consequently menubar's position + */ + +/** */ + +import { type Rectangle, type Tray, screen as electronScreen } from 'electron'; + +const isLinux = process.platform === 'linux'; + +const trayToScreenRects = (tray: Tray): [Rectangle, Rectangle] => { + // There may be more than one screen, so we need to figure out on which screen our tray icon lives. + const { workArea, bounds: screenBounds } = electronScreen.getDisplayMatching( + tray.getBounds(), + ); + + workArea.x -= screenBounds.x; + workArea.y -= screenBounds.y; + + return [screenBounds, workArea]; +}; + +type TaskbarLocation = 'top' | 'bottom' | 'left' | 'right'; + +/** + * Determine taskbard location: "top", "bottom", "left" or "right". + * + * Only tested on Windows for now, and only used in Windows. + * + * @param tray - The Electron Tray instance. + */ +export function taskbarLocation(tray: Tray): TaskbarLocation { + const [screenBounds, workArea] = trayToScreenRects(tray); + + // TASKBAR LEFT + if (workArea.x > 0) { + // Most likely Ubuntu hence assuming the window should be on top + if (isLinux && workArea.y > 0) return 'top'; + // The workspace starts more on the right + return 'left'; + } + + // TASKBAR TOP + if (workArea.y > 0) { + return 'top'; + } + + // TASKBAR RIGHT + // Here both workArea.y and workArea.x are 0 so we can no longer leverage them. + // We can use the workarea and display width though. + // Determine taskbar location + if (workArea.width < screenBounds.width) { + // The taskbar is either on the left or right, but since the LEFT case was handled above, + // we can be sure we're dealing with a right taskbar + return 'right'; + } + + // TASKBAR BOTTOM + // Since all the other cases were handled, we can be sure we're dealing with a bottom taskbar + return 'bottom'; +} + +type WindowPosition = + | 'trayCenter' + | 'topRight' + | 'trayBottomCenter' + | 'bottomLeft' + | 'bottomRight'; + +/** + * Depending on where the taskbar is, determine where the window should be + * positioned. + * + * @param tray - The Electron Tray instance. + */ +export function getWindowPosition(tray: Tray): WindowPosition { + switch (process.platform) { + // macOS + // Supports top taskbars + case 'darwin': + return 'trayCenter'; + // Linux + // Windows + // Supports top/bottom/left/right taskbar + case 'linux': + case 'win32': { + const traySide = taskbarLocation(tray); + + // Assign position for menubar + if (traySide === 'top') { + return isLinux ? 'topRight' : 'trayCenter'; + } + if (traySide === 'bottom') { + return 'bottomRight'; + } + if (traySide === 'left') { + return 'bottomLeft'; + } + if (traySide === 'right') { + return 'bottomRight'; + } + } + } + + // When we really don't know, we just show the menubar on the top-right + return 'topRight'; +} From b5d8f68251eecae3fd0d2d321ef092a66979ec97 Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 13:39:07 +0200 Subject: [PATCH 07/11] move libs inside plugin src to avoid path issues rollup would create another level of nesting which required to change imports in multiple places. I'd rather not touch any other imports for this change. Moving everything inside the plugin src directory has the least impact across unrelated files --- .../src}/libs/menubar/Menubar.ts | 0 .../src}/libs/menubar/ambient.d.ts | 0 .../src}/libs/menubar/index.ts | 0 .../src}/libs/menubar/types.ts | 0 .../src}/libs/menubar/util/cleanOptions.ts | 0 .../libs/menubar/util/getWindowPosition.ts | 0 .../src}/libs/positioner/README.md | 0 .../src/libs/positioner/index.ts} | 11 ++- .../electron-plugin/src/server/api/menuBar.ts | 2 +- resources/js/libs/menubar/Menubar.spec.ts | 45 ------------ .../js/libs/menubar/util/cleanOptions.spec.ts | 70 ------------------- 11 files changed, 9 insertions(+), 119 deletions(-) rename resources/js/{ => electron-plugin/src}/libs/menubar/Menubar.ts (100%) rename resources/js/{ => electron-plugin/src}/libs/menubar/ambient.d.ts (100%) rename resources/js/{ => electron-plugin/src}/libs/menubar/index.ts (100%) rename resources/js/{ => electron-plugin/src}/libs/menubar/types.ts (100%) rename resources/js/{ => electron-plugin/src}/libs/menubar/util/cleanOptions.ts (100%) rename resources/js/{ => electron-plugin/src}/libs/menubar/util/getWindowPosition.ts (100%) rename resources/js/{ => electron-plugin/src}/libs/positioner/README.md (100%) rename resources/js/{libs/positioner/index.js => electron-plugin/src/libs/positioner/index.ts} (97%) delete mode 100644 resources/js/libs/menubar/Menubar.spec.ts delete mode 100644 resources/js/libs/menubar/util/cleanOptions.spec.ts diff --git a/resources/js/libs/menubar/Menubar.ts b/resources/js/electron-plugin/src/libs/menubar/Menubar.ts similarity index 100% rename from resources/js/libs/menubar/Menubar.ts rename to resources/js/electron-plugin/src/libs/menubar/Menubar.ts diff --git a/resources/js/libs/menubar/ambient.d.ts b/resources/js/electron-plugin/src/libs/menubar/ambient.d.ts similarity index 100% rename from resources/js/libs/menubar/ambient.d.ts rename to resources/js/electron-plugin/src/libs/menubar/ambient.d.ts diff --git a/resources/js/libs/menubar/index.ts b/resources/js/electron-plugin/src/libs/menubar/index.ts similarity index 100% rename from resources/js/libs/menubar/index.ts rename to resources/js/electron-plugin/src/libs/menubar/index.ts diff --git a/resources/js/libs/menubar/types.ts b/resources/js/electron-plugin/src/libs/menubar/types.ts similarity index 100% rename from resources/js/libs/menubar/types.ts rename to resources/js/electron-plugin/src/libs/menubar/types.ts diff --git a/resources/js/libs/menubar/util/cleanOptions.ts b/resources/js/electron-plugin/src/libs/menubar/util/cleanOptions.ts similarity index 100% rename from resources/js/libs/menubar/util/cleanOptions.ts rename to resources/js/electron-plugin/src/libs/menubar/util/cleanOptions.ts diff --git a/resources/js/libs/menubar/util/getWindowPosition.ts b/resources/js/electron-plugin/src/libs/menubar/util/getWindowPosition.ts similarity index 100% rename from resources/js/libs/menubar/util/getWindowPosition.ts rename to resources/js/electron-plugin/src/libs/menubar/util/getWindowPosition.ts diff --git a/resources/js/libs/positioner/README.md b/resources/js/electron-plugin/src/libs/positioner/README.md similarity index 100% rename from resources/js/libs/positioner/README.md rename to resources/js/electron-plugin/src/libs/positioner/README.md diff --git a/resources/js/libs/positioner/index.js b/resources/js/electron-plugin/src/libs/positioner/index.ts similarity index 97% rename from resources/js/libs/positioner/index.js rename to resources/js/electron-plugin/src/libs/positioner/index.ts index f7311a37..eacd4c31 100644 --- a/resources/js/libs/positioner/index.js +++ b/resources/js/electron-plugin/src/libs/positioner/index.ts @@ -1,7 +1,10 @@ "use strict"; -module.exports = class Positioner { - constructor(browserWindow) { +class Positioner { + browserWindow: any; + electronScreen: any; + + constructor(browserWindow: any) { this.browserWindow = browserWindow; this.electronScreen = require("electron").screen; } @@ -165,4 +168,6 @@ module.exports = class Positioner { y: coords.y, }; } -}; +} + +export default Positioner; diff --git a/resources/js/electron-plugin/src/server/api/menuBar.ts b/resources/js/electron-plugin/src/server/api/menuBar.ts index 18a43445..af718df6 100644 --- a/resources/js/electron-plugin/src/server/api/menuBar.ts +++ b/resources/js/electron-plugin/src/server/api/menuBar.ts @@ -2,7 +2,7 @@ import express from "express"; import { app, Menu, Tray } from "electron"; import { compileMenu } from "./helper/index.js"; import state from "../state.js"; -import { menubar } from "../../../../libs/menubar/index.js"; +import { menubar } from "../../libs/menubar/index.js"; import { notifyLaravel } from "../utils.js"; import { fileURLToPath } from 'url' import { enable } from "@electron/remote/main/index.js"; diff --git a/resources/js/libs/menubar/Menubar.spec.ts b/resources/js/libs/menubar/Menubar.spec.ts deleted file mode 100644 index fb641fd5..00000000 --- a/resources/js/libs/menubar/Menubar.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { BrowserWindow, Tray, app } from 'electron'; - -import { Menubar } from './Menubar'; - -describe('Menubar', () => { - let mb: Menubar | undefined; - - beforeEach(() => { - mb = new Menubar(app, { preloadWindow: true }); - }); - - it('should have property `app`', () => { - expect(mb!.app).toBeDefined(); - }); - - it('should have property `positioner`', () => { - expect(() => mb!.positioner as unknown).toThrow(); - return new Promise((resolve) => { - mb!.on('after-create-window', () => { - expect(mb!.positioner).toBeDefined(); - resolve(); - }); - }); - }); - - it('should have property `tray`', () => { - expect(() => mb!.tray).toThrow(); - return new Promise((resolve) => { - mb!.on('ready', () => { - expect(mb!.tray).toBeInstanceOf(Tray); - resolve(); - }); - }); - }); - - it('should have property `window`', () => { - expect(mb!.window).toBeUndefined(); - return new Promise((resolve) => { - mb!.on('ready', () => { - expect(mb!.window).toBeInstanceOf(BrowserWindow); - resolve(); - }); - }); - }); -}); diff --git a/resources/js/libs/menubar/util/cleanOptions.spec.ts b/resources/js/libs/menubar/util/cleanOptions.spec.ts deleted file mode 100644 index 0beb163e..00000000 --- a/resources/js/libs/menubar/util/cleanOptions.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import * as path from 'path'; - -import { MOCK_APP_GETAPPPATH } from '../__mocks__/electron'; -import { cleanOptions } from './cleanOptions'; - -const DEFAULT_OPTIONS = { - activateWithApp: true, - browserWindow: { - height: 400, - width: 400, - }, - dir: path.resolve(MOCK_APP_GETAPPPATH), - index: `file://${path.join(path.resolve(MOCK_APP_GETAPPPATH), 'index.html')}`, - loadUrlOptions: {}, - tooltip: '', -}; - -describe('cleanOptions', () => { - it('should handle undefined', () => { - expect(cleanOptions(undefined)).toEqual(DEFAULT_OPTIONS); - }); - - it('should handle a dir string with relative path', () => { - expect(cleanOptions({ dir: 'MY_RELATIVE_PATH' })).toEqual({ - ...DEFAULT_OPTIONS, - dir: path.resolve('MY_RELATIVE_PATH'), - index: `file://${path.join( - path.resolve('MY_RELATIVE_PATH'), - 'index.html', - )}`, - }); - }); - - it('should handle a dir string with absolute path', () => { - expect(cleanOptions({ dir: '/home/me/MY_ABSOLUTE_PATH' })).toEqual({ - ...DEFAULT_OPTIONS, - dir: '/home/me/MY_ABSOLUTE_PATH', - index: 'file:///home/me/MY_ABSOLUTE_PATH/index.html', - }); - }); - - it('should handle a false index', () => { - expect(cleanOptions({ index: false })).toEqual({ - ...DEFAULT_OPTIONS, - index: false, - }); - }); - - it('should handle an object with multiple fields', () => { - expect( - cleanOptions({ - browserWindow: { - height: 100, - }, - index: 'file:///home/abc/index.html', - showDockIcon: true, - windowPosition: 'trayCenter', - }), - ).toEqual({ - ...DEFAULT_OPTIONS, - browserWindow: { - ...DEFAULT_OPTIONS.browserWindow, - height: 100, - }, - index: 'file:///home/abc/index.html', - showDockIcon: true, - windowPosition: 'trayCenter', - }); - }); -}); From 597f5900816507afa897dba9e0ce7301962c37e2 Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 13:40:30 +0200 Subject: [PATCH 08/11] update lock files --- resources/js/package-lock.json | 4 ++-- resources/js/yarn.lock | 20 ++++---------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/resources/js/package-lock.json b/resources/js/package-lock.json index 6b5fea11..d4ecc505 100644 --- a/resources/js/package-lock.json +++ b/resources/js/package-lock.json @@ -1,11 +1,11 @@ { - "name": "NativePHP", + "name": "laravel-dev", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "NativePHP", + "name": "laravel-dev", "version": "1.0.0", "hasInstallScript": true, "dependencies": { diff --git a/resources/js/yarn.lock b/resources/js/yarn.lock index c99d976d..371d1ee8 100644 --- a/resources/js/yarn.lock +++ b/resources/js/yarn.lock @@ -2275,9 +2275,9 @@ callsites@^3.0.0: integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== caniuse-lite@^1.0.30001737: - version "1.0.30001739" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz" - integrity sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA== + version "1.0.30001741" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz" + integrity sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw== chai@^5.2.0: version "5.3.3" @@ -2838,11 +2838,6 @@ electron-is-dev@^3.0.1: resolved "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-3.0.1.tgz" integrity sha512-8TjjAh8Ec51hUi3o4TaU0mD3GMTOESi866oRNavj9A3IQJ7pmv+MJVmdZBFGw4GFT36X7bkqnuDNYvkQgvyI8Q== -electron-positioner@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/electron-positioner/-/electron-positioner-4.1.0.tgz" - integrity sha512-726DfbI9ZNoCg+Fcu6XLuTKTnzf+6nFqv7h+K/V6Ug7IbaPMI7s9S8URnGtWFCy5N5PL4HSzRFF2mXuinftDdg== - electron-publish@25.1.7: version "25.1.7" resolved "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz" @@ -2903,7 +2898,7 @@ electron-window-state@^5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@^32.2.7, "electron@>= 13.0.0", electron@>=13.0.0, "electron@>=9.0.0 <33.0.0": +electron@^32.2.7, "electron@>= 13.0.0", electron@>=13.0.0: version "32.3.3" resolved "https://registry.npmjs.org/electron/-/electron-32.3.3.tgz" integrity sha512-7FT8tDg+MueAw8dBn5LJqDvlM4cZkKJhXfgB3w7P5gvSoUQVAY6LIQcXJxgL+vw2rIRY/b9ak7ZBFbCMF2Bk4w== @@ -4501,13 +4496,6 @@ media-typer@^1.1.0: resolved "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz" integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== -menubar@^9.5.1: - version "9.5.1" - resolved "https://registry.npmjs.org/menubar/-/menubar-9.5.1.tgz" - integrity sha512-swfgKal+DTgJINay36X+LGBSqyFKS4d9FyJ2w0s/4MtO7/UGplEZqluLTnq4xgLNxNjMWhXycOELP+rRYpTagA== - dependencies: - electron-positioner "^4.1.0" - meow@^13.2.0: version "13.2.0" resolved "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz" From 70c4e415de752c4488c3bea644c816e1c1cc9ccf Mon Sep 17 00:00:00 2001 From: gwleuverink <17123491+gwleuverink@users.noreply.github.com> Date: Fri, 5 Sep 2025 11:42:23 +0000 Subject: [PATCH 09/11] Build plugin --- .../dist/libs/menubar/Menubar.js | 201 ++++++++++++++++++ .../dist/libs/menubar/index.js | 7 + .../dist/libs/menubar/types.js | 1 + .../dist/libs/menubar/util/cleanOptions.js | 38 ++++ .../libs/menubar/util/getWindowPosition.js | 46 ++++ .../dist/libs/positioner/index.js | 113 ++++++++++ .../dist/server/api/menuBar.js | 2 +- resources/js/package-lock.json | 4 +- 8 files changed, 409 insertions(+), 3 deletions(-) create mode 100644 resources/js/electron-plugin/dist/libs/menubar/Menubar.js create mode 100644 resources/js/electron-plugin/dist/libs/menubar/index.js create mode 100644 resources/js/electron-plugin/dist/libs/menubar/types.js create mode 100644 resources/js/electron-plugin/dist/libs/menubar/util/cleanOptions.js create mode 100644 resources/js/electron-plugin/dist/libs/menubar/util/getWindowPosition.js create mode 100644 resources/js/electron-plugin/dist/libs/positioner/index.js diff --git a/resources/js/electron-plugin/dist/libs/menubar/Menubar.js b/resources/js/electron-plugin/dist/libs/menubar/Menubar.js new file mode 100644 index 00000000..8d28be49 --- /dev/null +++ b/resources/js/electron-plugin/dist/libs/menubar/Menubar.js @@ -0,0 +1,201 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +import { EventEmitter } from 'events'; +import fs from 'fs'; +import path from 'path'; +import { BrowserWindow, Tray } from 'electron'; +import Positioner from '../positioner/index.js'; +import { cleanOptions } from './util/cleanOptions.js'; +import { getWindowPosition } from './util/getWindowPosition.js'; +export class Menubar extends EventEmitter { + constructor(app, options) { + super(); + this._blurTimeout = null; + this._app = app; + this._options = cleanOptions(options); + this._isVisible = false; + if (app.isReady()) { + process.nextTick(() => this.appReady().catch((err) => console.error('menubar: ', err))); + } + else { + app.on('ready', () => { + this.appReady().catch((err) => console.error('menubar: ', err)); + }); + } + } + get app() { + return this._app; + } + get positioner() { + if (!this._positioner) { + throw new Error('Please access `this.positioner` after the `after-create-window` event has fired.'); + } + return this._positioner; + } + get tray() { + if (!this._tray) { + throw new Error('Please access `this.tray` after the `ready` event has fired.'); + } + return this._tray; + } + get window() { + return this._browserWindow; + } + getOption(key) { + return this._options[key]; + } + hideWindow() { + if (!this._browserWindow || !this._isVisible) { + return; + } + this.emit('hide'); + this._browserWindow.hide(); + this.emit('after-hide'); + this._isVisible = false; + if (this._blurTimeout) { + clearTimeout(this._blurTimeout); + this._blurTimeout = null; + } + } + setOption(key, value) { + this._options[key] = value; + } + showWindow(trayPos) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.tray) { + throw new Error('Tray should have been instantiated by now'); + } + if (!this._browserWindow) { + yield this.createWindow(); + } + if (!this._browserWindow) { + throw new Error('Window has been initialized just above. qed.'); + } + if (['win32', 'linux'].includes(process.platform)) { + this._options.windowPosition = getWindowPosition(this.tray); + } + this.emit('show'); + if (trayPos && trayPos.x !== 0) { + this._cachedBounds = trayPos; + } + else if (this._cachedBounds) { + trayPos = this._cachedBounds; + } + else if (this.tray.getBounds) { + trayPos = this.tray.getBounds(); + } + let noBoundsPosition = undefined; + if ((trayPos === undefined || trayPos.x === 0) && + this._options.windowPosition && + this._options.windowPosition.startsWith('tray')) { + noBoundsPosition = + process.platform === 'win32' ? 'bottomRight' : 'topRight'; + } + const position = this.positioner.calculate(this._options.windowPosition || noBoundsPosition, trayPos); + const x = this._options.browserWindow.x !== undefined + ? this._options.browserWindow.x + : position.x; + const y = this._options.browserWindow.y !== undefined + ? this._options.browserWindow.y + : position.y; + this._browserWindow.setPosition(Math.round(x), Math.round(y)); + this._browserWindow.show(); + this._isVisible = true; + this.emit('after-show'); + return; + }); + } + appReady() { + return __awaiter(this, void 0, void 0, function* () { + if (this.app.dock && !this._options.showDockIcon) { + this.app.dock.hide(); + } + if (this._options.activateWithApp) { + this.app.on('activate', (_event, hasVisibleWindows) => { + if (!hasVisibleWindows) { + this.showWindow().catch(console.error); + } + }); + } + let trayImage = this._options.icon || path.join(this._options.dir, 'IconTemplate.png'); + if (typeof trayImage === 'string' && !fs.existsSync(trayImage)) { + trayImage = path.join(__dirname, '..', 'assets', 'IconTemplate.png'); + } + const defaultClickEvent = this._options.showOnRightClick + ? 'right-click' + : 'click'; + this._tray = this._options.tray || new Tray(trayImage); + if (!this.tray) { + throw new Error('Tray has been initialized above'); + } + this.tray.on(defaultClickEvent, this.clicked.bind(this)); + this.tray.on('double-click', this.clicked.bind(this)); + this.tray.setToolTip(this._options.tooltip); + if (!this._options.windowPosition) { + this._options.windowPosition = getWindowPosition(this.tray); + } + if (this._options.preloadWindow) { + yield this.createWindow(); + } + this.emit('ready'); + }); + } + clicked(event, bounds) { + return __awaiter(this, void 0, void 0, function* () { + if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { + return this.hideWindow(); + } + if (this._blurTimeout) { + clearInterval(this._blurTimeout); + } + if (this._browserWindow && this._isVisible) { + return this.hideWindow(); + } + this._cachedBounds = bounds || this._cachedBounds; + yield this.showWindow(this._cachedBounds); + }); + } + createWindow() { + return __awaiter(this, void 0, void 0, function* () { + this.emit('create-window'); + const defaults = { + show: false, + frame: false, + }; + this._browserWindow = new BrowserWindow(Object.assign(Object.assign({}, defaults), this._options.browserWindow)); + this._positioner = new Positioner(this._browserWindow); + this._browserWindow.on('blur', () => { + if (!this._browserWindow) { + return; + } + this._browserWindow.isAlwaysOnTop() + ? this.emit('focus-lost') + : (this._blurTimeout = setTimeout(() => { + this.hideWindow(); + }, 100)); + }); + if (this._options.showOnAllWorkspaces !== false) { + this._browserWindow.setVisibleOnAllWorkspaces(true, { + skipTransformProcessType: true, + }); + } + this._browserWindow.on('close', this.windowClear.bind(this)); + this.emit('before-load'); + if (this._options.index !== false) { + yield this._browserWindow.loadURL(this._options.index, this._options.loadUrlOptions); + } + this.emit('after-create-window'); + }); + } + windowClear() { + this._browserWindow = undefined; + this.emit('after-close'); + } +} diff --git a/resources/js/electron-plugin/dist/libs/menubar/index.js b/resources/js/electron-plugin/dist/libs/menubar/index.js new file mode 100644 index 00000000..d996c034 --- /dev/null +++ b/resources/js/electron-plugin/dist/libs/menubar/index.js @@ -0,0 +1,7 @@ +import { app } from 'electron'; +import { Menubar } from './Menubar.js'; +export * from './util/getWindowPosition.js'; +export { Menubar }; +export function menubar(options) { + return new Menubar(app, options); +} diff --git a/resources/js/electron-plugin/dist/libs/menubar/types.js b/resources/js/electron-plugin/dist/libs/menubar/types.js new file mode 100644 index 00000000..cb0ff5c3 --- /dev/null +++ b/resources/js/electron-plugin/dist/libs/menubar/types.js @@ -0,0 +1 @@ +export {}; diff --git a/resources/js/electron-plugin/dist/libs/menubar/util/cleanOptions.js b/resources/js/electron-plugin/dist/libs/menubar/util/cleanOptions.js new file mode 100644 index 00000000..d6b7ac0b --- /dev/null +++ b/resources/js/electron-plugin/dist/libs/menubar/util/cleanOptions.js @@ -0,0 +1,38 @@ +import path from 'path'; +import url from 'url'; +import { app } from 'electron'; +const DEFAULT_WINDOW_HEIGHT = 400; +const DEFAULT_WINDOW_WIDTH = 400; +export function cleanOptions(opts) { + const options = Object.assign({}, opts); + if (options.activateWithApp === undefined) { + options.activateWithApp = true; + } + if (!options.dir) { + options.dir = app.getAppPath(); + } + if (!path.isAbsolute(options.dir)) { + options.dir = path.resolve(options.dir); + } + if (options.index === undefined) { + options.index = url.format({ + pathname: path.join(options.dir, 'index.html'), + protocol: 'file:', + slashes: true, + }); + } + options.loadUrlOptions = options.loadUrlOptions || {}; + options.tooltip = options.tooltip || ''; + if (!options.browserWindow) { + options.browserWindow = {}; + } + options.browserWindow.width = + options.browserWindow.width !== undefined + ? options.browserWindow.width + : DEFAULT_WINDOW_WIDTH; + options.browserWindow.height = + options.browserWindow.height !== undefined + ? options.browserWindow.height + : DEFAULT_WINDOW_HEIGHT; + return options; +} diff --git a/resources/js/electron-plugin/dist/libs/menubar/util/getWindowPosition.js b/resources/js/electron-plugin/dist/libs/menubar/util/getWindowPosition.js new file mode 100644 index 00000000..1c290434 --- /dev/null +++ b/resources/js/electron-plugin/dist/libs/menubar/util/getWindowPosition.js @@ -0,0 +1,46 @@ +import { screen as electronScreen } from 'electron'; +const isLinux = process.platform === 'linux'; +const trayToScreenRects = (tray) => { + const { workArea, bounds: screenBounds } = electronScreen.getDisplayMatching(tray.getBounds()); + workArea.x -= screenBounds.x; + workArea.y -= screenBounds.y; + return [screenBounds, workArea]; +}; +export function taskbarLocation(tray) { + const [screenBounds, workArea] = trayToScreenRects(tray); + if (workArea.x > 0) { + if (isLinux && workArea.y > 0) + return 'top'; + return 'left'; + } + if (workArea.y > 0) { + return 'top'; + } + if (workArea.width < screenBounds.width) { + return 'right'; + } + return 'bottom'; +} +export function getWindowPosition(tray) { + switch (process.platform) { + case 'darwin': + return 'trayCenter'; + case 'linux': + case 'win32': { + const traySide = taskbarLocation(tray); + if (traySide === 'top') { + return isLinux ? 'topRight' : 'trayCenter'; + } + if (traySide === 'bottom') { + return 'bottomRight'; + } + if (traySide === 'left') { + return 'bottomLeft'; + } + if (traySide === 'right') { + return 'bottomRight'; + } + } + } + return 'topRight'; +} diff --git a/resources/js/electron-plugin/dist/libs/positioner/index.js b/resources/js/electron-plugin/dist/libs/positioner/index.js new file mode 100644 index 00000000..2608c4ed --- /dev/null +++ b/resources/js/electron-plugin/dist/libs/positioner/index.js @@ -0,0 +1,113 @@ +"use strict"; +class Positioner { + constructor(browserWindow) { + this.browserWindow = browserWindow; + this.electronScreen = require("electron").screen; + } + _getCoords(position, trayPosition) { + let screenSize = this._getScreenSize(trayPosition); + let windowSize = this._getWindowSize(); + if (trayPosition === undefined) + trayPosition = {}; + let positions = { + trayLeft: { + x: Math.floor(trayPosition.x), + y: screenSize.y, + }, + trayBottomLeft: { + x: Math.floor(trayPosition.x), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), + }, + trayRight: { + x: Math.floor(trayPosition.x - windowSize[0] + trayPosition.width), + y: screenSize.y, + }, + trayBottomRight: { + x: Math.floor(trayPosition.x - windowSize[0] + trayPosition.width), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), + }, + trayCenter: { + x: Math.floor(trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2), + y: screenSize.y, + }, + trayBottomCenter: { + x: Math.floor(trayPosition.x - windowSize[0] / 2 + trayPosition.width / 2), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), + }, + topLeft: { + x: screenSize.x, + y: screenSize.y, + }, + topRight: { + x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])), + y: screenSize.y, + }, + bottomLeft: { + x: screenSize.x, + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), + }, + bottomRight: { + x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), + }, + topCenter: { + x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)), + y: screenSize.y, + }, + bottomCenter: { + x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)), + y: Math.floor(screenSize.height - (windowSize[1] - screenSize.y)), + }, + leftCenter: { + x: screenSize.x, + y: screenSize.y + + Math.floor(screenSize.height / 2) - + Math.floor(windowSize[1] / 2), + }, + rightCenter: { + x: Math.floor(screenSize.x + (screenSize.width - windowSize[0])), + y: screenSize.y + + Math.floor(screenSize.height / 2) - + Math.floor(windowSize[1] / 2), + }, + center: { + x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)), + y: Math.floor((screenSize.height + screenSize.y) / 2 - windowSize[1] / 2), + }, + }; + if (position.substr(0, 4) === "tray") { + if (positions[position].x + windowSize[0] > + screenSize.width + screenSize.x) { + return { + x: positions["topRight"].x, + y: positions[position].y, + }; + } + } + return positions[position]; + } + _getWindowSize() { + return this.browserWindow.getSize(); + } + _getScreenSize(trayPosition) { + if (trayPosition) { + return this.electronScreen.getDisplayMatching(trayPosition) + .workArea; + } + else { + return this.electronScreen.getDisplayNearestPoint(this.electronScreen.getCursorScreenPoint()).workArea; + } + } + move(position, trayPos) { + var coords = this._getCoords(position, trayPos); + this.browserWindow.setPosition(coords.x, coords.y); + } + calculate(position, trayPos) { + var coords = this._getCoords(position, trayPos); + return { + x: coords.x, + y: coords.y, + }; + } +} +export default Positioner; diff --git a/resources/js/electron-plugin/dist/server/api/menuBar.js b/resources/js/electron-plugin/dist/server/api/menuBar.js index 489f04a8..0271f7c3 100644 --- a/resources/js/electron-plugin/dist/server/api/menuBar.js +++ b/resources/js/electron-plugin/dist/server/api/menuBar.js @@ -2,7 +2,7 @@ import express from "express"; import { app, Menu, Tray } from "electron"; import { compileMenu } from "./helper/index.js"; import state from "../state.js"; -import { menubar } from "../../../../libs/menubar/index.js"; +import { menubar } from "../../libs/menubar/index.js"; import { notifyLaravel } from "../utils.js"; import { fileURLToPath } from 'url'; import { enable } from "@electron/remote/main/index.js"; diff --git a/resources/js/package-lock.json b/resources/js/package-lock.json index d4ecc505..6b5fea11 100644 --- a/resources/js/package-lock.json +++ b/resources/js/package-lock.json @@ -1,11 +1,11 @@ { - "name": "laravel-dev", + "name": "NativePHP", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "laravel-dev", + "name": "NativePHP", "version": "1.0.0", "hasInstallScript": true, "dependencies": { From d00bab05172d34a7b3c2e5935aaf312ffe7640b3 Mon Sep 17 00:00:00 2001 From: gwleuverink Date: Fri, 5 Sep 2025 16:48:23 +0200 Subject: [PATCH 10/11] update electron & chromedriver to `^38` --- resources/js/package-lock.json | 50 ++++++----- resources/js/package.json | 4 +- resources/js/yarn.lock | 151 +++++++++++++++++++++++++-------- 3 files changed, 145 insertions(+), 60 deletions(-) diff --git a/resources/js/package-lock.json b/resources/js/package-lock.json index d4ecc505..f702d234 100644 --- a/resources/js/package-lock.json +++ b/resources/js/package-lock.json @@ -1,11 +1,11 @@ { - "name": "laravel-dev", + "name": "NativePHP", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "laravel-dev", + "name": "NativePHP", "version": "1.0.0", "hasInstallScript": true, "dependencies": { @@ -46,9 +46,9 @@ "@typescript-eslint/parser": "^8.18.1", "@vue/eslint-config-prettier": "^10.1.0", "cross-env": "^10.0.0", - "electron": "^32.2.7", + "electron": "^38.0.0", "electron-builder": "^25.1.8", - "electron-chromedriver": "^32.2.6", + "electron-chromedriver": "^38.0.0", "electron-vite": "^4.0.0", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.0", @@ -2852,9 +2852,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.34.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", - "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", + "version": "9.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", + "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", "dev": true, "license": "MIT", "engines": { @@ -6645,14 +6645,14 @@ } }, "node_modules/electron": { - "version": "32.3.3", - "resolved": "https://registry.npmjs.org/electron/-/electron-32.3.3.tgz", - "integrity": "sha512-7FT8tDg+MueAw8dBn5LJqDvlM4cZkKJhXfgB3w7P5gvSoUQVAY6LIQcXJxgL+vw2rIRY/b9ak7ZBFbCMF2Bk4w==", + "version": "38.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-38.0.0.tgz", + "integrity": "sha512-egljptiPJqbL/oamFCEY+g3RNeONWTVxZSGeyLqzK8xq106JhzuxnhJZ3sxt4DzJFaofbGyGJA37Oe9d+gVzYw==", "hasInstallScript": true, "license": "MIT", "dependencies": { "@electron/get": "^2.0.0", - "@types/node": "^20.9.0", + "@types/node": "^22.7.7", "extract-zip": "^2.0.1" }, "bin": { @@ -6761,9 +6761,9 @@ } }, "node_modules/electron-chromedriver": { - "version": "32.3.3", - "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-32.3.3.tgz", - "integrity": "sha512-HVyd2Fa4kRuw1GIlJFr9Uw5ut5sfsgk0NgQ05KXdpVZs95LwJch96acE4BecHO1v8ruWzHZT0QIMcQxDNCHUiw==", + "version": "38.0.0", + "resolved": "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-38.0.0.tgz", + "integrity": "sha512-8GEBO0dighodFqRrpyWon28y861jmy/wxXukU3SBQ4ohOmud2gxGvmhSxKynCENz25JgxGgj18l8lDRwsg9GSQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7001,15 +7001,6 @@ "node": ">=8.0.0" } }, - "node_modules/electron/node_modules/@types/node": { - "version": "20.19.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.13.tgz", - "integrity": "sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, "node_modules/emoji-regex": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", @@ -7425,6 +7416,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", diff --git a/resources/js/package.json b/resources/js/package.json index 779a5fbe..c84a150e 100644 --- a/resources/js/package.json +++ b/resources/js/package.json @@ -75,9 +75,9 @@ "@typescript-eslint/parser": "^8.18.1", "@vue/eslint-config-prettier": "^10.1.0", "cross-env": "^10.0.0", - "electron": "^32.2.7", + "electron": "^38.0.0", "electron-builder": "^25.1.8", - "electron-chromedriver": "^32.2.6", + "electron-chromedriver": "^38.0.0", "electron-vite": "^4.0.0", "eslint": "^9.17.0", "eslint-config-prettier": "^10.0.0", diff --git a/resources/js/yarn.lock b/resources/js/yarn.lock index 3634f789..6cdb9df8 100644 --- a/resources/js/yarn.lock +++ b/resources/js/yarn.lock @@ -1047,10 +1047,10 @@ resolved "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== -"@esbuild/linux-x64@0.25.9": +"@esbuild/darwin-arm64@0.25.9": version "0.25.9" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz" - integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz" + integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.1", "@eslint-community/eslint-utils@^4.7.0": version "4.8.0" @@ -1100,7 +1100,12 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@^9.17.0", "@eslint/js@9.34.0": +"@eslint/js@^9.17.0": + version "9.35.0" + resolved "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz" + integrity sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw== + +"@eslint/js@9.34.0": version "9.34.0" resolved "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz" integrity sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw== @@ -1273,15 +1278,10 @@ resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@rollup/rollup-linux-x64-gnu@4.50.0": - version "4.50.0" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz" - integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== - -"@rollup/rollup-linux-x64-musl@4.50.0": +"@rollup/rollup-darwin-arm64@4.50.0": version "4.50.0" - resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz" - integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== + resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz" + integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== "@rushstack/eslint-patch@^1.10.4": version "1.12.0" @@ -1446,25 +1446,26 @@ resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/node@*", "@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^20.19.0 || >=22.12.0", "@types/node@^22.10.2": +"@types/node@*", "@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^20.19.0 || >=22.12.0", "@types/node@^22.10.2", "@types/node@^22.7.7": version "22.18.1" resolved "https://registry.npmjs.org/@types/node/-/node-22.18.1.tgz" integrity sha512-rzSDyhn4cYznVG+PCzGe1lwuMYJrcBS1fc3JqSa2PvtABwWo+dZ1ij5OVok3tqfpEBCBoaR4d7upFJk73HRJDw== dependencies: undici-types "~6.21.0" -"@types/node@^20.9.0": - version "20.19.13" - resolved "https://registry.npmjs.org/@types/node/-/node-20.19.13.tgz" - integrity sha512-yCAeZl7a0DxgNVteXFHt9+uyFbqXGy/ShC4BlcHkoE0AfGXYv/BUiplV72DjMYXHDBXFjhvr6DD1NiRVfB4j8g== - dependencies: - undici-types "~6.21.0" - "@types/normalize-package-data@^2.4.3": version "2.4.4" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== +"@types/plist@^3.0.1": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz" + integrity sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA== + dependencies: + "@types/node" "*" + xmlbuilder ">=11.0.1" + "@types/ps-node@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@types/ps-node/-/ps-node-0.1.3.tgz" @@ -1504,6 +1505,11 @@ "@types/node" "*" "@types/send" "*" +"@types/verror@^1.10.3": + version "1.10.11" + resolved "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz" + integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg== + "@types/yauzl@^2.9.1": version "2.10.3" resolved "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz" @@ -1764,7 +1770,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1955,6 +1961,11 @@ array-union@^2.1.0: resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz" @@ -2129,7 +2140,7 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.5.0: +buffer@^5.1.0, buffer@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2349,6 +2360,14 @@ cli-spinners@^2.5.0: resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-truncate@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz" @@ -2506,7 +2525,7 @@ core-js-compat@^3.40.0, core-js-compat@^3.43.0: dependencies: browserslist "^4.25.3" -core-util-is@~1.0.0: +core-util-is@~1.0.0, core-util-is@1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== @@ -2526,6 +2545,13 @@ crc-32@^1.2.0: resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== +crc@^3.8.0: + version "3.8.0" + resolved "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz" + integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== + dependencies: + buffer "^5.1.0" + crc32-stream@^4.0.2: version "4.0.3" resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz" @@ -2694,6 +2720,20 @@ dmg-builder@25.1.8: optionalDependencies: dmg-license "^1.0.11" +dmg-license@^1.0.11: + version "1.0.11" + resolved "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz" + integrity sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q== + dependencies: + "@types/plist" "^3.0.1" + "@types/verror" "^1.10.3" + ajv "^6.10.0" + crc "^3.8.0" + iconv-corefoundation "^1.1.7" + plist "^3.0.4" + smart-buffer "^4.0.2" + verror "^1.10.0" + dot-prop@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz" @@ -2765,10 +2805,10 @@ electron-builder@^25.1.8: simple-update-notifier "2.0.0" yargs "^17.6.2" -electron-chromedriver@^32.2.6: - version "32.3.3" - resolved "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-32.3.3.tgz" - integrity sha512-HVyd2Fa4kRuw1GIlJFr9Uw5ut5sfsgk0NgQ05KXdpVZs95LwJch96acE4BecHO1v8ruWzHZT0QIMcQxDNCHUiw== +electron-chromedriver@^38.0.0: + version "38.0.0" + resolved "https://registry.npmjs.org/electron-chromedriver/-/electron-chromedriver-38.0.0.tgz" + integrity sha512-8GEBO0dighodFqRrpyWon28y861jmy/wxXukU3SBQ4ohOmud2gxGvmhSxKynCENz25JgxGgj18l8lDRwsg9GSQ== dependencies: "@electron/get" "^2.0.1" extract-zip "^2.0.0" @@ -2856,13 +2896,13 @@ electron-window-state@^5.0.3: jsonfile "^4.0.0" mkdirp "^0.5.1" -electron@^32.2.7, "electron@>= 13.0.0", electron@>=13.0.0: - version "32.3.3" - resolved "https://registry.npmjs.org/electron/-/electron-32.3.3.tgz" - integrity sha512-7FT8tDg+MueAw8dBn5LJqDvlM4cZkKJhXfgB3w7P5gvSoUQVAY6LIQcXJxgL+vw2rIRY/b9ak7ZBFbCMF2Bk4w== +electron@^38.0.0, "electron@>= 13.0.0", electron@>=13.0.0: + version "38.0.0" + resolved "https://registry.npmjs.org/electron/-/electron-38.0.0.tgz" + integrity sha512-egljptiPJqbL/oamFCEY+g3RNeONWTVxZSGeyLqzK8xq106JhzuxnhJZ3sxt4DzJFaofbGyGJA37Oe9d+gVzYw== dependencies: "@electron/get" "^2.0.0" - "@types/node" "^20.9.0" + "@types/node" "^22.7.7" extract-zip "^2.0.1" emoji-regex@^10.3.0: @@ -3235,6 +3275,11 @@ extract-zip@^2.0.0, extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -3482,6 +3527,11 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -3849,6 +3899,14 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +iconv-corefoundation@^1.1.7: + version "1.1.7" + resolved "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz" + integrity sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ== + dependencies: + cli-truncate "^2.1.0" + node-addon-api "^1.6.3" + iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" @@ -4712,6 +4770,11 @@ node-abi@^3.45.0: dependencies: semver "^7.3.5" +node-addon-api@^1.6.3: + version "1.7.2" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz" + integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== + node-api-version@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz" @@ -5009,7 +5072,7 @@ pify@^4.0.1: resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -plist@^3.0.5, plist@^3.1.0: +plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -5658,6 +5721,15 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" @@ -5675,7 +5747,7 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -smart-buffer@^4.2.0: +smart-buffer@^4.0.2, smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== @@ -6365,6 +6437,15 @@ vary@^1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +verror@^1.10.0: + version "1.10.1" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz" + integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vite-node@3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz" @@ -6510,7 +6591,7 @@ write-file-atomic@^5.0.1: imurmurhash "^0.1.4" signal-exit "^4.0.1" -xmlbuilder@^15.1.1: +xmlbuilder@^15.1.1, xmlbuilder@>=11.0.1: version "15.1.1" resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== From cf9009f89d022d99ff7e0d22e501b1d45479f1ce Mon Sep 17 00:00:00 2001 From: gwleuverink <17123491+gwleuverink@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:50:19 +0000 Subject: [PATCH 11/11] Build plugin --- resources/js/yarn.lock | 117 ++++++----------------------------------- 1 file changed, 17 insertions(+), 100 deletions(-) diff --git a/resources/js/yarn.lock b/resources/js/yarn.lock index 6cdb9df8..2f1a21a1 100644 --- a/resources/js/yarn.lock +++ b/resources/js/yarn.lock @@ -1047,10 +1047,10 @@ resolved "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== -"@esbuild/darwin-arm64@0.25.9": +"@esbuild/linux-x64@0.25.9": version "0.25.9" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz" - integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz" + integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.1", "@eslint-community/eslint-utils@^4.7.0": version "4.8.0" @@ -1278,10 +1278,15 @@ resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@rollup/rollup-darwin-arm64@4.50.0": +"@rollup/rollup-linux-x64-gnu@4.50.0": version "4.50.0" - resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz" - integrity sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg== + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz" + integrity sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA== + +"@rollup/rollup-linux-x64-musl@4.50.0": + version "4.50.0" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz" + integrity sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw== "@rushstack/eslint-patch@^1.10.4": version "1.12.0" @@ -1458,14 +1463,6 @@ resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== -"@types/plist@^3.0.1": - version "3.0.5" - resolved "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz" - integrity sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA== - dependencies: - "@types/node" "*" - xmlbuilder ">=11.0.1" - "@types/ps-node@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@types/ps-node/-/ps-node-0.1.3.tgz" @@ -1505,11 +1502,6 @@ "@types/node" "*" "@types/send" "*" -"@types/verror@^1.10.3": - version "1.10.11" - resolved "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz" - integrity sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg== - "@types/yauzl@^2.9.1": version "2.10.3" resolved "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz" @@ -1770,7 +1762,7 @@ ajv-keywords@^3.4.1: resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: +ajv@^6.12.0, ajv@^6.12.4, ajv@^6.9.1: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1961,11 +1953,6 @@ array-union@^2.1.0: resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz" @@ -2140,7 +2127,7 @@ buffer-from@^1.0.0: resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer@^5.1.0, buffer@^5.5.0: +buffer@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2360,14 +2347,6 @@ cli-spinners@^2.5.0: resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - cli-truncate@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz" @@ -2525,7 +2504,7 @@ core-js-compat@^3.40.0, core-js-compat@^3.43.0: dependencies: browserslist "^4.25.3" -core-util-is@~1.0.0, core-util-is@1.0.2: +core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== @@ -2545,13 +2524,6 @@ crc-32@^1.2.0: resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== -crc@^3.8.0: - version "3.8.0" - resolved "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz" - integrity sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ== - dependencies: - buffer "^5.1.0" - crc32-stream@^4.0.2: version "4.0.3" resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz" @@ -2720,20 +2692,6 @@ dmg-builder@25.1.8: optionalDependencies: dmg-license "^1.0.11" -dmg-license@^1.0.11: - version "1.0.11" - resolved "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz" - integrity sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q== - dependencies: - "@types/plist" "^3.0.1" - "@types/verror" "^1.10.3" - ajv "^6.10.0" - crc "^3.8.0" - iconv-corefoundation "^1.1.7" - plist "^3.0.4" - smart-buffer "^4.0.2" - verror "^1.10.0" - dot-prop@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz" @@ -3275,11 +3233,6 @@ extract-zip@^2.0.0, extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -3527,11 +3480,6 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -3899,14 +3847,6 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-corefoundation@^1.1.7: - version "1.1.7" - resolved "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz" - integrity sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ== - dependencies: - cli-truncate "^2.1.0" - node-addon-api "^1.6.3" - iconv-lite@^0.6.2, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" @@ -4770,11 +4710,6 @@ node-abi@^3.45.0: dependencies: semver "^7.3.5" -node-addon-api@^1.6.3: - version "1.7.2" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz" - integrity sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg== - node-api-version@^0.2.0: version "0.2.1" resolved "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz" @@ -5072,7 +5007,7 @@ pify@^4.0.1: resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -plist@^3.0.4, plist@^3.0.5, plist@^3.1.0: +plist@^3.0.5, plist@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz" integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== @@ -5721,15 +5656,6 @@ slash@^3.0.0: resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" @@ -5747,7 +5673,7 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -smart-buffer@^4.0.2, smart-buffer@^4.2.0: +smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== @@ -6437,15 +6363,6 @@ vary@^1.1.2: resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -verror@^1.10.0: - version "1.10.1" - resolved "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz" - integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - vite-node@3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz" @@ -6591,7 +6508,7 @@ write-file-atomic@^5.0.1: imurmurhash "^0.1.4" signal-exit "^4.0.1" -xmlbuilder@^15.1.1, xmlbuilder@>=11.0.1: +xmlbuilder@^15.1.1: version "15.1.1" resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==