diff --git a/apps/app/src/components/player/menus.tsx b/apps/app/src/components/player/menus.tsx index 29357054..8e3fe98b 100644 --- a/apps/app/src/components/player/menus.tsx +++ b/apps/app/src/components/player/menus.tsx @@ -7,6 +7,7 @@ import { } from "@vidstack/react"; import { Menu } from "obsidian"; import { MoreIcon, SubtitlesIcon } from "@/components/icon"; +import { showAtButton } from "@/lib/menu"; import { useApp, useIsEmbed, @@ -38,7 +39,7 @@ export function Captions() { item.setTitle(label).setChecked(selected).onClick(select); }); }); - menu.showAtMouseEvent(evt.nativeEvent); + showAtButton(evt.nativeEvent, menu); evt.nativeEvent.stopImmediatePropagation(); }} aria-label="Select Caption" @@ -79,7 +80,7 @@ export function MoreOptions() { }, isEmbed ? "player-menu-embed" : "player-menu-view", ); - menu.showAtMouseEvent(evt.nativeEvent); + showAtButton(evt.nativeEvent, menu); evt.nativeEvent.stopImmediatePropagation(); }} aria-label="More options" diff --git a/apps/app/src/lib/menu.ts b/apps/app/src/lib/menu.ts new file mode 100644 index 00000000..92b2e822 --- /dev/null +++ b/apps/app/src/lib/menu.ts @@ -0,0 +1,24 @@ +import type { Menu } from "obsidian"; + +declare module "obsidian" { + interface MenuItem { + setSubmenu(): Menu; + } + interface Menu { + addSections(sections: string[]): void; + setParentElement(parent: HTMLElement): this; + } +} + +export function showAtButton(evt: Event, menu: Menu) { + const target = evt.target; + if (!(target instanceof HTMLElement)) return; + const rect = target.getBoundingClientRect(); + return menu.setParentElement(target).showAtPosition({ + x: rect.x, + y: rect.bottom, + width: rect.width, + overlap: true, + left: true, + }); +} diff --git a/apps/app/src/login/modal.ts b/apps/app/src/login/modal.ts index bdbbe23c..5e839d61 100644 --- a/apps/app/src/login/modal.ts +++ b/apps/app/src/login/modal.ts @@ -8,6 +8,7 @@ import { DropdownComponent, } from "obsidian"; import "./modal.global.less"; +import { showAtButton } from "@/lib/menu"; import { getPartition } from "@/lib/remote-player/const"; import { webHostDisplayNameNoGeneric, webHostUrl } from "@/web/match-webpage"; import type { SupportedWebHostNoGeneric } from "@/web/match-webpage"; @@ -93,8 +94,7 @@ export class LoginModal extends Modal { .onClick((e) => { const menu = new Menu(); this.onMoreOptions(menu); - const bounding = (e.target as HTMLElement).getBoundingClientRect(); - menu.showAtPosition({ x: bounding.right, y: bounding.bottom }); + showAtButton(e, menu); }); buildWelcome() { diff --git a/apps/app/src/media-view/menu/index.ts b/apps/app/src/media-view/menu/index.ts index 625da1b8..638dcaef 100644 --- a/apps/app/src/media-view/menu/index.ts +++ b/apps/app/src/media-view/menu/index.ts @@ -56,9 +56,6 @@ declare module "obsidian" { leaf?: WorkspaceLeaf, ): void; } - interface MenuItem { - setSubmenu(): Menu; - } } export default function registerMediaMenu(this: MxPlugin) {