Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,21 +1,97 @@
import * as React from 'react';
import { useEffect } from 'react';
import { useEffect, useState } from 'react';

import { BbbPluginSdk, PluginApi } from 'bigbluebutton-html-plugin-sdk';
import { SampleUiCommandsPluginProps } from './types';
import {
BbbPluginSdk,
PluginApi,
ActionButtonDropdownOption,
ChatFormUiDataNames,
} from 'bigbluebutton-html-plugin-sdk';
import { PrivateChatSubscriptionResult, SampleUiCommandsPluginProps } from './types';
import { GET_CHATS_SUBSCRIPTION } from './query';

function SampleUiCommandsPlugin(
{ pluginUuid: uuid }: SampleUiCommandsPluginProps,
): React.ReactElement {
BbbPluginSdk.initialize(uuid);
const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid);

const [privateChatId, setPrivateChatId] = useState<string | null>(null);
const [targetUserId, setTargetUserId] = useState<string | null>(null);

// Get all users in the meeting
const { data: usersData } = pluginApi.useUsersBasicInfo?.();

// Get current user to exclude from random selection
const { data: currentUser } = pluginApi.useCurrentUser?.();

// Subscribe to private chats to get chatId after creating
const { data: privateChatsData } = pluginApi.useCustomSubscription?.<
PrivateChatSubscriptionResult
>(GET_CHATS_SUBSCRIPTION);

// Monitor for the chatId of the private chat we created
useEffect(() => {
if (targetUserId && privateChatsData?.chat) {
const targetChat = privateChatsData.chat.find(
(chat) => chat.participant.userId === targetUserId,
);
if (targetChat && targetChat.chatId !== privateChatId) {
setPrivateChatId(targetChat.chatId);
}
}
}, [privateChatsData, targetUserId, privateChatId]);

useEffect(() => {
pluginApi.uiCommands.chat.form.open();
pluginApi.uiCommands.chat.form.fill({
text: 'Just an example message filled by the plugin',
});
}, []);
if (privateChatId) {
// Open the private chat panel
pluginApi.uiCommands?.chat.form.open({
chatId: privateChatId
});

// Fill the private chat form with a hello world message
setTimeout(() => {
pluginApi.uiCommands?.chat.form.fill({
text: 'Hello World! This message was filled by the plugin.',
});
}, 500);
}
}, [privateChatId]);

useEffect(() => {
// Set up the action button dropdown
pluginApi.setActionButtonDropdownItems([
new ActionButtonDropdownOption({
label: 'Create Private Chat & Say Hello',
icon: 'user',
tooltip: 'Creates a private chat with a random user and sends Hello World',
dataTest: 'createPrivateChatButton',
allowed: true,
onClick: () => {
// Get a random user (excluding current user)
if (usersData?.user && currentUser) {
const otherUsers = usersData.user.filter(
(user) => user.userId !== currentUser.userId,
);

if (otherUsers.length > 0) {
const randomUser = otherUsers[
Math.floor(Math.random() * otherUsers.length)
];

// Store the target user ID to track the chat creation
setTargetUserId(randomUser.userId);

// Create private chat with the random user
pluginApi.serverCommands?.chat.createPrivateChat({
userId: randomUser.userId,
});
}
}
},
}),
]);
}, [usersData, currentUser]);

