From 4b9954a57e89d6f927d5a5e6e47b4edb0177606d Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Fri, 26 Jul 2024 10:49:52 -0300 Subject: [PATCH 1/5] [video-control] - Added a display function in which will decide wheather to show the extensible area or not and also included arguments in the onclick function. --- .../src/queries.ts | 9 +++++++++ .../component.tsx | 19 +++++++++++++++---- .../types.ts | 12 +++++++++++- .../user-camera-dropdown-item/component.ts | 16 ++++++++++++++-- .../user-camera-dropdown-item/types.ts | 18 +++++++++++++++++- 5 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 samples/sample-user-camera-dropdown-plugin/src/queries.ts diff --git a/samples/sample-user-camera-dropdown-plugin/src/queries.ts b/samples/sample-user-camera-dropdown-plugin/src/queries.ts new file mode 100644 index 00000000..de6bfa30 --- /dev/null +++ b/samples/sample-user-camera-dropdown-plugin/src/queries.ts @@ -0,0 +1,9 @@ +export const VIDEO_STREAMS_SUBSCRIPTION = `subscription VideoStreams { + user_camera { + streamId + user { + name + userId + } + } +}`; diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx index 6d07ec73..2a76b0c6 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx @@ -4,24 +4,35 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, pluginLogger, UserCameraDropdownOption, UserCameraDropdownSeparator, } from 'bigbluebutton-html-plugin-sdk'; -import { SampleUserCameraDropdownPluginProps } from './types'; +import { SampleUserCameraDropdownPluginProps, VideoStreamsSubscriptionResultType } from './types'; +import { VIDEO_STREAMS_SUBSCRIPTION } from '../queries'; function SampleUserCameraDropdownPlugin({ pluginUuid: uuid }: SampleUserCameraDropdownPluginProps): React.ReactElement { + BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); + const { data: videoStreams } = pluginApi.useCustomSubscription< + VideoStreamsSubscriptionResultType + >(VIDEO_STREAMS_SUBSCRIPTION); + useEffect(() => { + const randomElement = videoStreams?.user_camera[ + Math.floor(Math.random() * (videoStreams?.user_camera.length ?? 0)) + ]; + pluginApi.setUserCameraDropdownItems([ new UserCameraDropdownSeparator(), new UserCameraDropdownOption({ label: 'This will log on the console', icon: 'user', - onClick: () => { - pluginLogger.info('Alert sent from plugin'); + displayFunction: ({ userId }) => randomElement?.user.userId === userId, + onClick: ({ userId }) => { + pluginLogger.info(`Alert sent from plugin, see userId: ${userId}`); }, }), ]); - }, []); + }, [videoStreams]); return null; } diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/types.ts b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/types.ts index bf7f66ea..fb28114e 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/types.ts +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/types.ts @@ -3,4 +3,14 @@ interface SampleUserCameraDropdownPluginProps { pluginUuid: string, } -export { SampleUserCameraDropdownPluginProps }; +interface VideoStreamsSubscriptionResultType { + user_camera?: { + streamId: string + user: { + name: string + userId: string + }; + }[]; +} + +export { SampleUserCameraDropdownPluginProps, VideoStreamsSubscriptionResultType }; diff --git a/src/extensible-areas/user-camera-dropdown-item/component.ts b/src/extensible-areas/user-camera-dropdown-item/component.ts index 27012d6b..b1b44fda 100644 --- a/src/extensible-areas/user-camera-dropdown-item/component.ts +++ b/src/extensible-areas/user-camera-dropdown-item/component.ts @@ -1,6 +1,9 @@ import { UserCameraDropdownItemType } from './enums'; import { + OnclickFunctionCallbackArguments, + UserCameraDropdownCallbackFunctionsArguments, UserCameraDropdownInterface, UserCameraDropdownOptionProps, + UserCameraDropdownSeparatorProps, } from './types'; // UserCameraDropdown Extensible Area @@ -14,7 +17,9 @@ export class UserCameraDropdownOption implements UserCameraDropdownInterface { icon: string; - onClick: () => void; + onClick: (args: OnclickFunctionCallbackArguments) => void; + + displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; /** * Returns object to be used in the setter for User Camera Dropdown. In this case @@ -28,7 +33,9 @@ export class UserCameraDropdownOption implements UserCameraDropdownInterface { */ constructor({ label = '', icon = '', onClick = () => {}, + displayFunction = () => true, }: UserCameraDropdownOptionProps) { + this.displayFunction = displayFunction; this.label = label; this.icon = icon; this.onClick = onClick; @@ -45,13 +52,18 @@ export class UserCameraDropdownSeparator implements UserCameraDropdownInterface type: UserCameraDropdownItemType; + displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; + /** * Returns object to be used in the setter for User Camera Dropdown. In this case * a separator. * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5) */ - constructor() { + constructor({ + displayFunction, + }: UserCameraDropdownSeparatorProps = { displayFunction: () => true }) { + this.displayFunction = displayFunction; this.type = UserCameraDropdownItemType.SEPARATOR; } diff --git a/src/extensible-areas/user-camera-dropdown-item/types.ts b/src/extensible-areas/user-camera-dropdown-item/types.ts index d08e6398..a69a6dfe 100644 --- a/src/extensible-areas/user-camera-dropdown-item/types.ts +++ b/src/extensible-areas/user-camera-dropdown-item/types.ts @@ -1,5 +1,15 @@ import { PluginProvidedUiItemDescriptor } from '../base'; +export interface UserCameraDropdownCallbackFunctionsArguments { + streamId: string; + userId: string; +} + +export interface OnclickFunctionCallbackArguments + extends UserCameraDropdownCallbackFunctionsArguments{ + browserClickEvent: React.MouseEvent; +} + /** * User Camera Dropdown Item - The general user camera dropdown extensible area item * @@ -7,10 +17,16 @@ import { PluginProvidedUiItemDescriptor } from '../base'; * This dropdown is located on the bottom left corner of the user webcam area */ export interface UserCameraDropdownInterface extends PluginProvidedUiItemDescriptor{ + displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; +} + +export interface UserCameraDropdownSeparatorProps { + displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; } export interface UserCameraDropdownOptionProps { label: string; icon: string; - onClick: () => void; + onClick: (args: OnclickFunctionCallbackArguments) => void; + displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; } From 6a65ccfbedbc27f3be12ad18592a7ab520b36029 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Mon, 29 Jul 2024 11:17:15 -0300 Subject: [PATCH 2/5] [video-control] - created useUserCameraDomElements as a dom element manipulation hook --- README.md | 1 + .../component.tsx | 6 ++ src/core/api/BbbPluginSdk.ts | 4 ++ src/core/api/types.ts | 10 +++ src/dom-element-manipulation/enums.ts | 1 + src/dom-element-manipulation/type.ts | 4 +- .../user-camera/hooks.ts | 62 +++++++++++++++++++ .../user-camera/types.ts | 12 ++++ 8 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/dom-element-manipulation/user-camera/hooks.ts create mode 100644 src/dom-element-manipulation/user-camera/types.ts diff --git a/README.md b/README.md index b9a73928..aa83a8a4 100644 --- a/README.md +++ b/README.md @@ -262,6 +262,7 @@ So the idea is that we have a `uiCommands` object and at a point, there will be ### Dom Element Manipulation - `useChatMessageDomElements` hook: This hook will return the dom element of a chat message reactively, so one can modify whatever is inside, such as text, css, js, etc.; +- `useUserCameraDomElements` hook: This hook will return the dom element of each of the user's webcam corresponding to the streamIds passed reactively, so one can modify whatever is inside, such as text, css, js, etc., and also can get the video element within it; ### Learning Analytics Dashboard integration diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx index 2a76b0c6..9d0fce83 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx @@ -16,6 +16,12 @@ React.ReactElement { VideoStreamsSubscriptionResultType >(VIDEO_STREAMS_SUBSCRIPTION); + const userCamera = pluginApi.useUserCameraDomElements( + videoStreams?.user_camera.map((vs) => vs.streamId), + ); + + pluginLogger.info(`logging the domElements manipulation for userCamera: (${userCamera}) for streams (${videoStreams})`); + useEffect(() => { const randomElement = videoStreams?.user_camera[ Math.floor(Math.random() * (videoStreams?.user_camera.length ?? 0)) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 675cd36d..9b92fe16 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -37,6 +37,7 @@ import { usePluginSettings } from '../../data-consumption/domain/settings'; import { UseLoadedChatMessagesFunction } from '../../data-consumption/domain/chat/loaded-chat-messages/types'; import { useLoadedChatMessages } from '../../data-consumption/domain/chat/loaded-chat-messages/hooks'; import { useChatMessageDomElements } from '../../dom-element-manipulation/chat/message/hooks'; +import { useUserCameraDomElements } from '../../dom-element-manipulation/user-camera/hooks'; import { UseTalkingIndicatorFunction } from '../../data-consumption/domain/user-voice/talking-indicator/types'; import { useTalkingIndicator } from '../../data-consumption/domain/user-voice/talking-indicator/hooks'; import { useUiData } from '../../ui-data-hooks/hooks'; @@ -86,6 +87,9 @@ export abstract class BbbPluginSdk { pluginApi.useChatMessageDomElements = ( messageIds: string[], ) => useChatMessageDomElements(messageIds); + pluginApi.useUserCameraDomElements = ( + streamIds: string[], + ) => useUserCameraDomElements(streamIds); pluginApi.uiCommands = uiCommands; pluginApi.serverCommands = serverCommands; pluginApi.useUiData = useUiData; diff --git a/src/core/api/types.ts b/src/core/api/types.ts index bbe83962..db84899c 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -28,6 +28,7 @@ import { UseUiDataFunction } from '../../ui-data-hooks/types'; import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-core/types'; import { ServerCommands } from '../../server-commands/types'; import { SendGenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; +import { UseUserCameraDomElementsFunction } from '../../dom-element-manipulation/user-camera/types'; // Setter Functions for the API export type SetPresentationToolbarItems = (presentationToolbarItem: @@ -211,6 +212,15 @@ export interface PluginApi { * */ useChatMessageDomElements?: UseChatMessageDomElementsFunction; + /** + * Returns an array with the DOM elements for the webcams corresponding to each streamId passed. + * + * @param streamIds - Ids of the user-camera streams one wants to retrieve in the form of an array + * @returns The array of an object with DOM elements (in this case, div) and the id + * of the stream + * + */ + useUserCameraDomElements?: UseUserCameraDomElementsFunction; // --- Auxiliary functions --- getSessionToken?: GetSessionTokenFunction; getJoinUrl?: GetJoinUrlFunction; diff --git a/src/dom-element-manipulation/enums.ts b/src/dom-element-manipulation/enums.ts index 17130d8c..cdad1170 100644 --- a/src/dom-element-manipulation/enums.ts +++ b/src/dom-element-manipulation/enums.ts @@ -1,3 +1,4 @@ export enum DomElementManipulationHooks { CHAT_MESSAGE = 'CHAT_MESSAGE', + USER_CAMERA = 'USER_CAMERA', } diff --git a/src/dom-element-manipulation/type.ts b/src/dom-element-manipulation/type.ts index 288af264..7bb37bb4 100644 --- a/src/dom-element-manipulation/type.ts +++ b/src/dom-element-manipulation/type.ts @@ -1,3 +1,5 @@ import { ChatMessageDomElementsArguments } from './chat/message/types'; +import { UserCameraDomElementsArguments } from './user-camera/types'; -export type DomElementManipulationArguments = ChatMessageDomElementsArguments; +export type DomElementManipulationArguments = ChatMessageDomElementsArguments + | UserCameraDomElementsArguments; diff --git a/src/dom-element-manipulation/user-camera/hooks.ts b/src/dom-element-manipulation/user-camera/hooks.ts new file mode 100644 index 00000000..4eb8cc1a --- /dev/null +++ b/src/dom-element-manipulation/user-camera/hooks.ts @@ -0,0 +1,62 @@ +import { useEffect, useState } from 'react'; +import { DomElementManipulationHooks } from '../enums'; +import { HookEvents } from '../../core/enum'; +import { + HookEventWrapper, SubscribedEventDetails, UnsubscribedEventDetails, UpdatedEventDetails, +} from '../../core/types'; +import { UserCameraDomElementsArguments, UpdatedEventDetailsForUserCameraDomElement } from './types'; +import { sortedStringify } from '../../data-consumption/utils'; + +export const useUserCameraDomElements = (streamIds: string[]) => { + const [domElement, setDomElement] = useState(); + const [streamIdsState, setStreamIdsState] = useState(streamIds); + + const handleCustomSubscriptionUpdateEvent: EventListener = ( + (event: HookEventWrapper< + UpdatedEventDetails>) => { + const detail = event.detail as UpdatedEventDetails< + UpdatedEventDetailsForUserCameraDomElement[]>; + if (detail.hook === DomElementManipulationHooks.USER_CAMERA + && sortedStringify( + detail.data.map((userCamera) => userCamera.streamId), + ) === sortedStringify(streamIdsState)) { + setDomElement(detail.data.map((userCamera) => userCamera.userCameraDomElement)); + } + }) as EventListener; + + useEffect(() => { + if (streamIdsState) { + window.addEventListener(HookEvents.UPDATED, handleCustomSubscriptionUpdateEvent); + return () => { + window.removeEventListener(HookEvents.UPDATED, handleCustomSubscriptionUpdateEvent); + window.dispatchEvent(new CustomEvent(HookEvents.UNSUBSCRIBED, { + detail: { + hook: DomElementManipulationHooks.USER_CAMERA, + hookArguments: { + streamIds, + } as UserCameraDomElementsArguments, + }, + })); + }; + } + return () => {}; + }, []); + useEffect(() => { + if (streamIdsState) { + window.removeEventListener(HookEvents.UPDATED, handleCustomSubscriptionUpdateEvent); + window.addEventListener(HookEvents.UPDATED, handleCustomSubscriptionUpdateEvent); + window.dispatchEvent(new CustomEvent(HookEvents.SUBSCRIBED, { + detail: { + hook: DomElementManipulationHooks.USER_CAMERA, + hookArguments: { + streamIds: streamIdsState, + } as UserCameraDomElementsArguments, + }, + })); + } + }, [streamIdsState]); + if (sortedStringify(streamIds) !== sortedStringify(streamIdsState)) { + setStreamIdsState(streamIds); + } + return domElement; +}; diff --git a/src/dom-element-manipulation/user-camera/types.ts b/src/dom-element-manipulation/user-camera/types.ts new file mode 100644 index 00000000..597321c8 --- /dev/null +++ b/src/dom-element-manipulation/user-camera/types.ts @@ -0,0 +1,12 @@ +export type UseUserCameraDomElementsFunction = ( + streamIds: string[] +) => HTMLDivElement[] | undefined; + +export interface UserCameraDomElementsArguments { + streamIds: string[]; +} + +export interface UpdatedEventDetailsForUserCameraDomElement { + streamId: string; + userCameraDomElement: HTMLDivElement; +} From a07527e9d68d398d8a29dbeb7cfe0b0d21d0cda8 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 31 Jul 2024 14:56:53 -0300 Subject: [PATCH 3/5] [video-control] - created screenshareHelperItems extensible-area --- .../component.tsx | 73 ++++++++++++++++++- src/core/api/BbbPluginSdk.ts | 1 + src/core/api/types.ts | 8 +- src/extensible-areas/base.ts | 4 +- src/extensible-areas/index.ts | 1 + .../screenshare-helper-item/component.ts | 58 +++++++++++++++ .../screenshare-helper-item/enums.ts | 14 ++++ .../screenshare-helper-item/index.ts | 9 +++ .../screenshare-helper-item/types.ts | 30 ++++++++ 9 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 src/extensible-areas/screenshare-helper-item/component.ts create mode 100644 src/extensible-areas/screenshare-helper-item/enums.ts create mode 100644 src/extensible-areas/screenshare-helper-item/index.ts create mode 100644 src/extensible-areas/screenshare-helper-item/types.ts diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx index 9d0fce83..6cf5ec7f 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx @@ -2,7 +2,13 @@ import * as React from 'react'; import { useEffect } from 'react'; import { - BbbPluginSdk, PluginApi, pluginLogger, UserCameraDropdownOption, UserCameraDropdownSeparator, + BbbPluginSdk, + PluginApi, + pluginLogger, + ScreenshareHelperItemPosition, + ScreenshareHelperButton, + UserCameraDropdownOption, + UserCameraDropdownSeparator, } from 'bigbluebutton-html-plugin-sdk'; import { SampleUserCameraDropdownPluginProps, VideoStreamsSubscriptionResultType } from './types'; import { VIDEO_STREAMS_SUBSCRIPTION } from '../queries'; @@ -22,6 +28,71 @@ React.ReactElement { pluginLogger.info(`logging the domElements manipulation for userCamera: (${userCamera}) for streams (${videoStreams})`); + useEffect(() => { + const buttonScreenshare1 = new ScreenshareHelperButton({ + icon: 'user', + disabled: false, + label: 'This will log on the console', + tooltip: 'this is a button injected by plugin', + position: ScreenshareHelperItemPosition.TOP_RIGHT, + onClick: () => { + pluginLogger.info('Log from nav bar plugin'); + }, + hasSeparator: true, + }); + + const buttonScreenshare5 = new ScreenshareHelperButton({ + icon: 'popout_window', + disabled: false, + label: 'This will log on the console', + tooltip: 'this is a button injected by plugin', + position: ScreenshareHelperItemPosition.TOP_RIGHT, + onClick: () => { + pluginLogger.info('Log from nav bar plugin'); + }, + hasSeparator: true, + }); + + const buttonScreenshare2 = new ScreenshareHelperButton({ + icon: 'undo', + disabled: false, + label: 'This will log on the console', + tooltip: 'this is a button injected by plugin', + position: ScreenshareHelperItemPosition.TOP_LEFT, + onClick: () => { + pluginLogger.info('Log from nav bar plugin'); + }, + hasSeparator: true, + }); + + const buttonScreenshare3 = new ScreenshareHelperButton({ + icon: 'settings', + disabled: false, + label: 'This will log on the console', + tooltip: 'this is a button injected by plugin', + position: ScreenshareHelperItemPosition.BOTTOM_LEFT, + onClick: () => { + pluginLogger.info('Log from nav bar plugin'); + }, + hasSeparator: true, + }); + + const buttonScreenshare4 = new ScreenshareHelperButton({ + icon: 'plus', + disabled: false, + label: 'This will log on the console', + tooltip: 'this is a button injected by plugin', + position: ScreenshareHelperItemPosition.BOTTOM_RIGHT, + onClick: () => { + pluginLogger.info('Log from nav bar plugin'); + }, + hasSeparator: true, + }); + pluginApi.setScreenshareHelperItems([buttonScreenshare1, buttonScreenshare5, + buttonScreenshare2, buttonScreenshare3, buttonScreenshare4, + ]); + }, []); + useEffect(() => { const randomElement = videoStreams?.user_camera[ Math.floor(Math.random() * (videoStreams?.user_camera.length ?? 0)) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 9b92fe16..d2b0fb43 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -153,6 +153,7 @@ export abstract class BbbPluginSdk { setAudioSettingsDropdownItems: () => [], setPresentationDropdownItems: () => [], setNavBarItems: () => [], + setScreenshareHelperItems: () => [], setOptionsDropdownItems: () => [], setCameraSettingsDropdownItems: () => [], setUserCameraDropdownItems: () => [], diff --git a/src/core/api/types.ts b/src/core/api/types.ts index db84899c..d96674d5 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -29,6 +29,7 @@ import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-c import { ServerCommands } from '../../server-commands/types'; import { SendGenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { UseUserCameraDomElementsFunction } from '../../dom-element-manipulation/user-camera/types'; +import { ScreenshareHelperInterface } from '../../extensible-areas'; // Setter Functions for the API export type SetPresentationToolbarItems = (presentationToolbarItem: @@ -55,7 +56,11 @@ export type SetPresentationDropdownItems = ( ) => string[]; export type SetNavBarItems = ( - userListDropdownItem: NavBarInterface[] + navBarItem: NavBarInterface[] +) => string[]; + +export type SetScreenshareHelperItems = ( + screenshareHelperItem: ScreenshareHelperInterface[] ) => string[]; export type SetOptionsDropdownItems = ( @@ -91,6 +96,7 @@ export interface PluginApi { setAudioSettingsDropdownItems: SetAudioSettingsDropdownItems; setPresentationDropdownItems: SetPresentationDropdownItems; setNavBarItems: SetNavBarItems; + setScreenshareHelperItems: SetScreenshareHelperItems; setOptionsDropdownItems: SetOptionsDropdownItems; setCameraSettingsDropdownItems: SetCameraSettingsDropdownItems; setUserCameraDropdownItems: SetUserCameraDropdownItems; diff --git a/src/extensible-areas/base.ts b/src/extensible-areas/base.ts index 0859e209..a211bcd8 100644 --- a/src/extensible-areas/base.ts +++ b/src/extensible-areas/base.ts @@ -8,6 +8,7 @@ import { NavBarItemType } from './nav-bar-item/enums'; import { OptionsDropdownItemType } from './options-dropdown-item/enums'; import { PresentationDropdownItemType } from './presentation-dropdown-item/enums'; import { PresentationToolbarItemType } from './presentation-toolbar-item/enums'; +import { ScreenshareHelperItemType } from './screenshare-helper-item/enums'; import { UserCameraDropdownItemType } from './user-camera-dropdown-item/enums'; import { UserListDropdownItemType } from './user-list-dropdown-item/enums'; import { UserListItemAdditionalInformationType } from './user-list-item-additional-information/enums'; @@ -17,7 +18,8 @@ type PluginProvidedUiItemType = PresentationToolbarItemType | ActionsBarItemType | AudioSettingsDropdownItemType | PresentationDropdownItemType | NavBarItemType | OptionsDropdownItemType | CameraSettingsDropdownItemType | UserCameraDropdownItemType | - UserListItemAdditionalInformationType | FloatingWindowType | GenericContentType; + UserListItemAdditionalInformationType | FloatingWindowType | GenericContentType | + ScreenshareHelperItemType; export interface PluginProvidedUiItemDescriptor { /** Defined by BigBlueButton Plugin Engine. */ diff --git a/src/extensible-areas/index.ts b/src/extensible-areas/index.ts index ca405237..e7d074ce 100644 --- a/src/extensible-areas/index.ts +++ b/src/extensible-areas/index.ts @@ -5,6 +5,7 @@ export * from './actions-bar-item'; export * from './audio-settings-dropdown-item'; export * from './presentation-dropdown-item'; export * from './nav-bar-item'; +export * from './screenshare-helper-item'; export * from './options-dropdown-item'; export * from './camera-settings-dropdown-item'; export * from './user-camera-dropdown-item'; diff --git a/src/extensible-areas/screenshare-helper-item/component.ts b/src/extensible-areas/screenshare-helper-item/component.ts new file mode 100644 index 00000000..fa6c9b0c --- /dev/null +++ b/src/extensible-areas/screenshare-helper-item/component.ts @@ -0,0 +1,58 @@ +import { ScreenshareHelperItemType, ScreenshareHelperItemPosition } from './enums'; +import { + ScreenshareHelperButtonProps, + ScreenshareHelperButtonInterface, +} from './types'; + +// ScreenshareHelper Extensible Area + +export class ScreenshareHelperButton implements ScreenshareHelperButtonInterface { + id: string = ''; + + type: ScreenshareHelperItemType; + + label: string; + + icon: string; + + tooltip: string; + + disabled: boolean; + + position: ScreenshareHelperItemPosition; + + onClick: () => void; + + /** + * Returns object to be used in the setter for the Screenshare Helper. In this case, + * a button. + * + * @param label - label to be displayed in screenshare helper button (Not mandatory). + * @param tooltip - label to be displayed when hovering the screenshare helper button. + * @param icon - icon to be used in the screenshare helper button. It goes in the left side of it. + * @param onClick - function to be called when clicking the button. + * @param position - position to place the screenshare helper button. + * See {@link ScreenshareHelperItemPosition} + * @param hasSeparator - boolean indicating whether the screenshare helper button has separator + * (vertical bar) + * @param disabled - if true, the screenshare helper button will not be clickable + * + * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). + */ + constructor({ + label = '', icon = '', tooltip = '', disabled = true, onClick = () => {}, + position = ScreenshareHelperItemPosition.TOP_RIGHT, + }: ScreenshareHelperButtonProps) { + this.label = label; + this.icon = icon; + this.tooltip = tooltip; + this.disabled = disabled; + this.onClick = onClick; + this.type = ScreenshareHelperItemType.BUTTON; + this.position = position; + } + + setItemId: (id: string) => void = (id: string) => { + this.id = `ScreenshareHelperButton_${id}`; + }; +} diff --git a/src/extensible-areas/screenshare-helper-item/enums.ts b/src/extensible-areas/screenshare-helper-item/enums.ts new file mode 100644 index 00000000..d71353f7 --- /dev/null +++ b/src/extensible-areas/screenshare-helper-item/enums.ts @@ -0,0 +1,14 @@ +// Screenshare Helper items types: +export enum ScreenshareHelperItemType { + BUTTON = 'SCREENSHARE_HELPER_BUTTON', +} + +/** + * Enum with the position to insert the screenshare helper item (Information or Button) + */ +export enum ScreenshareHelperItemPosition { + TOP_RIGHT = 'TOP_RIGHT', + TOP_LEFT = 'TOP_LEFT', + BOTTOM_RIGHT = 'BOTTOM_RIGHT', + BOTTOM_LEFT = 'BOTTOM_LEFT', +} diff --git a/src/extensible-areas/screenshare-helper-item/index.ts b/src/extensible-areas/screenshare-helper-item/index.ts new file mode 100644 index 00000000..dc3b8239 --- /dev/null +++ b/src/extensible-areas/screenshare-helper-item/index.ts @@ -0,0 +1,9 @@ +export { + ScreenshareHelperButton, +} from './component'; +export { + ScreenshareHelperInterface, +} from './types'; +export { + ScreenshareHelperItemPosition, +} from './enums'; diff --git a/src/extensible-areas/screenshare-helper-item/types.ts b/src/extensible-areas/screenshare-helper-item/types.ts new file mode 100644 index 00000000..2c4cfa04 --- /dev/null +++ b/src/extensible-areas/screenshare-helper-item/types.ts @@ -0,0 +1,30 @@ +import { PluginProvidedUiItemDescriptor } from '../base'; +import { ScreenshareHelperItemPosition } from './enums'; + +export interface ScreenshareHelperInterface extends PluginProvidedUiItemDescriptor{ + position: ScreenshareHelperItemPosition; +} + +export interface ScreenshareHelperButtonInterface extends ScreenshareHelperInterface{ + label: string; + + icon: string; + + tooltip: string; + + disabled: boolean; + + position: ScreenshareHelperItemPosition; + + onClick: () => void; +} + +export interface ScreenshareHelperButtonProps { + label?: string; + icon: string; + tooltip: string; + disabled: boolean; + hasSeparator: boolean; + position: ScreenshareHelperItemPosition; + onClick: () => void; +} From 8df146e0ffb75ba2d90d7d40b991d3c906450ec8 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Fri, 2 Aug 2024 08:49:25 -0300 Subject: [PATCH 4/5] [video-control] change logging message --- .../component.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx index 6cf5ec7f..9fef94c5 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx @@ -36,7 +36,7 @@ React.ReactElement { tooltip: 'this is a button injected by plugin', position: ScreenshareHelperItemPosition.TOP_RIGHT, onClick: () => { - pluginLogger.info('Log from nav bar plugin'); + pluginLogger.info('Logging from the screenshare extensible area'); }, hasSeparator: true, }); @@ -48,7 +48,7 @@ React.ReactElement { tooltip: 'this is a button injected by plugin', position: ScreenshareHelperItemPosition.TOP_RIGHT, onClick: () => { - pluginLogger.info('Log from nav bar plugin'); + pluginLogger.info('Logging from the screenshare extensible area'); }, hasSeparator: true, }); @@ -60,7 +60,7 @@ React.ReactElement { tooltip: 'this is a button injected by plugin', position: ScreenshareHelperItemPosition.TOP_LEFT, onClick: () => { - pluginLogger.info('Log from nav bar plugin'); + pluginLogger.info('Logging from the screenshare extensible area'); }, hasSeparator: true, }); @@ -72,7 +72,7 @@ React.ReactElement { tooltip: 'this is a button injected by plugin', position: ScreenshareHelperItemPosition.BOTTOM_LEFT, onClick: () => { - pluginLogger.info('Log from nav bar plugin'); + pluginLogger.info('Logging from the screenshare extensible area'); }, hasSeparator: true, }); @@ -84,7 +84,7 @@ React.ReactElement { tooltip: 'this is a button injected by plugin', position: ScreenshareHelperItemPosition.BOTTOM_RIGHT, onClick: () => { - pluginLogger.info('Log from nav bar plugin'); + pluginLogger.info('Logging from the screenshare extensible area'); }, hasSeparator: true, }); From 88949c08b6473f41b77035d32aecc10bfaa5eb53 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Fri, 2 Aug 2024 15:30:30 -0300 Subject: [PATCH 5/5] [video-control] - show all possible arguments for the new onClick function on sample --- .../src/sample-user-camera-dropdown-plugin-item/component.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx index 9fef94c5..a8c8c03b 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/sample-user-camera-dropdown-plugin-item/component.tsx @@ -104,8 +104,8 @@ React.ReactElement { label: 'This will log on the console', icon: 'user', displayFunction: ({ userId }) => randomElement?.user.userId === userId, - onClick: ({ userId }) => { - pluginLogger.info(`Alert sent from plugin, see userId: ${userId}`); + onClick: ({ userId, streamId, browserClickEvent }) => { + pluginLogger.info(`Alert sent from plugin, see userId: ${userId}; ${streamId}; ${browserClickEvent.clientX}`); }, }), ]);