Files
tauri/tooling/api/src/menu/base.ts
Amr Bashir 77b9a508a4 feat(api): add Image class (#9042)
* feat(api): add `Image` class

* clippy

* license headers

* small cleanup

* fixes

* code review

* readd from_png_bytes and from_ico_bytes

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
2024-03-03 04:31:08 +02:00

124 lines
2.9 KiB
TypeScript

// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { Channel, invoke, Resource } from '../core'
import { transformImage } from '../image'
import { CheckMenuItemOptions } from './checkMenuItem'
import { IconMenuItemOptions } from './iconMenuItem'
import { MenuItemOptions } from './menuItem'
import { PredefinedMenuItemOptions } from './predefinedMenuItem'
import { SubmenuOptions } from './submenu'
export type ItemKind =
| 'MenuItem'
| 'Predefined'
| 'Check'
| 'Icon'
| 'Submenu'
| 'Menu'
function injectChannel(
i:
| MenuItemOptions
| SubmenuOptions
| IconMenuItemOptions
| PredefinedMenuItemOptions
| CheckMenuItemOptions
):
| MenuItemOptions
| SubmenuOptions
| IconMenuItemOptions
| PredefinedMenuItemOptions
| (CheckMenuItemOptions & { handler?: Channel<string> }) {
if ('items' in i) {
i.items = i.items?.map((item) =>
'rid' in item ? item : injectChannel(item)
)
} else if ('action' in i && i.action) {
const handler = new Channel<string>()
handler.onmessage = i.action
delete i.action
return { ...i, handler }
}
return i
}
export async function newMenu(
kind: ItemKind,
opts?: unknown
): Promise<[number, string]> {
const handler = new Channel<string>()
let items: null | Array<
| [number, string]
| MenuItemOptions
| SubmenuOptions
| IconMenuItemOptions
| PredefinedMenuItemOptions
| CheckMenuItemOptions
> = null
if (opts && typeof opts === 'object') {
if ('action' in opts && opts.action) {
handler.onmessage = opts.action as () => void
delete opts.action
}
if ('items' in opts && opts.items) {
items = (
opts.items as Array<
| { rid: number; kind: string }
| MenuItemOptions
| SubmenuOptions
| IconMenuItemOptions
| PredefinedMenuItemOptions
| CheckMenuItemOptions
>
).map((i) => {
if ('rid' in i) {
return [i.rid, i.kind]
}
if ('item' in i && typeof i.item === 'object' && i.item.About?.icon) {
i.item.About.icon = transformImage(i.item.About.icon)
}
if ('icon' in i && i.icon) {
i.icon = transformImage(i.icon)
}
return injectChannel(i)
})
}
}
return invoke('plugin:menu|new', {
kind,
options: opts ? { ...opts, items } : undefined,
handler
})
}
export class MenuItemBase extends Resource {
/** @ignore */
readonly #id: string
/** @ignore */
readonly #kind: ItemKind
/** The id of this item. */
get id(): string {
return this.#id
}
/** @ignore */
get kind(): string {
return this.#kind
}
/** @ignore */
protected constructor(rid: number, id: string, kind: ItemKind) {
super(rid)
this.#id = id
this.#kind = kind
}
}