return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const GET_CHATS_SUBSCRIPTION = `
subscription PrivateChats {
chat(where: {public: {_eq: false}}) {
chatId
participant {
userId
name
}
}
}
`;
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
interface SampleUiCommandsPluginProps {
export interface SampleUiCommandsPluginProps {
pluginName: string,
pluginUuid: string,
}

export { SampleUiCommandsPluginProps };
export interface PrivateChatSubscriptionResult {
chat: Array<{
chatId: string;
participant: {
userId: string;
name: string;
};
}>;
}
48 changes: 48 additions & 0 deletions src/server-commands/chat/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,36 @@ import { ChatCommandsEnum } from './enum';
import {
ChatSendMessageCommandArguments,
ChatSendMessageEventArguments,
SendChatMessageArguments,
CreatePrivateChatCommandArguments,
} from './types';

export const chat = (pluginName: string) => ({
/**
* Sends chat message to specific chat.
*
* @param SendChatMessageArguments the text, custom metadata(optional), optional flag
* to tell whether or not the message will be custom, and the chatId;
* to be sent in the public chat message.
* Refer to {@link SendChatMessageArguments} to understand the argument
* structure.
*/
sendChatMessage: (
chatMessageArguments: SendChatMessageArguments,
) => {
window.dispatchEvent(
new CustomEvent<
ChatSendMessageEventArguments
>(ChatCommandsEnum.SEND_MESSAGE, {
detail: {
pluginName,
...chatMessageArguments,
custom: chatMessageArguments?.custom || false,
},
}),
);
},

/**
* Sends chat message to the public chat.
*
Expand Down Expand Up @@ -56,4 +83,25 @@ export const chat = (pluginName: string) => ({
}),
);
},

/**
* Creates a private chat with a specific user.
*
* @param createPrivateChatCommandArguments the userId of the user to create a private chat with.
* Refer to {@link CreatePrivateChatCommandArguments} to understand the argument
* structure.
*/
createPrivateChat: (
createPrivateChatCommandArguments: CreatePrivateChatCommandArguments,
) => {
window.dispatchEvent(
new CustomEvent<
CreatePrivateChatCommandArguments
>(ChatCommandsEnum.CREATE_PRIVATE_CHAT, {
detail: {
...createPrivateChatCommandArguments,
},
}),
);
},
});
1 change: 1 addition & 0 deletions src/server-commands/chat/enum.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export enum ChatCommandsEnum {
SEND_MESSAGE = 'CHAT_SEND_MESSAGE',
CREATE_PRIVATE_CHAT = 'CHAT_CREATE_PRIVATE_CHAT',
}
19 changes: 18 additions & 1 deletion src/server-commands/chat/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,34 @@ export interface ChatSendMessageCommandArguments {
}

export interface ChatSendMessageEventArguments
extends ChatSendMessageCommandArguments {
extends ChatSendMessageCommandArguments {
pluginName: string;
chatId: string;
custom: boolean;
}

export interface SendChatMessageArguments {
textMessageInMarkdownFormat: string;
chatId: string;
custom?: boolean;
pluginCustomMetadata?: string;
}

export interface CreatePrivateChatCommandArguments {
userId: string;
}

export interface ServerCommandsChatObject {
sendChatMessage: (
chatMessageArguments: SendChatMessageArguments
) => void;
sendCustomPublicChatMessage: (
chatSendCustomPublicChatMessageCommandArguments: ChatSendMessageCommandArguments
) => void;
sendPublicChatMessage: (
chatSendPublicChatMessageCommandArguments: ChatSendMessageCommandArguments
) => void;
createPrivateChat: (
createPrivateChatCommandArguments: CreatePrivateChatCommandArguments
) => void;
}
3 changes: 3 additions & 0 deletions src/ui-commands/chat/enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export enum ChatUiCommandsEnum {
OPEN_PRIVATE_CHAT = 'OPEN_PRIVATE_CHAT_COMMAND',
}
22 changes: 18 additions & 4 deletions src/ui-commands/chat/form/commands.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import { ChatFormCommandsEnum } from './enums';
import { FillChatFormCommandArguments } from './types';
import {
FillChatFormCommandArguments,
OpenChatFormCommandArguments,
} from './types';

export const form = {
/**
* Opens the public chat panel automatically.
* Opens the chat panel automatically. If chatId is provided, opens that specific chat.
*
* @param openChatCommandArgument Optional chatId to open a specific chat panel.
* Refer to {@link OpenChatFormCommandArguments} to understand the argument structure.
*/
open: () => {
window.dispatchEvent(new Event(ChatFormCommandsEnum.OPEN));
open: (openChatCommandArgument?: OpenChatFormCommandArguments) => {
if (openChatCommandArgument) {
window.dispatchEvent(
new CustomEvent<OpenChatFormCommandArguments>(ChatFormCommandsEnum.OPEN, {
detail: openChatCommandArgument,
}),
);
} else {
window.dispatchEvent(new Event(ChatFormCommandsEnum.OPEN));
}
},

/**
Expand Down
6 changes: 5 additions & 1 deletion src/ui-commands/chat/form/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ export interface FillChatFormCommandArguments {
text: string;
}

export interface OpenChatFormCommandArguments {
chatId: string;
}

export interface UiCommandsChatFormObject {
open: () => void;
open: (openChatCommandArgument?: OpenChatFormCommandArguments) => void;
fill: (FillChatFormCommandArguments: FillChatFormCommandArguments) => void;
}
1 change: 1 addition & 0 deletions src/ui-commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { NotificationTypeUiCommand } from './notification/enums';
export { ChangeEnforcedLayoutTypeEnum, EnforcedLayoutTypeEnum } from './layout/enums';
export { ChatUiCommandsEnum } from './chat/enums';