base.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. import { Channel, invoke, Resource } from '../core'
  5. import { CheckMenuItemOptions } from './checkMenuItem'
  6. import { IconMenuItemOptions } from './iconMenuItem'
  7. import { MenuItemOptions } from './menuItem'
  8. import { PredefinedMenuItemOptions } from './predefinedMenuItem'
  9. import { SubmenuOptions } from './submenu'
  10. export type ItemKind =
  11. | 'MenuItem'
  12. | 'Predefined'
  13. | 'Check'
  14. | 'Icon'
  15. | 'Submenu'
  16. | 'Menu'
  17. function injectChannel(
  18. i:
  19. | MenuItemOptions
  20. | SubmenuOptions
  21. | IconMenuItemOptions
  22. | PredefinedMenuItemOptions
  23. | CheckMenuItemOptions
  24. ):
  25. | MenuItemOptions
  26. | SubmenuOptions
  27. | IconMenuItemOptions
  28. | PredefinedMenuItemOptions
  29. | (CheckMenuItemOptions & { handler?: Channel<string> }) {
  30. if ('items' in i) {
  31. i.items = i.items?.map((item) =>
  32. 'rid' in item ? item : injectChannel(item)
  33. )
  34. } else if ('action' in i && i.action) {
  35. const handler = new Channel<string>()
  36. handler.onmessage = i.action
  37. delete i.action
  38. return { ...i, handler }
  39. }
  40. return i
  41. }
  42. export async function newMenu(
  43. kind: ItemKind,
  44. opts?: unknown
  45. ): Promise<[number, string]> {
  46. const handler = new Channel<string>()
  47. let items: null | Array<
  48. | [number, string]
  49. | MenuItemOptions
  50. | SubmenuOptions
  51. | IconMenuItemOptions
  52. | PredefinedMenuItemOptions
  53. | CheckMenuItemOptions
  54. > = null
  55. if (opts && typeof opts === 'object') {
  56. if ('action' in opts && opts.action) {
  57. handler.onmessage = opts.action as () => void
  58. delete opts.action
  59. }
  60. if ('items' in opts && opts.items) {
  61. items = (
  62. opts.items as Array<
  63. | { rid: number; kind: string }
  64. | MenuItemOptions
  65. | SubmenuOptions
  66. | IconMenuItemOptions
  67. | PredefinedMenuItemOptions
  68. | CheckMenuItemOptions
  69. >
  70. ).map((i) => {
  71. if ('rid' in i) {
  72. return [i.rid, i.kind]
  73. }
  74. return injectChannel(i)
  75. })
  76. }
  77. }
  78. return invoke('plugin:menu|new', {
  79. kind,
  80. options: opts ? { ...opts, items } : undefined,
  81. handler
  82. })
  83. }
  84. export class MenuItemBase extends Resource {
  85. /** @ignore */
  86. readonly #id: string
  87. /** @ignore */
  88. readonly #kind: ItemKind
  89. /** The id of this item. */
  90. get id(): string {
  91. return this.#id
  92. }
  93. /** @ignore */
  94. get kind(): string {
  95. return this.#kind
  96. }
  97. /** @ignore */
  98. protected constructor(rid: number, id: string, kind: ItemKind) {
  99. super(rid)
  100. this.#id = id
  101. this.#kind = kind
  102. }
  103. }