From 886951cf1f853519ee64b17a2b911fef3061a76d Mon Sep 17 00:00:00 2001 From: Arthurk12 Date: Thu, 9 Oct 2025 15:43:02 -0300 Subject: [PATCH] feat: ajust plugin to run on bbb 3.1.x - Updates required sdk version in manifest.json - Updates SDK version to 0.1.10 - Replaces `ActionButtonDropdownItems` by `MediaAreaItems` - Adds proper padding in sidekick panel component - Uses hook to inject intl messages --- manifest.json | 2 +- package-lock.json | 16 +++- package.json | 5 +- src/components/main/component.tsx | 83 +++++-------------- src/components/main/types.ts | 8 +- src/components/modal/component.tsx | 18 +--- .../modal/locales-dropdown/component.tsx | 46 +--------- src/components/modal/styles.ts | 2 +- .../component.tsx | 10 +-- .../typed-captions-sidekick-content/styles.ts | 15 +++- src/hooks/injectIntl.tsx | 27 ++++++ src/index.tsx | 21 +++-- src/intlMessages.js | 76 +++++++++++++++++ webpack.config.js | 3 + 14 files changed, 180 insertions(+), 152 deletions(-) create mode 100644 src/hooks/injectIntl.tsx create mode 100644 src/intlMessages.js diff --git a/manifest.json b/manifest.json index 3f376db..953fbf5 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "requiredSdkVersion": "~0.0.59", + "requiredSdkVersion": "0.1.x", "name": "TypedCaptions", "javascriptEntrypointUrl": "TypedCaptions.js", "localesBaseUrl": "locales", diff --git a/package-lock.json b/package-lock.json index 12d6fd4..5deb42b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.84", + "bigbluebutton-html-plugin-sdk": "0.1.10", "path": "^0.12.7", "react": "^18.2.0", "react-chat-elements": "^12.0.14", @@ -34,6 +34,7 @@ "@types/react-dom": "^18.2.7", "@types/react-modal": "^3.16.0", "@types/styled-components": "^5.1.26", + "@types/webpack-env": "^1.18.8", "@typescript-eslint/eslint-plugin": "^6.2.0", "@typescript-eslint/parser": "^6.2.0", "babel-loader": "^9.1.2", @@ -2703,6 +2704,13 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/webpack-env": { + "version": "1.18.8", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.8.tgz", + "integrity": "sha512-G9eAoJRMLjcvN4I08wB5I7YofOb/kaJNd5uoCMX+LbKXTPCF+ZIHuqTnFaK9Jz1rgs035f9JUPUhNFtqgucy/A==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.5.12", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", @@ -3789,9 +3797,9 @@ "license": "MIT" }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.84", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.84.tgz", - "integrity": "sha512-ZaCrwxyYUv2G7HZGfOqPWZzK6QBucb7BEFS/sBuwyJhvlfMKKMdmrYdfDETZ0cGjEV4neFxf1KyCjtpQTm9+iA==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.1.10.tgz", + "integrity": "sha512-cFN8TAJabZQx6rtUzJAGCaQ2cPJqN5Cq0vIL9zEJxBBbfkRTVuX3Ku3Wja5EAQSH4Bo9sS0Sdv8X9pMxdpxTrQ==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", diff --git a/package.json b/package.json index a633ea2..feea1e7 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,12 @@ "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.84", + "bigbluebutton-html-plugin-sdk": "0.1.10", "path": "^0.12.7", - "react-intl": "^6.6.8", "react": "^18.2.0", "react-chat-elements": "^12.0.14", "react-dom": "^18.2.0", + "react-intl": "^6.6.8", "react-modal": "^3.16.1", "react-select": "^5.7.3", "react-textarea-autosize": "^8.5.3", @@ -50,6 +50,7 @@ "@types/react-dom": "^18.2.7", "@types/react-modal": "^3.16.0", "@types/styled-components": "^5.1.26", + "@types/webpack-env": "^1.18.8", "@typescript-eslint/eslint-plugin": "^6.2.0", "@typescript-eslint/parser": "^6.2.0", "babel-loader": "^9.1.2", diff --git a/src/components/main/component.tsx b/src/components/main/component.tsx index 9301538..bb30ae9 100644 --- a/src/components/main/component.tsx +++ b/src/components/main/component.tsx @@ -1,69 +1,26 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; -import { createIntl, defineMessages } from 'react-intl'; import { - ActionButtonDropdownOption, - ActionButtonDropdownSeparator, - BbbPluginSdk, + MediaAreaOption, + MediaAreaSeparator, DataChannelTypes, GenericContentSidekickArea, - PluginApi, } from 'bigbluebutton-html-plugin-sdk'; -import { TypedCaptionsProps } from './types'; import { TypedCaptionsModal } from '../modal/component'; import { CaptionMenu } from '../../common/types'; import { TypedCaptionsSidekickArea } from '../typed-captions-sidekick-content/component'; +import { TypedCaptionsProps } from './types'; +import { intlMessages } from '../../intlMessages'; -const intlMessages = defineMessages({ - writeCC: { - id: 'plugin.actionButtonDropdown.write', - description: 'action button dropdown label to start writing', - }, - stopCC: { - id: 'plugin.actionButtonDropdown.remove', - description: 'action button dropdown label to start writing', - }, - sectionName: { - id: 'plugin.actionButtonDropdown.sidekickComponent.sectionName', - description: 'name of the sidekick component section', - }, - menuTitle: { - id: 'plugin.actionButtonDropdown.sidekickComponent.menuTitle', - description: 'title of the sidekick component menu (internal part)', - }, -}); - -function TypedCaptions( - { pluginUuid: uuid }: TypedCaptionsProps, -): React.ReactElement { - BbbPluginSdk.initialize(uuid); - - const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); - +function TypedCaptions({ intl, pluginApi, uuid }: TypedCaptionsProps): React.ReactElement { const { data: captionMenusResponseFromDataChannel, pushEntry: pushCaptionMenuResponseFromDataChannel, deleteEntry: excludeCaptionMenuResponseFromDataChannel, } = pluginApi.useDataChannel('typed-captions-data-channel', DataChannelTypes.ALL_ITEMS, 'caption-menus'); - const { - messages, - currentLocale, - loading: localeMessagesLoading, - } = pluginApi.useLocaleMessages({ - headers: { - 'ngrok-skip-browser-warning': 'any', - }, - }); - - const intl = (!localeMessagesLoading && messages) ? createIntl({ - locale: currentLocale, - messages, - fallbackOnEmptyString: true, - }) : null; - const [captionLocale, setCaptionLocale] = React.useState(''); const currentUserResponse = pluginApi.useCurrentUser(); @@ -76,7 +33,7 @@ function TypedCaptions( /// contentFunction, name, section, buttonIcon React.useEffect(() => { - if (!localeMessagesLoading && captionMenusResponseFromDataChannel?.data && currentUserResponse?.data?.role === 'MODERATOR') { + if (captionMenusResponseFromDataChannel?.data && currentUserResponse?.data?.role === 'MODERATOR') { const sectionName = intl.formatMessage(intlMessages.sectionName); const sidekickMenuComponentList = captionMenusResponseFromDataChannel?.data .map((menu) => new GenericContentSidekickArea({ @@ -102,7 +59,7 @@ function TypedCaptions( })); pluginApi.setGenericContentItems(sidekickMenuComponentList); } - }, [captionMenusResponseFromDataChannel, localeMessagesLoading, messages]); + }, [captionMenusResponseFromDataChannel]); React.useEffect(() => { if (currentUserResponse?.data?.role === 'MODERATOR') { @@ -131,23 +88,21 @@ function TypedCaptions( }; } else actionButtonDropdownLabel = intl.formatMessage(intlMessages.stopCC); } - if (!localeMessagesLoading) { - pluginApi.setActionButtonDropdownItems([ - new ActionButtonDropdownSeparator(), - new ActionButtonDropdownOption({ - icon: 'closed_caption', - label: actionButtonDropdownLabel, - tooltip: 'this is a button injected by plugin', - allowed: true, - onClick: actionButtonDropdownOnClick, - }), - ]); - } + pluginApi.setMediaAreaItems([ + new MediaAreaSeparator({}), + new MediaAreaOption({ + icon: 'closed_caption', + label: actionButtonDropdownLabel, + tooltip: 'this is a button injected by plugin', + allowed: true, + onClick: actionButtonDropdownOnClick, + }), + ]); } else { - pluginApi.setActionButtonDropdownItems([]); + pluginApi.setMediaAreaItems([]); pluginApi.setGenericContentItems([]); } - }, [currentUserResponse, captionMenusResponseFromDataChannel, localeMessagesLoading, messages]); + }, [currentUserResponse, captionMenusResponseFromDataChannel]); return ( (WrappedComponent: React.ComponentType

, pluginApi: PluginApi) => function injectIntl(props: Omit) { + const currentLocale = pluginApi.useUiData(IntlLocaleUiDataNames.CURRENT_LOCALE, { + locale: 'en', + fallbackLocale: 'en', + }); + + let messages = []; + try { + messages = localesContext(`./${currentLocale.locale}.json`); + } catch { + messages = localesContext(`./${currentLocale.fallbackLocale}.json`); + } + + const intl = createIntl({ + locale: currentLocale.locale, + messages, + fallbackOnEmptyString: true, + }); + + return ; +}; diff --git a/src/index.tsx b/src/index.tsx index 0d50eda..2668f0e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,16 +1,25 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; +import { BbbPluginSdk, PluginApi } from 'bigbluebutton-html-plugin-sdk'; import TypedCaptions from './components/main/component'; +import { useInjectIntl } from './hooks/injectIntl'; const uuid = document.currentScript?.getAttribute('uuid') || 'root'; -const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +function PluginInitializer({ pluginUuid }: + { pluginUuid: string }): React.ReactNode { + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + const IntlInjectedTypedCaptions = useInjectIntl(TypedCaptions, pluginApi); + return (); +} const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( - , + + + , ); diff --git a/src/intlMessages.js b/src/intlMessages.js new file mode 100644 index 0000000..49af73c --- /dev/null +++ b/src/intlMessages.js @@ -0,0 +1,76 @@ +import { defineMessages } from 'react-intl'; + +export const intlMessages = defineMessages({ + writeCC: { + id: 'plugin.actionButtonDropdown.write', + description: 'action button dropdown label to start writing', + }, + stopCC: { + id: 'plugin.actionButtonDropdown.remove', + description: 'action button dropdown label to start writing', + }, + sectionName: { + id: 'plugin.actionButtonDropdown.sidekickComponent.sectionName', + description: 'name of the sidekick component section', + }, + menuTitle: { + id: 'plugin.actionButtonDropdown.sidekickComponent.menuTitle', + description: 'title of the sidekick component menu (internal part)', + }, + selectorLabel: { + id: 'plugin.actionButtonDropdown.modal.selectorLabel', + description: 'action button dropdown label to start writing', + }, + selectPlaceholder: { + id: 'plugin.actionButtonDropdown.modal.selectPlaceHolder', + description: 'placeholder of the selector', + }, + startButtonLabel: { + id: 'plugin.actionButtonDropdown.modal.start', + description: 'start button label', + }, + 'en-US': { + id: 'plugin.actionButtonDropdown.modal.dropdown.en-US', + description: 'English language', + }, + 'de-DE': { + id: 'plugin.actionButtonDropdown.modal.dropdown.de-DE', + description: 'English language', + }, + 'es-ES': { + id: 'plugin.actionButtonDropdown.modal.dropdown.es-ES', + description: 'English language', + }, + 'fr-FR': { + id: 'plugin.actionButtonDropdown.modal.dropdown.fr-FR', + description: 'English language', + }, + 'hi-ID': { + id: 'plugin.actionButtonDropdown.modal.dropdown.hi-ID', + description: 'English language', + }, + 'it-IT': { + id: 'plugin.actionButtonDropdown.modal.dropdown.it-IT', + description: 'English language', + }, + 'ja-JP': { + id: 'plugin.actionButtonDropdown.modal.dropdown.ja-JP', + description: 'English language', + }, + 'pt-BR': { + id: 'plugin.actionButtonDropdown.modal.dropdown.pt-BR', + description: 'English language', + }, + 'ru-RU': { + id: 'plugin.actionButtonDropdown.modal.dropdown.ru-RU', + description: 'English language', + }, + 'zh-CN': { + id: 'plugin.actionButtonDropdown.modal.dropdown.zh-CN', + description: 'English language', + }, + inputPlaceholder: { + id: 'plugin.actionButtonDropdown.sidekickComponent.inputPlaceholder', + description: 'Placeholder of the sidekick component input', + }, +}); diff --git a/webpack.config.js b/webpack.config.js index 691753e..ed037d9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -58,6 +58,9 @@ module.exports = { }, resolve: { extensions: ['.js', '.jsx', '.tsx', '.ts'], + alias: { + '@locales': path.resolve(__dirname, './public/locales'), + }, }, plugins: [ new CopyWebpackPlugin({