/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectionToken } from "@ogre-tools/injectable"; import type { BrowserWindow, KeyboardEvent, MenuItemConstructorOptions, MenuItem as ElectronMenuItem } from "electron"; import type { SetOptional } from "type-fest"; import type { ChildOfParentComposite, ParentOfChildComposite } from "../../../../common/utils/composite/interfaces"; import type { MaybeShowable } from "../../../../common/utils/composable-responsibilities/showable/showable"; import type { Discriminable } from "../../../../common/utils/composable-responsibilities/discriminable/discriminable"; import type { Orderable } from "../../../../common/utils/composable-responsibilities/orderable/orderable"; export interface MayHaveKeyboardShortcut { keyboardShortcut?: string; } export interface ElectronClickable { // TODO: This leaky abstraction is exposed in Extension API, therefore cannot be updated onClick: (menuItem: ElectronMenuItem, browserWindow: (BrowserWindow) | (undefined), event: KeyboardEvent) => void; } export interface Labeled { label: string; } export interface MaybeLabeled extends SetOptional {} type ApplicationMenuItemType = // Note: "kind" is being used for Discriminated unions of TypeScript to achieve type narrowing. // See: https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions & Discriminable & ParentOfChildComposite & ChildOfParentComposite & MaybeShowable & Orderable; export type TopLevelMenu = & ApplicationMenuItemType<"top-level-menu"> & { parentId: "root" } & Labeled & MayHaveElectronRole; interface MayHaveElectronRole { role?: ElectronRoles; } type ElectronRoles = Exclude; export type SubMenu = & ApplicationMenuItemType<"sub-menu"> & Labeled & ChildOfParentComposite; export type ClickableMenuItem = & ApplicationMenuItemType<"clickable-menu-item"> & MenuItem & Labeled & ElectronClickable; export type OsActionMenuItem = & ApplicationMenuItemType<"os-action-menu-item"> & MenuItem & MaybeLabeled & TriggersElectronAction; type MenuItem = & ChildOfParentComposite & MayHaveKeyboardShortcut; interface TriggersElectronAction { actionName: ElectronRoles; } // Todo: SeparatorMenuItem export type Separator = & ApplicationMenuItemType<"separator"> & ChildOfParentComposite; export type ApplicationMenuItemTypes = | TopLevelMenu | SubMenu | OsActionMenuItem | ClickableMenuItem | Separator ; const applicationMenuItemInjectionToken = getInjectionToken({ id: "application-menu-item-injection-token", }); export default applicationMenuItemInjectionToken;