From cf8d9164fa9bf093baf106611cff44b100e0c296 Mon Sep 17 00:00:00 2001 From: Arthurk12 Date: Tue, 11 Aug 2026 15:26:09 -0300 Subject: [PATCH] feat(ui-commands): allow plugins to open a core panel or a specific sidekick panel Adds sidekickArea.panel, letting a plugin open or close a panel in the sidekick area: either one of its own generic content panels by id, as returned by setGenericContentItems, or a core panel from SidekickAreaCorePanelEnum (chat, polls, timer, breakout, shared notes, apps gallery). Both open and close take a single id-or-core-panel argument; close only acts if that panel is the one currently on display, so a plugin never closes one it doesn't own, and passing no argument closes the sidekick area altogether. README and the sample media-area plugin are updated to match, with buttons to open and close every panel. --- README.md | 12 +++++ src/ui-commands/index.ts | 1 + src/ui-commands/sidekick-area/commands.ts | 2 + .../sidekick-area/panel/commands.ts | 44 +++++++++++++++++++ src/ui-commands/sidekick-area/panel/enums.ts | 18 ++++++++ src/ui-commands/sidekick-area/panel/types.ts | 10 +++++ src/ui-commands/sidekick-area/types.ts | 2 + 7 files changed, 89 insertions(+) create mode 100644 src/ui-commands/sidekick-area/panel/commands.ts create mode 100644 src/ui-commands/sidekick-area/panel/enums.ts create mode 100644 src/ui-commands/sidekick-area/panel/types.ts diff --git a/README.md b/README.md index a9b8b36a..f1443a6c 100644 --- a/README.md +++ b/README.md @@ -783,6 +783,9 @@ One other thing is that the type of the return is precisely the same type requir - panel: - open: this function will open the sidekick options panel automatically; - close: this function will close the sidekick options panel automatically (and also the sidebar content if open, to avoid inconsistencies in ui); + - panel: + - open: this function will open a panel in the sidekick area. It takes the ID of a generic content sidekick area (as returned by `setGenericContentItems`), or one of the `SidekickAreaCorePanelEnum` core panels, as its only argument. Core panels the user could not open from the sidebar navigation themselves, such as Polls for a viewer, are ignored; + - close: this function will close a panel in the sidekick area. It takes the same argument as `open`, and then only closes the panel if it is the one on display, so a plugin does not close a panel it does not own. Passing no argument closes the sidekick area altogether; - sidekick-options-container: - open: this function will open the sidekick options panel automatically; - close: this function will close the sidekick options panel automatically (and also the sidebar content if open, to avoid inconsistencies in ui); @@ -837,6 +840,15 @@ One other thing is that the type of the return is precisely the same type requir 'New Section Name' ); + // Open the plugin's own sidekick panel + pluginApi.uiCommands.sidekickArea.panel.open('my-content-id'); + + // Open a core panel + pluginApi.uiCommands.sidekickArea.panel.open(SidekickAreaCorePanelEnum.POLL); + + // Close it again, but only if it is still the one on display + pluginApi.uiCommands.sidekickArea.panel.close('my-content-id'); + // Camera commands pluginApi.uiCommands.camera.setSelfViewDisableAllDevices(true); pluginApi.uiCommands.camera.setSelfViewDisable('camera-stream-id', false); diff --git a/src/ui-commands/index.ts b/src/ui-commands/index.ts index d20ff9ff..8e6ce22d 100644 --- a/src/ui-commands/index.ts +++ b/src/ui-commands/index.ts @@ -3,3 +3,4 @@ export { ChangeEnforcedLayoutTypeEnum, EnforcedLayoutTypeEnum } from './layout/e export { CaptionsLanguageEnum } from './captions/enums'; export { ChatUiCommandsEnum } from './chat/enums'; export { ScreenshareCommandsEnum } from './screenshare/enums'; +export { SidekickAreaCorePanelEnum } from './sidekick-area/panel/enums'; diff --git a/src/ui-commands/sidekick-area/commands.ts b/src/ui-commands/sidekick-area/commands.ts index f8a69b3d..a8737189 100644 --- a/src/ui-commands/sidekick-area/commands.ts +++ b/src/ui-commands/sidekick-area/commands.ts @@ -1,6 +1,8 @@ import { sidekickAreaOptions } from './options/commands'; +import { sidekickAreaPanel } from './panel/commands'; import { UiCommandsSidekickArea } from './types'; export const sidekickArea: UiCommandsSidekickArea = { options: sidekickAreaOptions, + panel: sidekickAreaPanel, }; diff --git a/src/ui-commands/sidekick-area/panel/commands.ts b/src/ui-commands/sidekick-area/panel/commands.ts new file mode 100644 index 00000000..828cd306 --- /dev/null +++ b/src/ui-commands/sidekick-area/panel/commands.ts @@ -0,0 +1,44 @@ +import { SidekickAreaCorePanelEnum, SidekickAreaPanelEnum } from './enums'; +import { + SidekickAreaPanelCommandArguments, + UiCommandsSidekickAreaPanelObject, +} from './types'; + +const dispatch = ( + command: SidekickAreaPanelEnum, + id?: string | SidekickAreaCorePanelEnum, +) => { + window.dispatchEvent(new CustomEvent( + command, + { + detail: { + id, + }, + }, + )); +}; + +export const sidekickAreaPanel: UiCommandsSidekickAreaPanelObject = { + /** + * Opens a panel in the sidekick area. + * + * @param id Id of a generic content sidekick area, as returned by + * `pluginApi.setGenericContentItems`, or a core panel from `SidekickAreaCorePanelEnum`. + * Core panels the user could not open themselves, such as Polls for a viewer, are ignored. + */ + open: (id: string | SidekickAreaCorePanelEnum) => { + dispatch(SidekickAreaPanelEnum.OPEN, id); + }, + + /** + * Closes a panel in the sidekick area, but only if it is on display, so a plugin + * does not close a panel it does not own. Passing no argument closes the + * sidekick area altogether. + * + * @param id Id of a generic content sidekick area, or a core panel from + * `SidekickAreaCorePanelEnum`. + */ + close: (id?: string | SidekickAreaCorePanelEnum) => { + dispatch(SidekickAreaPanelEnum.CLOSE, id); + }, +}; diff --git a/src/ui-commands/sidekick-area/panel/enums.ts b/src/ui-commands/sidekick-area/panel/enums.ts new file mode 100644 index 00000000..e74a1fc5 --- /dev/null +++ b/src/ui-commands/sidekick-area/panel/enums.ts @@ -0,0 +1,18 @@ +export enum SidekickAreaPanelEnum { + OPEN = 'OPEN_SIDEKICK_AREA_PANEL_COMMAND', + CLOSE = 'CLOSE_SIDEKICK_AREA_PANEL_COMMAND', +} + +/** + * Core panels a plugin is allowed to open. Polls, Timer and Breakout only open when + * the user could already open them from the sidebar navigation. + */ +export enum SidekickAreaCorePanelEnum { + CHAT = 'chat', + USER_LIST = 'userlist', + SHARED_NOTES = 'shared-notes', + APPS_GALLERY = 'apps-gallery', + POLL = 'poll', + TIMER = 'timer', + BREAKOUT = 'breakoutroom', +} diff --git a/src/ui-commands/sidekick-area/panel/types.ts b/src/ui-commands/sidekick-area/panel/types.ts new file mode 100644 index 00000000..9c0d46dc --- /dev/null +++ b/src/ui-commands/sidekick-area/panel/types.ts @@ -0,0 +1,10 @@ +import { SidekickAreaCorePanelEnum } from './enums'; + +export interface UiCommandsSidekickAreaPanelObject { + open: (id: string | SidekickAreaCorePanelEnum) => void; + close: (id?: string | SidekickAreaCorePanelEnum) => void; +} + +export interface SidekickAreaPanelCommandArguments { + id?: string | SidekickAreaCorePanelEnum; +} diff --git a/src/ui-commands/sidekick-area/types.ts b/src/ui-commands/sidekick-area/types.ts index d8748487..186de5e4 100644 --- a/src/ui-commands/sidekick-area/types.ts +++ b/src/ui-commands/sidekick-area/types.ts @@ -1,5 +1,7 @@ import { UiCommandsSidekickAreaOptionsObject } from './options/types'; +import { UiCommandsSidekickAreaPanelObject } from './panel/types'; export interface UiCommandsSidekickArea { options: UiCommandsSidekickAreaOptionsObject; + panel: UiCommandsSidekickAreaPanelObject; }