
Wtyczki BigBlueButton
Witamy w oficjalnej dokumentacji wtyczek BigBlueButton.
Poradnik obejmuje szeroki zakres tematów związanych z tworzeniem wtyczek, w tym:
- Jak działają wtyczki w systemie BigBlueButton;
- Jak zbudować pierwszą wtyczkę (na prostym przykładzie „Hello World”); — szczegółowa dokumentacja dotycząca różnych interfejsów API dostępnych do interakcji podczas spotkań;
...i wiele więcej.
Zaczynamy!
Zastosowanie
To jest ogólna instrukcja dotycząca korzystania z wtyczki. Aby zapoznać się ze szczegółowym przykładem konfiguracji dla każdego przypadku użycia, zajrzyj do plików README w odpowiednich folderach samples.
Uruchamianie wtyczki ze źródła
W celach programistycznych możesz uruchomić wtyczkę lokalnie ze źródła.
Na przykład, jeśli weźmiesz sample-action-button-dropdown-plugin,
, wykonasz następujące czynności:
Uruchamianie z kodu źródłowego z lokalnym serwerem BBB
-
Uruchom serwer deweloperski:
cd $HOME/src/bigbluebutton-html-plugin-sdk/samples/sample-action-button-dropdown-plugin npm install npm start -
Dodaj odniesienie do niego w wywołaniu
/createBigBlueButton lub dodaj je w/etc/bigbluebutton/bbb-web.properties:
pluginManifests=[{"url": "http://<your-URL>/manifest.json"}]
Przypomnienie: Nie używaj adresu URL localhost, który utworzy dla Ciebie npm start, Akka nie będzie mogła w ten sposób uzyskać dostępu do plików manifestu (nawet jeśli programujesz w lokalnym środowisku bbb-docker). Dlatego zalecamy wykonanie instrukcji z następnej sekcji, aby przetestować wtyczkę tak, jakby znajdowała się na zdalnym serwerze BBB (uwaga: będziesz używać NGROK).
Uruchamiany z kodu źródłowego na zdalnym serwerze BBB
Jeśli uruchamiasz swój serwer BBB gdzie indziej, nie możesz po prostu wskazać adresu URL manifestu na adres lokalny, musisz albo udostępnić wbudowaną wersję w CDN, albo udostępnić wersję deweloperską za pomocą usługi, która to zrobi publiczne. W przypadku drugiej opcji polecamy NGROK. Oto instrukcja jak to zrobić:
-
Załóż konto na https://ngrok.com/ (Oficjalna strona NGROK);
-
Zainstaluj NGROK na swoim komputerze. Mają na to przewodnik zaraz po utworzeniu konta;
-
Uruchom serwer rozwoju wtyczki:
cd $HOME/src/plugin-pick-random-user-plugin
npm install
npm start
- Uruchom serwer NGROK na swoim komputerze za pomocą następującego polecenia:
ngrok http http://172.17.0.1:4701
Pamiętaj, aby wskazać NGROK poprawny lokalny adres URL (w naszym przypadku - próbki są wykonane w ten sposób, na przykład użyliśmy http://172.17.0.1:4701)
Zaraz potem NGROK utworzy interfejs do twojego terminala i wyświetli adres URL, pod którym podawane są twoje pliki statyczne.
Oto przykład adresu URL: https://<uuid>.ngrok-free.app
Możesz już wchodzić w interakcję z tym adresem URL i uzyskać dostęp do obu
https://<uuid>.ngrok-free.app/manifest.json
lub
https://<uuid>.ngrok-free.app/PickRandomUserPlugin.js
- Dodaj ten parametr tworzenia do API-mate serwera, na którym go testujesz:
pluginManifests=[{"url": "https://<uuid>.ngrok-free.app/manifest.json"}]
I gotowe, możesz to swobodnie testować.
Budowa wtyczki (produkcyjna)
Aby zbudować wtyczkę do produkcji użyj
(ponownie na przykładzie sample-action-button-dropdown-plugin),
wykonaj następujące kroki:
cd $HOME/src/bigbluebutton-html-plugin-sdk/samples/sample-action-button-dropdown-plugin
npm ci
npm run build-bundle
Powyższe polecenie wygeneruje folder dist, zawierający dołączony plik JavaScript o nazwie SampleActionButtonDropdownPlugin.js wraz z manifest.json.
Te pliki mogą być hostowane na dowolnym serwerze HTTPS.
Aby używać wtyczki z BigBlueButton, dodaj adres URL wtyczki manifest.json do bigbluebutton.properties lub możesz po prostu wysłać go poprzez parametr /create:
pluginManifests=[{"url":"<your-domain>/path/to/manifest.json"}]
Hostowanie wtyczki na serwerze BBB
Chociaż wtyczka może być hostowana na dowolnym serwerze, możliwe jest również hostowanie dołączonego pliku bezpośrednio na
na serwerze BigBlueButton. W tym celu kopiujesz dist/SampleActionButtonDropdownPlugin.js i dist/manifest.json do folderu /var/www/bigbluebutton-default/assets/plugins/sampleActionButtonDropdownPlugin.
W tym przypadku adres URL manifestu będzie miał postać https://<your-host>/plugins/sampleActionButtonDropdownPlugin/manifest.json.
Komentarze
Sposoby ładowania wtyczki do spotkania
Jak opisano we wcześniejszych sekcjach, istnieje kilka sposobów ładowania wtyczki do spotkania:
/createParametrpluginManifests– Dotyczy tylko tworzonego spotkania. Musisz wyraźnie wymienić wtyczki w żądaniu.- parametr
/createpluginManifestsFetchUrl– dotyczy również tylko tworzonego spotkania, ale zamiast bezpośrednio wyświetlać listę wtyczek, podajesz adres URL, który zwraca listę manifestów wtyczek. Pomaga to zmniejszyć rozmiar żądania/create. pluginManifestsw/etc/bigbluebutton/bbb-web.properties– dotyczy globalnie wszystkich spotkań na serwerze.
Wszystkie źródła wtyczek są połączone w jedną listę z usuniętymi duplikatami. Oznacza to, że wtyczki są łączone, a nie zastępowane.
Używanie symboli zastępczych w adresach URL wtyczek
Możesz używać symboli zastępczych w adresach URL wtyczek zdefiniowanych w dowolnej z wyżej wymienionych konfiguracji. Obecnie jedynym obsługiwanym symbolem zastępczym jest:
%%HTML5_PLUGIN_SDK_VERSION%%– zostanie automatycznie zastąpione wersjąbigbluebutton-html-plugin-sdkużywaną przezbigbluebutton-html5.%%HTML5_PLUGIN_SDK_MAIN_VERSION%%– zostanie to automatycznie zastąpione przez wersję głównąbigbluebutton-html-plugin-sdk, zgodnie z kompatybilnością z serwerami: tylko Major z1.0(np.:1dla1.0.0-beta.3i dla1.2.0), Major + Minor dla wersji0.x, gdzie każdy Minor jest zmianą przełomową (np.:0.1dla0.1.26) - używany przezbigbluebutton-html5.%%BBB_VERSION%%– Zostanie to automatycznie zastąpione pełną wersją serwera BigBlueButton (np.:3.0.6), z której wywoływany jest adres URL.%%BBB_MAIN_VERSION%%– zostanie to automatycznie zastąpione bieżącą wersją główną serwera BigBlueButton - złożoną przez Major + Minor (np.:3.0dla3.0.6), z którego wywoływany jest adres URL.%%MEETING_ID%%– zostanie automatycznie zastąpiony zewnętrznym identyfikatorem spotkania.
Jest to przydatne do odwoływania się do plików wtyczek z wersjonowaniem bez kodowania na stałe wersji SDK.
Przykłady:
pluginManifests=[{"url":"https://my-cdn.com/%%HTML5_PLUGIN_SDK_VERSION%%/pick-random-user/manifest.json"}]
lub
pluginManifestsFetchUrl=https://my-cdn.com/%%HTML5_PLUGIN_SDK_VERSION%%/all-my-plugins/list-of-plugins.json
Jeśli twój klient bbb-html5 używa wersji 0.0.79 bigbluebutton-html-plugin-sdk (jak widać w jego package.json):
{
"dependencies": {
"bigbluebutton-html-plugin-sdk": "0.0.79",
},
}
Następnie BBB-Web automatycznie przekształci adresy URL w następujący sposób:
pluginManifests=[{"url":"https://my-cdn.com/0.0.79/pick-random-user/manifest.json"}]
lub
pluginManifestsFetchUrl=https://my-cdn.com/0.0.79/all-my-plugins/list-of-plugins.json
BBB-Web pobierze następnie manifesty wtyczek, korzystając z tych rozpoznanych adresów URL.
W przyszłości może zostać dodana obsługa dodatkowych symboli zastępczych.
Manifest Json
Zgodność wersji SDK
Pole requiredSdkVersion deklaruje zakres SDK obsługiwany przez wtyczkę,
począwszy od pierwszej wersji SDK, na której działa. Ta minimalna kompatybilna wersja
jest oddzielna od zależności SDK użytej do zbudowania wtyczki w
package.json, która może być nowsza.
Po rozpoczęciu spotkania BigBlueButton odczytuje wersję SDK z właściwości serwera
html5PluginSdkVersion i sprawdza, czy ta wersja spełnia
zakres manifestu zadeklarowany przez wtyczkę. Autor wtyczki jest odpowiedzialny za wybranie przez
zakresu określającego, które wersje BigBlueButton mogą ją załadować. Jeśli
zestaw SDK serwera nie spełnia tego zakresu, BigBlueButton rejestruje błąd ładowania wtyczki
w bbb-apps-akka.
Pole akceptuje zakres wersji semantycznej. Dwa zakresy używane przez oficjalne wtyczki zachowują się inaczej przed wersją 1.0:
— zakres tyldy umożliwia aktualizacje poprawek w ramach określonej wersji pomocniczej. Na przykład
~0.0.77 akceptuje 0.0.77 i 0.0.78, ale odrzuca 0.1.0.
— Zakres karetki umożliwia aktualizacje, które nie zmieniają niezerowej wersji znajdującej się najbardziej po lewej stronie.
Na przykład ^0.1.26 akceptuje 0.1.26 i 0.1.27, ale odrzuca 0.2.0.
Na linii 0.0.x ^0.0.77 akceptuje tylko 0.0.77.
Dlatego oficjalne wtyczki starszej linii 0.0.x używają zakresów tyld, jak pokazano
w poniższych przykładach. Wtyczki z linii 0.1.x używają zakresów karetki. Ta konwencja daszka
nadal wyraża zgodność, gdy SDK osiągnie 1.x: na przykład
^1.0.0 akceptuje kompatybilne wydania 1.x i odrzuca 2.0.0.
Przedpremierowe wersje SDK są zgodne z zasadą npm dotyczącą przedpremierowych wydań: tylko przedpremierowe wydanie
spełnia zakres, w którym niektóre komparatory nazywają przedpremierowe wydanie tego samego
major.minor.patch. Chociaż na serwerze działają 1.0.0-beta.3, ^1.0.0, 0.x i
>=0.1.5, wszystkie go odrzucają, ponieważ żaden z nich nie nazywa wersji wstępnej 1.0.0. Aby
załadować przedpremierową wersję SDK i nadal obsługiwać stabilną linię, zadeklaruj oba, dla
na przykład ^0.1.5 || ^1.0.0-beta.1. ^1.0.0-beta.1 akceptuje również ostateczne wydania
1.0.0 i późniejsze wydania 1.x, ale odrzuca wstępne wydania innych wersji, takich jak
jako 1.1.0-alpha.1.
Oto kompletny przykład manifest.json ze wszystkimi możliwymi konfiguracjami:
{
"requiredSdkVersion": "~0.0.77",
"name": "MyPlugin",
"version": "0.0.8", // Optional
"javascriptEntrypointUrl": "MyPlugin.js",
"javascriptEntrypointIntegrity": "sha384-Bwsz2rxm...", // Optional
"localesBaseUrl": "https://cdn.domain.com/my-plugin/", // Optional
"enabledForBreakoutRooms": false, // Optional, defaults to false
"loggerSettings": { // Optional
"console": {
"enableRuntimeErrorLogging": false,
"enabled": true,
"level": "debug" // Possible values: info, debug, warn, error
},
"external": {
"enabled": false,
"level": "info", // Possible values: info, debug, warn, error
"url": "https://LOG_HOST/html5Log",
"method": "POST",
"throttleInterval": 400,
"flushOnClose": true,
"logTag": ""
}
},
"dataChannels":[
{
"name": "public-channel",
"pushPermission": ["moderator","presenter"], // "moderator","presenter", "all", "viewer"
"replaceOrDeletePermission": ["moderator", "creator"] // "moderator", "presenter","all", "viewer", "creator"
}
], // One can enable more data-channels to better organize client communication
"eventPersistence": {
"isEnabled": true // By default it is not enabled
},
"remoteDataSources": [
{
"name": "allUsers",
"url": "${meta_pluginSettingsUserInformation}",
"fetchMode": "onMeetingCreate", // Possible values: "onMeetingCreate", "onDemand"
"permissions": ["moderator", "viewer"]
}
],
"serverCommandsPermission": {
"chat.sendCustomPublicChatMessage": ["presenter", "moderator"] // "moderator","presenter", "all", "viewer"
},
"settingsSchema": [
{
"name": "myJson",
"label": "myJson",
"required": true,
"defaultValue": {
"abc": 123
},
"type": "json" // Possible values: "int", "float", "string", "boolean", "json"
}
]
}
Aby lepiej zrozumieć zdalne źródła danych, proszę zapoznać się z tą sekcją
wersja:
Dotyczy wersji wtyczki. Zapobiega buforowaniu przez przeglądarki starych plików wtyczek.
Po ustawieniu dołącza wersję do javascriptEntrypointUrl, zmuszając przeglądarki do pobrania najnowszego pliku.
Przykład:
version=0.0.8
javascriptEntrypointUrl=MyPlugin.js
Załaduje się przeglądarka: MyPlugin.js?version=0.0.8.
loggerSettings:
Opcjonalna dyrektywa loggerSettings pozwala na nadpisanie domyślnej konfiguracji rejestratora dla konkretnej wtyczki. Na przykład możesz ustawić poziom dziennika klienta na informacyjny, jednocześnie ograniczając poziom dziennika wtyczki na błąd. Jeżeli nie zostaną podane żadne ustawienia, rejestrator wtyczki dziedziczy konfigurację domyślną.
Schemat ustawień:
settingsSchema służy dwóm głównym celom:
- Weryfikacja: Zapewnia, że wszystkie wymagane ustawienia są dostępne dla wtyczki. Jeśli brakuje któregoś z wymaganych ustawień, wtyczka nie zostanie załadowana.
- Wyświetlanie konfiguracji: Wyświetla listę wszystkich dostępnych ustawień wtyczki, umożliwiając systemom zewnętrznym — takim jak system zarządzania nauczaniem (LMS) — prezentowanie tych ustawień organizatorowi spotkania. Dzięki temu organizator może ręcznie skonfigurować wtyczkę przed rozpoczęciem spotkania.
Tabela jest szersza od ekranu. Przewiń ją w poziomie.
| Imię | Wymagane | Opis |
|---|---|---|
name |
Tak | Nazwa ustawienia zdefiniowana w pliku YAML |
label |
Nie | Etykieta widoczna dla użytkownika, która pojawia się w interfejsie użytkownika integracji |
required |
Tak | Wskazuje, czy należy podać to ustawienie (true lub false) |
defaultValue |
Nie | Wartość domyślna, która ma być używana, jeśli nie zdefiniowano jawnie żadnego ustawienia |
type |
Tak | Oczekiwany typ danych dla ustawienia. Możliwe wartości: "int", "float", "string", "boolean", "json" |
Przykład
Biorąc pod uwagę settingsSchema zdefiniowane w manifest.json, odpowiedni plik konfiguracyjny YAML (/etc/bigbluebutton/bbb-html5.yml) wyglądałby następująco:
public:
plugins:
- name: MyPlugin
settings:
myJson:
abc: my123
def: 3234
enabledForBreakoutRooms:
Domyślnie wtyczki nie są ładowane w pokojach podgrup. Ustawienie enabledForBreakoutRooms na true sprawia, że wtyczka będzie dostępna zarówno w pokojach podgrup, jak i w pokoju głównym.
{
"enabledForBreakoutRooms": true
}
Jeśli ta właściwość ma wartość false (lub została pominięta), serwer odfiltrowuje wtyczkę przed utworzeniem pokoju podgrup, więc nigdy nie będzie ona ładowana dla uczestników podgrup.
javascriptEntrypointIntegrity:
Opcjonalny skrót Subresource Integrity (SRI) dla pakietu JavaScript wtyczki. Jeśli jest obecna, przeglądarka sprawdza, czy pobrany plik jest zgodny z hashem przed jego wykonaniem, chroniąc przed nieuprawnionymi lub złośliwymi podstawieniami pliku wtyczki.
Wartość musi być zgodna z formatem SRI <algorithm>-<base64-hash> (np. sha384-Bwsz2rxm...).
{
"javascriptEntrypointIntegrity": "sha384-Bwsz2rxm..."
}
Ograniczenia między źródłami: Program ładujący wtyczki ustawia atrybut
integrityw znaczniku<script>, ale nie ustawia atrybutucrossorigin. Przeglądarki wymagają zarównointegrity, jak icrossorigin="anonymous"(plus nagłówki CORS z serwera) do kontroli SRI skryptów pochodzących z różnych źródeł. Bezcrossoriginsprawdzenie integralności nie powiedzie się w przypadku wtyczek hostowanych w innej domenie (np. CDN). Dlatego weryfikacja integralności SRI działa niezawodnie tylko wtedy, gdy plik wtyczki jest dostarczany z tego samego źródła co klient BigBlueButton. Unikaj ustawiania tego pola dla wtyczek hostowanych przez CDN, dopóki do modułu ładującego nie zostanie dodana obsługa różnych źródeł.
Jeśli pominięto, nie jest przeprowadzana żadna kontrola integralności.
localesBaseUrl:
Opcjonalny podstawowy adres URL, z którego zestaw SDK wtyczki ładuje pliki komunikatów ustawień regionalnych (i18n) dla wtyczki. Umożliwia to obsługę internacjonalizacji — zestaw SDK pobiera pliki ustawień regionalnych w odniesieniu do tego adresu URL, gdy klient przełącza język.
{
"localesBaseUrl": "https://cdn.domain.com/my-plugin/"
}
Jeśli adres URL jest względny (nie zaczyna się od http:// ani https://), serwer rozwiązuje go, dołączając go do części katalogu adresu URL manifestu, używając zwykłego łączenia ciągów. Oznacza to, że wiodący / nie jest traktowany jako katalog główny witryny — zostanie dosłownie połączony, tworząc uszkodzony adres URL. Użyj bezwzględnego adresu URL lub ścieżki względnej bez wiodącego /:
{ "localesBaseUrl": "locales/" } // OK — appended to manifest directory
{ "localesBaseUrl": "https://cdn.example.com/my-plugin/locales/" } // OK — absolute
{ "localesBaseUrl": "/locales/" } // BAD — leading slash breaks the URL
Jeśli zostanie pominięty, pliki ustawień regionalnych nie zostaną załadowane dla wtyczki.
Przykłady
Przykładowe implementacje pokazujące, jak rozszerzać i dostosowywać różne części klienta BigBlueButton, można znaleźć w folderze samples repozytorium bigbluebutton-html-plugin-sdk.
Ponadto repozytorium wtyczek BigBlueButton udostępnia kolekcję oficjalnych wtyczek, które możesz eksplorować w poszukiwaniu inspiracji.
Budowanie przykładowej wtyczki Hello-World
Ta sekcja przeprowadzi Cię przez wszystkie kroki potrzebne do stworzenia funkcjonalnej wtyczki — lub przynajmniej solidnego punktu wyjścia. W tym przykładzie wtyczka doda opcję do menu rozwijanego Opcje (trzy kropki w prawym górnym rogu klienta). Po kliknięciu wyświetli się wyskakujące okienko z komunikatem "hello world".
1. Wybierz odpowiednią wersję SDK
Najpierw wybierz odpowiednią wersję bigbluebutton-html-plugin-sdk w oparciu o Twój serwer BigBlueButton. Wskazówki można znaleźć w sekcji Wersja wtyczek. Informacje te będą Ci potrzebne w dalszej części samouczka.
2. Użyj oficjalnego szablonu wtyczki
Zacznij od szablonu wtyczki dostarczonego przez organizację BigBlueButton, dostępnego pod adresem:
https://github.com/bigbluebutton/plugin-template
Chociaż możliwe jest zbudowanie wtyczki od zera, wymaga to określonych konfiguracji w plikach takich jak package.json i webpack.config.js (jeśli używasz pakietu Webpack), co może być trudne do wykonania. Oficjalny szablon oszczędza czas, udostępniając wszystkie niezbędne szablony, dzięki czemu możesz skupić się na pisaniu logiki wtyczki.
Aby rozpocząć:
— odwiedź stronę szablonu i kliknij przycisk „Użyj tego szablonu”, aby utworzyć własne repozytorium w ramach swojego konta GitHub.

3. Sklonuj repozytorium i rozpocznij kodowanie
Sklonuj swoje nowe repozytorium lokalnie i rozpocznij wprowadzanie niezbędnych modyfikacji. Wykonaj poniższe kroki:
Ustaw nazwę wtyczki
- Nazwij swoją wtyczkę. W tym samouczku użyjemy nazwy
plugin-hello-world, ale możesz wybrać inną nazwę. — zdefiniuj także wersję nazwy PascalCase (np.PluginHelloWorld) dla plików konfiguracyjnych.
Aktualizuj symbole zastępcze
Zastąp wszystkie symbole zastępcze <plugin-name> w następujących plikach:
package.jsonwebpack.config.js(użyj PascalCase)manifest.json(użyj PascalCase)
Sprawdź zgodność wersji SDK
Przejdź do bigbluebutton-html-plugin-sdk strony NPM i sprawdź, która wersja jest kompatybilna z Twoim serwerem BigBlueButton.
Na przykład, jeśli Twój serwer korzysta z BigBlueButton 3.0, możesz potrzebować najnowszej wersji
0.0.x, czyli obecnie0.0.73.
Zaktualizuj odpowiednio swój package.json, a następnie uruchom:
npm install
Utwórz komponent wtyczki
Utwórz folder i plik komponentu:
mkdir src/plugin-hello-world
touch src/plugin-hello-world/component.tsx
Teraz dodaj następujący kod do component.tsx:
import { BbbPluginSdk, OptionsDropdownOption, pluginLogger } from 'bigbluebutton-html-plugin-sdk';
import * as React from 'react';
import { useEffect } from 'react';
interface PluginHelloWorldProps {
pluginUuid: string;
}
function PluginHelloWorld({ pluginUuid }: PluginHelloWorldProps): React.ReactElement {
BbbPluginSdk.initialize(pluginUuid);
const pluginApi = BbbPluginSdk.getPluginApi(pluginUuid);
useEffect(() => {
pluginApi.setOptionsDropdownItems([
new OptionsDropdownOption({
label: 'Click me',
icon: 'user',
onClick: () => {
alert('Hello, World!');
pluginLogger.info('Option has been clicked');
},
}),
]);
}, []);
return null;
}
export default PluginHelloWorld;
— zaczep useEffect zapewnia, że wtyczka inicjuje się tylko raz.
setOptionsDropdownItemsdodaje nowy przycisk do menu rozwijanego. — moduł obsługionClickuruchamia proste wyskakujące okienko.
4. Zaktualizuj index.tsx
Wklej następujący kod do swojego pliku index.tsx:
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import PluginHelloWorld from './plugin-hello-world/component';
const uuid = document.currentScript?.getAttribute('uuid') || 'root';
const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin';
const root = ReactDOM.createRoot(document.getElementById(uuid));
root.render(
<PluginHelloWorld
pluginUuid={uuid}
pluginName={pluginName}
/>
);
To wszystko!
Udało Ci się stworzyć swoją pierwszą wtyczkę!
Aby uruchomić wtyczkę, wybierz jeden z trybów:
Skontaktuj się z nami, aby uzyskać dodatkowe informacje lub pomoc.
Architektura wtyczek
W tej sekcji wyjaśniono, jak wtyczki działają w BigBlueButton, od definicji po ładowanie i wykonanie w kliencie.
Co to jest wtyczka?
W BigBlueButton wtyczka to po prostu plik JavaScript ładowany w przeglądarce użytkownika.
Często zadawane pytanie brzmi:
Czy użytkownicy końcowi (np. studenci) muszą coś instalować, np. rozszerzenie przeglądarki?
Odpowiedź brzmi: Nie! Plik JavaScript (wtyczka) jest dostarczany do klienta automatycznie przez serwer. Klient bigbluebutton-html5 ładuje go bez konieczności wykonywania jakichkolwiek działań ze strony użytkownika.
Jak ładuje się wtyczkę?
Proces ładowania wtyczki jest podzielony na dwie główne fazy: tworzenie spotkania i ładowanie klienta.
- Faza tworzenia spotkania
sequenceDiagram
participant Client
participant BbbWeb
participant Akka
participant DataBase
participant PluginStorageServer
Client->>BbbWeb: /create with "pluginManifests"
BbbWeb->>PluginStorageServer: Request Plugin Manifests contents
PluginStorageServer->>BbbWeb: Return Plugin Manifests contents
BbbWeb->>Akka: CreateMeetingReqMsg (contains the pluginManifests)
Akka->>DataBase: Save Meeting with plugins
Podczas tworzenia spotkania:
- Klient wysyła żądanie do punktu końcowego /create z listą
pluginManifests. bbb-webpobiera manifesty wtyczki ze statycznej pamięci serwera wtyczek (np.: S3 lub wewnętrznie z serwera BBB). — po pobraniu zawiera treść manifestu w pliku CreateMeetingReqMsg, który jest wysyłany do Akka.- Akka przechowuje dane wtyczki w bazie danych dla tego spotkania.
Innym sposobem wysłania listy pluginManifests do bbb-web jest włączenie jej do /etc/bigbluebutton/bbb-web.properties, jak wspomniano wcześniej w drugim punkcie tej sekcji. W ten sposób bbb-web pobiera to poprzez plik konfiguracyjny i będzie stosowane do każdego spotkania tego konkretnego serwera (bez potrzeby dołączania go do każdego wywołania tworzenia). Kluczowy punkt: jeśli w wywołaniu tworzenia zostanie uwzględniona inna lista wraz z listą w pliku właściwości, zostaną one połączone w jedną i kontynuowany będzie przepływ.
sequenceDiagram
participant Client
participant GraphqlServer
participant DataBase
participant PluginStorageServer
Client->>GraphqlServer: query PluginConfigurationQuery (with all plugin information)
GraphqlServer->>DataBase: query PluginConfigurationQuery
DataBase->>GraphqlServer: return PluginConfigurationQuery data
GraphqlServer->>Client: return PluginConfigurationQuery data
Client->>PluginStorageServer: Request Plugin Javascript bundle
PluginStorageServer->>Client: Return Plugin Javascript bundle
Jeśli chodzi o drugą część, gdy użytkownik dołącza do spotkania:
- Klient wysyła zapytanie PluginConfigurationQuery za pośrednictwem serwera GraphQL.
- Serwer wysyła zapytanie do bazy danych i zwraca konfigurację wtyczki, która obejmuje:
plugin {
name,
javascriptEntrypointUrl,
javascriptEntrypointIntegrity,
localesBaseUrl,
}
— korzystając z tych informacji, klient pobiera pakiet JavaScript wtyczki z serwera magazynu wtyczek i ładuje go do drzewa komponentów React.
Galeria aplikacji
Galeria aplikacji to centralny panel interfejsu użytkownika, w którym użytkownicy mogą odkrywać wtyczki i narzędzia dostępne podczas spotkania oraz korzystać z nich. Został zaprojektowany jako rozszerzalny pulpit nawigacyjny, który umożliwia programistom rejestrowanie własnych aplikacji, aby pojawiały się obok natywnych narzędzi BigBlueButton.
Galeria przedstawia dwie główne grupy aplikacji:
- Przypięte aplikacje: Aplikacje, które użytkownik zdecydował, aby były widoczne na pasku bocznym w celu szybkiego dostępu.
- Odpięte aplikacje: Lista wszystkich innych zarejestrowanych aplikacji, które nie są aktualnie przypięte.
Bazując na dostarczonych plikach, podstawowa logika znajduje się w ui/components/apps-gallery/component.tsx, który odwzorowuje registeredApps i pinnedApps z kontekstu układu, aby renderować je we właściwych sekcjach interfejsu użytkownika. Pojemnik na ten komponent to ui/components/apps-gallery/container.tsx.
Tworzenie bigbluebutton-html-plugin-sdk
Ten przewodnik wyjaśnia, jak wnosić wkład w bigbluebutton-html-plugin-sdk, w tym dodawać nowe funkcje lub naprawiać istniejące problemy. Omówiono także, w razie potrzeby, jak zintegrować te zmiany z klientem BigBlueButton.
1. Określ zakres zmiany
Przed rozpoczęciem programowania oceń, czy Twoja zmiana dotyczy tylko repozytorium plugin-sdk, czy też wymaga zmiany w głównym repozytorium BigBlueButton (bbb-html5).
Jako przykład przeanalizujmy funkcję, która wpływa na oba elementy: dodanie atrybutu data-test do obszaru rozszerzalnego pływającego okna.
2. Rozwiń niezbędne repozytoria
Po wybraniu repozytoriów, w których potrzebne są zmiany, konieczne jest posiadanie forka, aby wnieść swój wkład.
- Wykonaj fork repozytorium bigbluebutton-html-plugin-sdk;
- Utwórz rozwidlenie repozytorium główny bigbluebutton;
- Sklonuj widełki lokalnie;
git clone https://github.com/YourUsername/bigbluebutton-html-plugin-sdk
3. Konfigurowanie środowiska
Po sklonowaniu obu repozytoriów sklonowano lokalnie:
bigbluebutton-html-plugin-sdkbigbluebutton
Utwórz gałąź programistyczną w obu repozytoriach (najlepiej o tej samej nazwie), aby zachować porządek zmian.
4. Dokonaj zmian w zestawie SDK wtyczki
Zacznij od wdrożenia wymaganych zmian w pakiecie SDK. W naszym przykładzie do komponentu FloatingWindow dodamy nową właściwość string dataTest:
File: src/extensible-areas/floating-window/component.ts
export class FloatingWindow implements FloatingWindowInterface {
id: string = '';
type: FloatingWindowType;
dataTest: string;
constructor({
id,
dataTest,
...
}: FloatingWindowProps) {
if (id) this.id = id;
this.dataTest = dataTest;
...
}
}
Zaktualizuj także definicję typu, aby odzwierciedlić tę nową właściwość:
Plik: src/extensible-areas/floating-window/types.ts
export interface FloatingWindowProps {
id: string;
dataTest: string;
...
}
5. Opublikuj zmiany w potrzebnych projektach
Aby zweryfikować zmianę, musisz ją przetestować w przykładowej wtyczce i kliencie BigBlueButton.
W przypadku nowych funkcji najlepiej utworzyć nową przykładową wtyczkę. Jednak w tym przykładzie użyjemy istniejącego sample-floating-window-plugin.
Wykonaj poniższe kroki, aby skompilować i opublikować pakiet SDK zarówno w przykładowej wtyczce, jak i w bbb-html5:
# From the SDK root
npm install
npm run build
# Ensure dependencies are installed in both target projects
cd ~/path/to/bigbluebutton-html5
npm install
cd -
cd samples/sample-floating-window-plugin
npm install
cd -
# Publish SDK changes to both the BBB client and the sample plugin
./scripts/publish-to-project-folder.sh ~/path/to/bbb-html5
./scripts/publish-to-project-folder.sh samples/sample-floating-window-plugin
Dzięki temu zmiany w zestawie SDK zostaną zastosowane zarówno do klienta BigBlueButton, jak i próbki wtyczki.
Opcjonalnie: Aby opublikować SDK we wszystkich przykładowych wtyczkach jednocześnie, użyj:
./scripts/publish-to-samples.sh
6. Zaktualizuj klienta BigBlueButton (bbb-html5)
Teraz wprowadź niezbędne zmiany w Repozytorium bigbluebutton/bigbluebutton w katalogu bigbluebutton-html5. W naszym przykładzie zaktualizuj następujące pliki, aby przekazać i użyć nowej właściwości dataTest:
Plik: imports/ui/components/floating-window/component.tsx
const renderComponent = (
elementRef: React.MutableRefObject<null>,
...
dataTest: string,
) => (
<Styled.FloatingWindowContent
ref={elementRef}
id={key}
data-test={dataTest}
...
/>
);
Zaktualizuj logikę kontenera (imports/ui/components/floating-window/container.tsx), aby przekazać dataTest do renderComponent.
7. Zaktualizuj przykładową wtyczkę
Po zbudowaniu i opublikowaniu pakietu SDK możesz zaktualizować przykładową wtyczkę, aby korzystała z nowego dataTest odpowiednio własność. I przetestuj go (na przykład używając trybu programistycznego) na kliencie BigBlueButton (bigbluebutton-html5).
8. Przesyłanie żądań ściągnięcia
Po zakończeniu i przetestowaniu wszystkich zmian:
— Zatwierdź zmiany w bigbluebutton-html-plugin-sdk (wszystkie potrzebne do uruchomienia funkcji/poprawki i zmian wprowadzonych w przykładzie);
- W kliencie
bigbluebutton-html5nie podawaj jeszcze numeru wersji pakietu SDK wpackage.json. Zamiast tego użyj skrótu zatwierdzenia ze zmian SDK
Przykład:
"dependencies": {
...
"bigbluebutton-html-plugin-sdk": "https://codeload.github.com/bigbluebutton/bigbluebutton-html-plugin-sdk/tar.gz/<commit-hash-id>"
}
Możesz uzyskać skrót zatwierdzenia z git log lub bezpośrednio z listy zatwierdzeń w żądaniu ściągnięcia bigbluebutton-html-plugin-sdk.
Alternatywnie możliwe jest bezpośrednie odniesienie do PR z bigbluebutton-html-plugin-sdk. (Oznacza to, że musisz najpierw wysłać PR dla tego repozytorium, a następnie PR dla bigbluebutton/bigbluebutton)
Wynikowy package.json będzie wyglądał następująco:
"dependencies": {
...
"bigbluebutton-html-plugin-sdk": "https://codeload.github.com/bigbluebutton/bigbluebutton-html-plugin-sdk/tar.gz/refs/pull/<pr-number>/head"
}
Zastąp <pr-number> rzeczywistym numerem żądania ściągnięcia.
Po dodaniu uruchom:
# From bigbluebutton-html5
npm install
Spowoduje to odpowiednią aktualizację bigbluebutton-html5/package-lock.json.
- Opublikuj gałęzie do źródła, uruchamiając
git push --set-upstream origin <branch-name>dla obu repozytoriów; - Prześlij oddzielne żądanie ściągnięcia dla każdego repozytorium (
bigbluebutton-html-plugin-sdkibigbluebutton).
9. Finalizowanie przy użyciu oficjalnej wersji SDK
Po zatwierdzeniu żądań PR:
- Opiekunowie najpierw połączą SDK PR.
- Nowa wersja zostanie opublikowana na npmjs.com (np.:
0.0.99). - Następnie zaktualizujesz
package.jsonwbigbluebutton-html5, aby używać oficjalnej wersji:
"dependencies": {
...
"bigbluebutton-html-plugin-sdk": "0.0.99"
}
- Uruchom:
npm install
- Na koniec zaktualizuj wersję SDK w następującym pliku w projekcie
bigbluebutton-web:
Plik: bigbluebutton-web/grails-app/conf/bigbluebutton.properties
html5PluginSdkVersion=0.0.99
- Teraz wprowadzasz te ostatnie zmiany, prawdopodobnie będą to po prostu:
bigbluebutton-web/grails-app/conf/bigbluebutton.properties
bigbluebutton-html5/package.json
bigbluebutton-html5/package-lock.json
- Zatwierdź zmiany etapowe i wypchnij do źródła, aby zaktualizować
bigbluebutton/bigbluebuttonPR.
Dzięki temu Twoja funkcja lub poprawka będzie gotowa do wydania. 🎉
API
Rozszerzalne obszary interfejsu użytkownika
Dla każdego z następujących rozszerzalnych obszarów interfejsu użytkownika mamy inną funkcję ustawiania dostępną poprzez pluginApi.
Pamiętaj, że chociaż każdy obszar ma swoją własną strukturę, wszystkie funkcje mają określoną strukturę argumentów i nic nie zwracają, czyli:
pluginApi.setterFunctionExample([{
objectProperty1: 'string',
objectProperty2: 123,
}])
Widzisz, jest to w zasadzie funkcja wymagająca tablicy jako argumentu, przy czym im więcej elementów wepchniesz do tej tablicy, tym więcej będziesz mieć rozszerzalnego obszaru.
Poniżej przedstawiono rozszerzalne obszary, które mamy do tej pory:
— Elementy paska akcji (przycisk, separator) — Elementy rozwijane ustawień audio (opcja, separator) — Elementy rozwijane ustawień kamery (opcja, separator) – Elementy rozwijane ustawień opcji (opcja, separator) – Elementy paska nawigacji (przycisk, informacja) – Elementy rozwijane prezentacji (opcja, separator) – Elementy paska narzędzi prezentacji (przycisk, separator, pokrętło) – Ustawienia kamery użytkownika rozwijane pozycje (opcja, separator)
- rozwijane pozycje listy użytkowników (opcja, separator)
- dodatkowe informacje o pozycji listy użytkowników (pozycja, etykieta)
- pływające elementy okna (floatingWindow)
- ogólna treść (główna, pomocnicza)
- Pomocnik aparatu użytkownika (przycisk) — Pomocnik udostępniania ekranu (przycisk) — Galeria aplikacji (pozycja, znaczek „Nowy”)
Należy pamiętać, że żadna wtyczka nie będzie ingerować w obszar rozszerzalny innej osoby. Możesz więc bez obaw ustawić wszystko, czego potrzebujesz, w określonej wtyczce.
Odznaka „Nowa” w galerii aplikacji
Ta funkcja umożliwia administratorom wyróżnianie nowych lub polecanych wtyczek poprzez wyświetlanie obok nich plakietki „Nowa” w Galerii aplikacji.
Aby włączyć tę odznakę dla konkretnej wtyczki, dodaj flagę isNew: true do jej konfiguracji w pliku settings.yml.
Przykład (settings.yml):
public:
plugins:
- name: my-plugin-name
settings:
isNew: true
Po załadowaniu klienta element „nazwa-mojej-wtyczki” automatycznie wyświetli plakietkę „Nowy” w Galerii aplikacji.
Konfigurowalne style przycisków
Dostarczone przez wtyczkę przyciski paska nawigacyjnego, paska akcji i paska narzędzi prezentacji akceptują kilka opcjonalnych pól stylu, które kontrolują kształt renderowanego przycisku. Są odczytywane, jeśli są obecne, a po pominięciu wracają do poprzednich ustawień domyślnych, więc starsze obiekty wtyczek renderują się dokładnie tak jak poprzednio (wymaga wtyczki SDK 0.0.100 lub nowszej):
color— kolor przycisku (np.primary,default). Wartość domyślna:primaryna pasku nawigacji i pasku akcji,defaultna pasku narzędzi prezentacji.circle— renderuj jako okrągłą ikonę przycisku. Domyślnie:truena pasku akcji,falsena pasku narzędzi prezentacji i pasku nawigacyjnym.hideLabel— ukryj etykietę tekstową i pokaż tylko ikonę. Domyślnie:truena pasku akcji,falsena pasku narzędzi prezentacji i pasku nawigacyjnym.size— rozmiar przycisku (sm,md,lg). Domyślnie:lgna pasku akcji,mdna pasku narzędzi prezentacji i pasku nawigacyjnym.style— wbudowany obiekt w stylu CSS zastosowany do przycisku.
Funkcje pomocnicze:
getSessionToken: zwraca token sesji użytkownika znajdujący się w adresie URL użytkownika.getJoinUrl: zwraca adres URL połączenia powiązany z parametrami przekazanymi jako argument. Ponieważ pobiera interfejs API BigBlueButton, ta metoda pobierająca jest asynchroniczna.useLocaleMessages: zwraca komunikaty do wykorzystania w funkcjach internacjonalizacji (zaleca się użyciereact-intl, jako przykład, patrz oficjalne wtyczki)logger: pluginLogger jest częścią API i może być używany jak pokazano poniżej:
export const { logger: pluginLogger } = pluginApi;
// Or in the index file:
import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk';
const uuid = document.currentScript?.getAttribute('uuid') || 'root';
export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid);
Zużycie danych w czasie rzeczywistym
- Hak
useCurrentPresentation: dostarcza informacji dotyczących aktualnej prezentacji; useLoadedUserListhook: dostarcza informacji o załadowanej liście użytkowników (wyświetlanej na ekranie);useCurrentUserhook: dostarcza informacji o bieżącym użytkowniku;- hook
useUsersBasicInfo: udostępnia informacje dotyczące wszystkich użytkowników (tylko istotne informacje: userId, nazwa i rola); Hook useLoadedChatMessages: dostarcza informacji o załadowanych wiadomościach czatu. Każda wiadomość zawierasenderUserId, a od wersji BigBlueButton 3.0.33senderRole— rolę, jaką pełnił nadawca w momencie wysłania wiadomości (pozostaje taka sama, jak była, nawet jeśli rola użytkownika zmieni się w dalszej części spotkania); HakuseCustomSubscription: dzięki temu hakowi programista może wysyłać zapytania do praktycznie wszystkiego, co może zapewnić graphql. Uwaga: Upewnij się, że w przypadku zmiany wersji BBB utworzone przez Ciebie subskrypcje niestandardowe będą działać zgodnie z oczekiwaniami.usePluginSettingshook: zapewnia wszystkie specyficzne ustawienia dotyczące bieżącej wtyczki, z której został załadowany. — hakuseTalkingIndicator: dostarcza informacji o danych głosu użytkownika, czyli o tym, kto mówi lub jest wyciszony.- Hook
useMeeting: dostarcza informacji o bieżącym spotkaniu, na którym uczestniczy użytkownik. — hakuseMeetingData: zapewnia szczegółowe dane dotyczące spotkań z obsługą projekcji, oferując większą elastyczność niżuseMeeting. - hak
useCustomQuery: podobny douseCustomSubscription, ale dla jednorazowych zapytań GraphQL, a nie subskrypcji. Uwaga: Upewnij się, że w przypadku zmiany wersji BBB niestandardowe zapytania, które wykonasz, będą działać zgodnie z oczekiwaniami. - Hook
useTimer: podaje stan timera/stopera spotkania — czy toactiveirunning, czy jest w trybiestopwatch, skonfigurowanetime,accumulateditimePassedwartości,startedAt, czy maelapsedi wybranysongTrack(wymaga wtyczki SDK0.0.104lub nowszej, dostarczanej z BigBlueButton 3.0.33).
Zatem dla tego typu haków powrót będzie przebiegał według tej samej struktury:
export interface GraphqlResponseWrapper<TData> {
loading: boolean;
data?: TData;
error?: ApolloError;
}
Mamy więc data, który jest inny dla każdego haka, dlatego jest to błąd ogólny, który zostanie ustawiony wtedy i tylko wtedy, gdy wystąpi błąd, w przeciwnym razie jest niezdefiniowany, oraz ładowanie, które informuje programistę, czy zapytanie nadal się ładuje (jest pobierane), czy nie.
Tworzenie danych w czasie rzeczywistym
useCustomMutation Hook
Hook useCustomMutation umożliwia wysyłanie danych do backendu (Postgres) przy użyciu istniejących mutacji GraphQL, z poszanowaniem uprawnień użytkownika.
Działa podobnie do useMutation klienta Apollo, zwracając funkcję wyzwalającą i obiekt wynikowy z informacją o wykonaniu mutacji. Zostaną one opisane bardziej szczegółowo poniżej.
Jedną ważną różnicą jest to, że zapytanie o mutację musi być dostarczone jako ciąg znaków. Wynika to ze sposobu, w jaki zestaw SDK komunikuje się z klientem HTML5. W konsekwencji należy jawnie zdefiniować typ argumentu variables dla funkcji wyzwalającej, jak pokazano w poniższym przykładzie.
interface MutationVariablesType {
reactionEmoji: string;
}
const [trigger, result] = pluginApi.useCustomMutation<MutationVariablesType>(`
mutation SetReactionEmoji($reactionEmoji: String!) {
userSetReactionEmoji(reactionEmoji: $reactionEmoji)
}
`);
// Later in the code, you can trigger the mutation:
trigger({
variables: {
reactionEmoji: '👏',
},
});
Należy pamiętać, że ten sam typ (MutationVariablesType) przekazany jako parametr ogólny do useCustomMutation jest także typem obiektu variables w funkcji wyzwalacza.
Obiekt result zwrócony przez hak zawiera następujące pola:
const {
called,
data,
error,
loading,
} = result;
obsługujące ten interfejs:
interface MutationResultObject {
called: boolean; // Indicates if the trigger function has been called
data?: object; // Response data after the mutation is triggered
error?: object; // Error details from the mutation execution
loading: boolean; // Whether the mutation is currently loading (triggered or in progress)
}
Teraz zobacz schemat przepływu komunikacji tego haka i działania pod maską:
sequenceDiagram
participant PLUGIN-SDK
participant HTML5
PLUGIN-SDK->>HTML5: CREATE_NEW_CUSTOM_MUTATION
HTML5->>PLUGIN-SDK: MUTATION_READY
PLUGIN-SDK->>HTML5: TRIGGER_MUTATION
HTML5->>PLUGIN-SDK: MUTATION_RESULT_SENT
Postępuj zgodnie ze schematem z pewnymi szczegółami:
- Na początku SDK wysyła
windowEvent(CREATE_NEW_CUSTOM_MUTATION) do klienta HTML5 i zaczyna czekać na aktualizację od klienta; - Jednocześnie rozpoczyna nasłuchiwanie zdarzenia
MUTATION_READY; - Gdy klient otrzyma żądanie utworzenia nowej mutacji, doda tę mutację wraz z opcjami do listy aktywnych mutacji;
- Mając pod ręką listę aktywnych mutacji, wywoła procedurę obsługi każdej mutacji, która sama utworzy mutację dla każdej z mutacji na liście;
— gdy mutacja jest tworzona w kliencie HTML5, wysyła
windowEvent(MUTATION_READY) do plugin-sdk, aby poinformować go, że jest gotowy do wyzwolenia i zaczyna nasłuchiwać zdarzenia wyzwalającego; - Gdy SDK odbierze zdarzenie
ready, tworzy funkcję wyzwalającą i udostępnia ją dla wtyczki; — teraz, gdy wtyczka uruchomi funkcję, do HTML5 zostanie wysłany komunikatwindowEvent; - HTML5 po prostu go odbiera i wykonuje, zwracając wynikowe dane dla wtyczki poprzez zdarzenie
MUTATION_RESULT_SENT.
To jest aktualna architektura tej funkcji
Wymiana danych w czasie rzeczywistym
useDataChannelhook: pozwoli to na wymianę informacji (wysyłanie i odbieranie) pomiędzy różni użytkownicy za pośrednictwem tej samej wtyczki;
Aby ten hak mógł odczytać dane z kanału danych, programista będzie mógł wybrać format, w jakim chce. Możliwe formaty opisano poniżej:
- ALL_ITEMS: Pobiera wszystkie elementy z określonego kanału danych i określonej nazwy podkanału od początku spotkania od najnowszego do najnowszego (można go użyć jako historii);
- LATEST_ITEM: Pobiera tylko najnowszy element przesłany do kanału danych w ramach określonej nazwy podkanału od początku spotkania;
- NEW_ITEMS: Pobiera nowe elementy wepchnięte do kanału danych w ramach określonej nazwy podkanału od momentu wywołania haka
useDataChannel(nie będzie wyświetlać wpisów wysłanych wcześniej do tego momentu);
Interesującą rzeczą w tym haku jest to, że jest on ogólny, więc możesz użyć niestandardowego typu, który można znaleźć nie tylko w konsumenckiej części zwracanej struktury danych, ale także w funkcjach, w których musisz określić obiekt, który ma zostać utrwalony, co oznacza, że wymusi, aby obiekt był typu, o którym wspomniałeś wcześniej (tak jest w przypadku pushEntry i replaceEntry). Przykłady użycia tego można znaleźć w próbce wtyczki kanału danych lub w większości oficjalnych. Składnię opisano poniżej:
const {
data: response, // Data that will be returned
pushEntry: pushEntryFunction, // Function to push another item to the data-channel
deleteEntry: deleteEntryFunction, // Function to delete specific item or wipe all
replaceEntry: replaceEntryFunction, // Function replace a specific item
} = useDataChannel<CustomType>(
channelName, // Defined according to what is on manifest.json
DataChannelTypes.ALL_ITEMS, // | LATEST_ITEM | NEW_ITEMS -> ALL_ITEMS is default
subChannelName = 'default', // If no subchannelName is specified, it will be 'default'
);
Wyczyszczenie wszystkich danych spowoduje usunięcie każdego elementu z określonego kanału danych w ramach określonej nazwy podkanału.
Konfiguracja kanału danych:
Nazwa kanału danych musi znajdować się w manifest.json wraz ze wszystkimi uprawnieniami do zapisu (pushPermission), aktualizacji i usuwania (replaceOrDeletePermission), patrz przykład poniżej:
{
"requiredSdkVersion": "~0.0.59",
"name": "PluginName",
"javascriptEntrypointUrl": "PluginName.js",
"dataChannels":[
{
"name": "channel-name",
"pushPermission": ["moderator","presenter"],
"replaceOrDeletePermission": ["moderator", "creator"]
}
]
}
Jeśli w tym pliku nie jest wymienione żadne pozwolenie (zapisywanie lub usuwanie), nikt nie będzie mógł wykonać tej konkretnej akcji:
pushEntryFunction ma drobny szczegół, na który należy zwrócić uwagę, możliwe jest określenie użytkowników, do których chcesz wysłać element, jeśli nie określono żadnego, wszyscy otrzymają element, np. zrobione z wyprzedzeniem:
pushEntryFunction(objectToBePushed: T, options: {
receivers?: ObjectTo[];
})
export interface ToUserId {
userId: string;
}
export interface ToRole {
role: DataChannelPushEntryFunctionUserRole;
}
export type ObjectTo = ToUserId | ToRole;
Zużycie danych przez interfejs użytkownika w czasie rzeczywistym
— hak useUiData: Spowoduje to zwrócenie określonych danych z interfejsu użytkownika w zależności od parametru używanego przez programistę. Działa podobnie jak hak useUiEvent, ale zamiast przekazywać wywołanie zwrotne jako parametr uruchamiany za każdym razem, gdy wystąpi zdarzenie, zwróci dane bezpośrednio. Należy pamiętać, że drugi parametr jest wartością domyślną, jaką przyjmie ta funkcja. Możliwe wybory:
- IntlLocaleUiDataNames.CURRENT_LOCALE;
- ChatFormUiDataNames.CURRENT_CHAT_INPUT_TEXT;
- ChatFormUiDataNames.CHAT_INPUT_IS_FOCUSED;
- Zewnętrzny wolumen wideoUiDataNames.CURRENT_VOLUME_VALUE;
- Zewnętrzny wolumen wideoUiDataNames.IS_VOLUME_MUTED;
- UserListUiDataNames.USER_LIST_IS_OPEN;
- LayoutPresentationAreaUiDataNames.CURRENT_ELEMENT;
Przykład zastosowania:
const currentLocale = pluginApi.useUiData(IntlLocaleUiDataNames.CURRENT_LOCALE, {
locale: 'en',
fallbackLocale: 'en',
});
// Do something with the currentLocale:
currentLocale.locale;
currentLocale.fallbackLocale;
Pamiętaj, że dla każdego wyliczenia potrzebny jest inny typ rezerwy jako drugi argument. W powyższym przykładzie chcemy intl, więc drugi argument będzie zgodny z przedstawioną strukturą.
Kolejną rzeczą jest to, że typ zwrotu jest dokładnie taki sam, jak wymagany jako drugi argument.
Pobieranie danych interfejsu użytkownika na żądanie
getUiDatafunkcja asynchroniczna: Zwróci określone dane z interfejsu użytkownika w zależności od parametru używanego przez programistę. W przeciwieństwie douseUiDatata funkcja nie zwraca informacji w czasie rzeczywistym w przypadku ich zmian. Zobacz aktualnie obsługiwane:- PrezentacjaWhiteboardUiDataNames.CURRENT_PAGE_SNAPSHOT;
Przykład zastosowania:
const { pngBase64 } = pluginApi.getUiData(
PresentationWhiteboardUiDataNames.CURRENT_PAGE_SNAPSHOT,
);
// Do something with the currentLocale:
console.log('This is an example fetching the base64 PNG', pngBase64);
Jak widać w przypadku useUiData, typ zwracany jest dobrze zdefiniowany przez wybrane wyliczenie (innymi słowy, nazwę danych interfejsu użytkownika). Zachęcam więc do zapoznania się z poprzednią sekcją, aby dowiedzieć się więcej na ten temat.
Polecenia interfejsu użytkownika do automatyzacji zadań w BBB
uiCommands obiekt: Zasadniczo zawiera wszystkie możliwe polecenia dostępne dla programisty do interakcji z rdzeniem interfejsu użytkownika BBB, zobacz te zaimplementowane poniżej:
- pasek akcji:
- setDisplayActionBar: funkcja decyduje o wyświetlaniu paska akcji
- kamera:
- setSelfViewDisableAllDevices: Ustawia funkcję automatycznego podglądu na wyłączoną/włączoną dla wszystkich kamer użytkownika;
- setSelfViewDisable: Wyłącza/włącza kamerę samoobserwacyjną dla określonej kamery.
- czat:
- formularz:
- otwórz: ta funkcja automatycznie otworzy boczny panel czatu. Opcjonalnie akceptuje
{chatId: string}, aby otworzyć określony czat; - fill: funkcja wypełni pole wejściowe formularza czatu przekazanego w argumencie jako
{text: string} - konferencja:
- setSpeakerLevel: funkcja ta ustawi poziom głośności głośnika (wyjście audio) konferencji na określoną liczbę z zakresu od 0 do 1;
- zewnętrzne-wideo:
- głośność:
- ustaw: ta funkcja ustawi zewnętrzną głośność wideo na określoną liczbę z zakresu od 0 do 1 (tj. 0% i);
- układ:
- zmianaEnforcedLayout: (przestarzałe) Zmienia wymuszony układ
- setEnforcedLayout: Ustawia wymuszony układ
- navBar:
- setDisplayNavBar: Ustawia displayNavBar na true (pokaż) lub false (ukryj).
- powiadomienie:
- wyślij: Ta funkcja wyśle powiadomienie do klienta o konieczności renderowania, należy pamiętać, że jest to tylko po stronie klienta. Jeśli chcesz, aby był renderowany na wielu klientach, użyj tego z kanałem danych;
- obszar prezentacji:
- open: funkcja automatycznie otwiera zawartość obszaru prezentacji;
- zamknij: funkcja automatycznie zamknie zawartość obszaru prezentacji;
- udostępnij ekran:
- stop: Zatrzymuje udostępnianie ekranu, jeśli użytkownik jest prezenterem i udostępnia ekran (w przeciwnym razie jest to ignorowane);
- kontener-opcji pomocnika: (przestarzałe - zamiast tego użyj sidekickArea)
- open: ta funkcja automatycznie otworzy panel opcji pomocnika;
- zamknij: ta funkcja automatycznie zamknie panel opcji pomocnika (oraz zawartość paska bocznego, jeśli jest otwarta, aby uniknąć niespójności w interfejsie użytkownika);
- sidekickArea:
- opcje:
- panel:
- open: funkcja ta automatycznie otworzy kontener sidekicka;
- zamknij: ta funkcja automatycznie zamknie kontener pomocnika (i panel zawartości paska bocznego);
- renameGenericContentMenu: ta funkcja zmienia nazwę menu (nazwę opcji) ogólnej zawartości dodatkowej. Jako parametry przyjmuje
id(string) inewName(string). - renameGenericContentSection: ta funkcja zmienia nazwę sekcji (sekcji, do której należy opcja) ogólnej zawartości dodatkowej. Jako parametry przyjmuje
id(string) inewName(string). - setMenuBadge: ta funkcja ustawia plakietkę w menu opcji pomocnika. Jako parametry przyjmuje
id(string) ibadgeContent(string). - usuńMenuBadge: ta funkcja usuwa odznakę z menu opcji pomocnika. Jako parametr przyjmuje
id(string); - status użytkownika:
- setAwayStatus: funkcja ta ustawia status nieobecności użytkownika na określony status;
Zobacz przyszłe wykorzystanie:
pluginApi.uiCommands.chat.form.open();
pluginApi.uiCommands.chat.form.fill({
text: 'Just an example message filled by the plugin',
});
Pomysł jest taki, że mamy obiekt uiCommands i w pewnym momencie pojawi się polecenie wykonania zamierzonej akcji, takiej jak otwarcie formularza czatu i/lub wypełnienie go, jak pokazano powyżej
Polecenia interfejsu SidekickArea
Polecenia sidekickArea umożliwiają wtyczkom kontrolowanie i dostosowywanie panelu pomocniczego oraz jego opcji zawartości. Polecenia te są szczególnie przydatne podczas pracy z ogólną zawartością pomocniczą.
Sterowanie na panelu:
// Open the sidekick container
pluginApi.uiCommands.sidekickArea.options.panel.open();
// Close the sidekick container
pluginApi.uiCommands.sidekickArea.options.panel.close();
Zarządzanie identyfikatorami:
Odznaki to wskaźniki wizualne, które można wyświetlić w opcjach menu pomocnika, aby pokazać powiadomienia lub liczniki.
// Set a badge on a sidekick menu option
pluginApi.uiCommands.sidekickArea.options.setMenuBadge(
'my-sidekick-content-id',
'5' // Badge content (e.g., notification count)
);
// Remove a badge from a sidekick menu option
pluginApi.uiCommands.sidekickArea.options.removeMenuBadge('my-sidekick-content-id');
Zmiana nazwy treści:
// Rename the menu option name
pluginApi.uiCommands.sidekickArea.options.renameGenericContentMenu(
'my-sidekick-content-id',
'New Menu Name'
);
// Rename the section that contains the menu option
pluginApi.uiCommands.sidekickArea.options.renameGenericContentSection(
'my-sidekick-content-id',
'New Section Name'
);
Kompletny działający przykład można znaleźć w sample-generic-content-sidekick-plugin w repozytorium SDK.
Polecenia serwera
serverCommands Obiekt: Zawiera wszystkie możliwe polecenia dostępne dla programisty w celu interakcji z głównym serwerem BBB, zobacz te zaimplementowane poniżej:
- czat:
- sendChatMessage: Funkcja wysyła wiadomość na konkretny czat według chatId w imieniu aktualnie zalogowanego użytkownika
- sendPublicChatMessage: Funkcja wysyła wiadomość na czat publiczny w imieniu aktualnie zalogowanego użytkownika
- sendCustomPublicMessage: Ta funkcja wysyła wiadomość tekstową na czat publiczny, opcjonalnie zawierającą niestandardowe metadane.
Uwaga: Niestandardowe wiadomości wysyłane przez wtyczki nie są automatycznie renderowane przez klienta. Aby wyświetlić te komunikaty, wtyczka musi obsługiwać renderowanie przy użyciu
useLoadedChatMessagesiuseChatMessageDomElements.
-
createPrivateChat: Ta funkcja tworzy prywatny czat z konkretnym użytkownikiem
-
podpis:
-
zapisz: funkcja zapisuje podany tekst, lokalizację i typ napisu
-
addLocale: funkcja wysyła ustawienia regionalne do dodania do dostępne opcje
-
prezentacja:
-
upload: przesyła nową prezentację do BigBlueButton;
Ponieważ te polecenia mogą zmieniać stan w back-endzie, dostępna jest „kontrola uprawnień” w zależności od roli dla niektórych poleceń (w manifeście), są to:
- czat:
- sendCustomPublicMessage;
Przykład użycia pokazano w sekcji Manifest, ale ogólnie pomysł jest taki, aby mieć podobną hierarchię jak polecenia serwera z SDK, patrz przykład dalej:
"serverCommandsPermission": {
"chat.sendCustomPublicChatMessage": ["presenter"] // Could have all the other roles, see manifest section
}
Jeśli w manifeście nie ma żadnych uprawnień, uważamy, że każdy użytkownik na spotkaniu może użyć polecenia serwera.
Manipulacja elementem Dom
- Hak
useChatMessageDomElements: Ten hak reaktywnie zwróci element domeny wiadomości czatu, dzięki czemu można modyfikować wszystko, co jest w środku, takie jak tekst, css, js itp.; — hakuseUserCameraDomElements: ten hak zwróci element dom każdej kamery internetowej użytkownika odpowiadający przekazywanym reaktywnie identyfikatorom strumienia, dzięki czemu można modyfikować wszystko, co jest w środku, takie jak tekst, css, js itp., a także można uzyskać z niego element wideo;
Integracja z pulpitem nawigacyjnym Learning Analytics
Ta integracja umożliwia wstawianie/aktualizowanie wpisów w LAD (panel narzędzi analitycznych) za pomocą funkcji upsertUserData, a także usuwanie wpisów za pomocą funkcji deleteUserData.
Jest to obiekt dostępny w pluginApi, który obejmuje te 3 funkcje:
pluginApi.learningAnalyticsDashboard.upsertUserDatapluginApi.learningAnalyticsDashboard.deleteUserDatapluginApi.learningAnalyticsDashboard.clearAllUsersData
Dla funkcji upsert struktura obiektu danych argumentu musi być następująca:
interface LearningAnalyticsDashboardUserData {
cardTitle: string;
columnTitle: string;
value: string;
}
Dla funkcji deleteUserData struktura obiektu danych argumentu musi być następująca:
interface LearningAnalyticsDashboardDeleteUserData {
cardTitle: string;
columnTitle: string;
}
Dla funkcji clearAllUsersData argumentem jest CardTitle (opcjonalnie), a w przypadku jego niewysłania wszystkie wpisy dla konkretnego pluginu zostaną usunięte. (A jeśli karta będzie pusta, zostanie usunięta)
Jeżeli użytkownik jest moderatorem, istnieje możliwość publikacji danych w imieniu innych użytkowników poprzez użycie drugiego opcjonalnego parametru o nazwie targetUserId
Dzięki temu dane pojawią się w następującej formie:
Tabela jest szersza od ekranu. Przewiń ją w poziomie.
| Użytkownik | Hrabia | <columnTitle> |
|---|---|---|
| nazwa użytkownika | 1 | <value> |
Zobacz przykład użycia w przyszłości:
const targetUserId = 'abcd-efg';
pluginApi.learningAnalyticsDashboard.upsertUserData(
{
cardTitle: 'Example Title',
columnTitle: 'link sent by user',
value: '[link](https://my-website.com/abc.png)'
},
targetUserId,
);
pluginApi.learningAnalyticsDashboard.deleteUserData(
{
cardTitle: 'Example Title',
columnTitle: 'link sent by user',
},
targetUserId,
);
pluginApi.learningAnalyticsDashboard.clearAllUsersData(columnTitle);
pluginApi.learningAnalyticsDashboard.clearAllUsersData(); // Or without the Column Title
Uwaga 1: Pole value (w argumencie funkcji upsert) obsługuje przecenę, więc możesz go używać według własnego uznania.
Uwaga 2: pluginApi.sendGenericDataForLearningAnalyticsDashboard jest obecnie przestarzały, ale ma taką samą strukturę danych jak upsert (bez możliwości wysłania wpisu w imieniu innego użytkownika)
Zewnętrzne zasoby danych
Jest to nowa integracja z serwerami zewnętrznymi umożliwiająca bezpieczne pobieranie danych.
Jest to możliwe poprzez proste skonfigurowanie nazwy dataResource w manifeście, a następnie jego punktu końcowego w metaparametrze adresu URL, który jest uwzględniany w żądaniu utworzenia. Manifest będzie wyglądał następująco:
{
// ...rest of manifest configuration
"remoteDataSources": [
{
"name": "allUsers",
"url": "${meta_pluginSettingsUserInformation}",
"fetchMode": "onMeetingCreate", // Possible values: "onMeetingCreate", "onDemand"
"permissions": ["moderator", "viewer"] // Possible values: "moderator", "viewer", "presenter"
}
]
}
Przeglądanie każdego parametru, aby lepiej zrozumieć jego strukturę:
name: Jest to nazwa zdalnego źródła danych, czyli nazwa, której będziesz później używać we wtyczce podczas jej tworzenia;url: Adres URL, na który będą pobierane dane (może być zakodowany na stałe wmanifest.json, ale zalecamy przekazanie go jako parametrumeta_);fetchMode: Informuje serwer wtyczek, czy ma pobierać dane tylko podczas tworzenia spotkania, czy za każdym razem, gdy funkcja jest wywoływana w części wtyczki; — jeśli wybierzeszonMeetingCreate, dane zostaną pobrane, gdy zostanie wywołany punkt końcowy tworzenia spotkania, a następnie zostaną zapisane w pamięci podręcznej na serwerze wtyczek, więc za każdym razem, gdy wtyczka będzie potrzebować tych danych, serwer wtyczek odpowie buforowanymi danymi;- Z drugiej strony, jeśli wybrano
onDemand, za każdym razem, gdy wtyczka wywołuje tę metodę, serwer wtyczek pobierze dane, a następnie prześle je do wtyczki; permissions: Informuje back-end, która rola spotkania może uzyskać dostęp do tych zdalnych danych;
Oto parametry /create, które należy przekazać, aby interfejs API zdalnego źródła danych działał:
meta_pluginSettingsUserInformation=https://<your-external-source-with-your-authentication>/api/users
pluginManifests=[{"url": "http://<domain-of-your-manifest>/your-plugin/manifest.json"}]
Zobacz, że wysyłamy parametr meta_, aby uzyskać więcej informacji, zapoznaj się z sekcją metaparametry
Na koniec we wtyczce użyj funkcji takiej jak:
pluginApi.getRemoteData('allUsers').then((response: Response) => {
if (response.ok) {
response.json().then((r: CourseData) => {
// Do something with the jsonified data (if it's a json)
}).catch((reason) => {
pluginLogger.error('Error while processing the json from success response: ', reason);
});
}
}).catch((reason) => {
pluginLogger.error('Error while fetching external resource: ', reason);
});
Dostosuj plik manifest.json
W poniższych sekcjach wyjaśniono, w jaki sposób można dynamicznie dostosowywać plik manifest.json do różnych uruchomień.
Meta_parametry
To nie jest część API, ale jest sposobem przekazywania informacji do manifestu. Dowolną wartość można przekazać w ten sposób, wystarczy umieścić coś takiego jak ${meta_nameOfParameter} w określonej konfiguracji manifestu, a w wywołaniu /create ustawić ten metaparametr na dowolną preferowaną wartość, np. meta_nameOfParameter="Sample message"
Ta funkcja jest używana głównie ze względów bezpieczeństwa, patrz dane zewnętrzne sekcja. Ale można go również wykorzystać do celów dostosowywania.
Parametry wtyczki
Parametry plugin_ działają podobnie do parametrów meta_, umożliwiając dynamiczne przekazywanie danych do manifestu. Chociaż mogą służyć tym samym celom — takim jak bezpieczeństwo lub dostosowywanie — ich zakres jest ograniczony do poszczególnych wtyczek.
Format:
plugin_<pluginName>_<parameter-name>
<pluginName>— Nazwa wtyczki zdefiniowana wmanifest.json.<parameter-name>— Nazwa parametru. Może zawierać litery (duże lub małe), cyfry i łączniki (-).
Ta konwencja nazewnictwa zapewnia, że każda wtyczka ma własną przestrzeń nazw dla parametrów. Inne wtyczki nie mogą uzyskać dostępu do wartości spoza ich własnej przestrzeni nazw. Na przykład:
plugin_pickRandomUserPlugin_url-to-fetch-data=https://...
Izoluje parametr od pickRandomUserPlugin i pozwala uniknąć konfliktów z innymi wtyczkami.
Wartość domyślna (zastępcza) dla brakujących parametrów symbolu zastępczego
Jeśli wtyczka oczekuje obiektu zastępczego (przez meta_ lub plugin_), ale nie otrzyma wartości, wtyczka nie zostanie załadowana. Aby temu zapobiec, oba typy symboli zastępczych obsługują wartości domyślne. Umożliwia to administratorowi systemu zdefiniowanie wartości rezerwowych, zapewniając prawidłowe załadowanie wtyczki.
Przykład z wartością domyślną (manifest.json):
{
"requiredSdkVersion": "~0.0.77",
"name": "MyPlugin",
"javascriptEntrypointUrl": "MyPlugin.js",
"localesBaseUrl": "https://cdn.domain.com/my-plugin/", // Optional
"dataChannels":[
{
"name": "${plugin_MyPlugin_data-channel-name:storeState}",
"pushPermission": ["moderator","presenter"], // "moderator","presenter", "all"
"replaceOrDeletePermission": ["moderator", "creator"] // "moderator", "presenter","all", "creator"
}
]
}
W tym przykładzie, jeśli parametr plugin_MyPlugin_data-channel-name nie zostanie podany podczas wywołania /create, powróci do "storeState".
Trwałość zdarzeń
Ta funkcja umożliwi programiście zapisanie informacji (która jest w zasadzie wydarzeniem) w pliku event.xml spotkania, jeśli jest ono nagrywane.
Aby z niego skorzystać należy najpierw dodać do swojego manifest.json następujące linie:
{
// ...rest of manifest configuration
"eventPersistence": {
"isEnabled": true
}
}
Zatem API w SDK to:
pluginApi.persistEvent(eventName: string, payloadJson: Object);
Zobacz przykład wtyczki sample-use-meeting tutaj, w tym repozytorium. Wygląda to następująco:
useEffect(() => {
setInterval(() => {
pluginLogger.info('persisting event');
pluginApi.persistEvent('eventFromUseMeetingSample', { foo: 'bar' });
}, 5000);
}, []);
Po zakończeniu spotkania (o ile zostało ono nagrane) można po prostu wykonać następujące kroki, aby zobaczyć wydarzenia:
W terminalu serwera:
sudo updatedb
vi $(locate events.xml | grep <meeting-id>)
Gdzie <meeting-id> to identyfikator właśnie nagranego spotkania. Następnie, wśród wszystkich innych zdarzeń w pliku, jeśli go przeszukasz, znajdziesz następujące:
<event timestamp="25004947" module="PLUGIN" eventname="PluginGeneratedEvent">
<payloadJson>{"foo":"bar"}</payloadJson>
<pluginEventName>eventFromUseMeetingSample</pluginEventName>
<date>2024-10-30T18:00:11.929Z</date>
<pluginName>SampleUseMeeting</pluginName>
<userId>w_sxlfjbcb0yxs</userId>
<timestampUTC>1730311211929</timestampUTC>
</event>
Wytyczne
W tej sekcji opisano dobre praktyki tworzenia wtyczek. Są one obowiązkowe w przypadku oficjalnych wtyczek opracowanych przez organizację BBB i jej partnerów w celu zachowania niezawodności, bezpieczeństwa i odpowiedzialności.
Wytyczne dotyczące manipulacji elementami Dom
Ponieważ wtyczki są ładowane bezpośrednio do klienta, nie ma żadnych ograniczeń technicznych uniemożliwiających programistom dowolne manipulowanie elementami DOM. Jednakże zdecydowanie zalecamy przestrzeganie poniższych praktyk:
- Jeśli to możliwe, manipuluj elementami za pomocą haków dostarczonych przez dom-element-manipulation;
- Jeśli potrzebna Ci funkcjonalność nie jest dostępna, utwórz problem w repozytorium SDK lub sprawdź, czy jeden z obszarów rozszerzalnych będzie w stanie spełnić Twoje potrzeby;
- Nigdy nie edytuj bezpośrednio treści wiadomości na czacie (nawet przy manipulacji DOM). Obecnie odtwarzanie części BBB z nagraniami nie obsługuje wtyczek ani rozszerzeń. Wszelkie zmiany wprowadzone w wiadomościach czatu na żywo (takie jak dodanie lub usunięcie słów) nie zostaną odzwierciedlone w nagraniu, co prowadzi do niespójności i potencjalnych problemów z odpowiedzialnością.
Aby podkreślić: Nie zmieniaj treści wiadomości czatu. Może to spowodować poważne problemy z niezawodnością i odpowiedzialnością.
Zamiast tego dostarczony hak może służyć do modyfikowania sposobu prezentowania wiadomości — na przykład zmieniając styl w celu podkreślenia określonych słów, renderując specjalny układ dla wiadomości typu „powiadomienie” (podobny do wiadomości „zmień prezentera”), a nawet wyświetlając zarówno oryginalny tekst wiadomości, jak i dodatkowe, niestandardowo renderowane elementy interfejsu użytkownika.
Lokalizacja
Plugin SDK udostępnia funkcję useLocaleMessages opisaną w sekcji funkcje pomocnicze. Chociaż jego użycie nie jest obowiązkowe, zdecydowanie go zalecamy, ponieważ obsługuje pewne przypadki brzegowe, które w innym przypadku byłyby trudne do przewidzenia.
Gorąco zachęcamy także programistów do włączania lokalizacji do swoich wtyczek. To znacznie poprawia przyjęcie i użyteczność w społeczności.
Jako praktyczny przykład zobacz, jak wtyczka pick-random-user wykorzystuje ją w haku useGetInternationalization.
Często zadawane pytania (FAQ)
Jak usunąć pewien obszar rozszerzalny, którego już nie chcę? To całkiem proste: wystarczy ustawić pustą tablicę elementów tego konkretnego obszaru rozszerzalnego. Lub po prostu usuń konkretny element tablicy i ustaw nową tablicę na ten rozszerzalny obszar w następnej iteracji.
Patrz przykład poniżej:
// First iteration:
// Define both variables:
const dropdownToUserListItem = { ... };
const buttonToUserListItem = { ... };
pluginApi.setActionsBarItems([dropdownToUserListItem, buttonToUserListItem]);
// Second iteration:
// Redefine variable(s):
const newButtonToUserListItem = { ... };
pluginApi.setActionsBarItems([newButtonToUserListItem]);
// Third iteration:
// I don't want any of this extensible-area:
pluginApi.setActionsBarItems([]);
// All set from this plugin will disappear from the UI;
Jak poprawnie zbudować wtyczkę? Wystarczy przejść do folderu z wtyczkami, zainstalować zależności i uruchomić komendę budowania w następujący sposób:
cd my-plugin-folder/
npm i
npm run build-bundle
W tym momencie w katalogu wtyczek zostanie utworzony kolejny folder o nazwie „dist/”. Wewnątrz tego folderu znajdziesz samą wtyczkę MyPlugin.js. Pamiętaj, że nazwa tego pliku będzie taka sama jak zdefiniowana w webpack.config.js, np.:
module.exports = {
// ... Other configurations
output: {
filename: 'MyPlugin.js'
}
// ... Other configurations
}
Czy zbudowana wtyczka musi znajdować się na tym samym serwerze BBB?
Nie, możesz hostować ją gdziekolwiek chcesz, pamiętaj tylko o poprawnym wskazaniu adresu URL z manifest.json (do punktu końcowego tworzenia lub bigbluebutton.properties).
Tworzę wtyczkę w oparciu o próbkę z SDK, ale jakoś próbka nie działa poprawnie. Co mam zrobić, aby uruchomić ją w trybie deweloperskim i sprawić, by działała? Istnieje kilka powodów, dla których próbka nie działa poprawnie, więc omówię pokrótce każdy z nich:
- Konfiguracja nie została poprawnie ustawiona w
manifest.json, zobacz tę sekcję, aby skonfigurować wtyczkę; - Wtyczka nie działa nawet w trybie deweloperskim, może to być port już używany lub błędy maszynopisu i/lub javascriptu (pamiętaj o zainicjowaniu
pluginApijako dowolny przykład wewnątrz komponentu funkcji reakcji); - Może to rzeczywiście być błąd w tym przykładzie lub funkcja, której używa wtyczka, jest zepsuta (nie jest to normalne, ale może się zdarzyć, ponieważ BBB stale zmienia i ulepsza swoje funkcje dzięki swojej wspaniałej społeczności). Jeśli tak się stanie, po prostu otwórz problem w githubie pakietu SDK, szczegółowo opisując napotkany błąd. Z góry dziękujemy za zgłoszenie nam problemu, abyśmy mogli za każdym razem udoskonalać nasze działania.
Jak rozwiązywać problemy z wtyczkami? Sprawdź na przykład, czy został załadowany do BBB. Cóż, za każdym razem, gdy zestaw wtyczek ma zostać uruchomiony podczas określonego spotkania, uruchomi się kilka dzienników w oparciu o liczbę wtyczek, które należy załadować do klienta. Zatem otwórz konsolę w przeglądarce wciskając klawisz F12 na klawiaturze i wyszukaj następujący log:
<ratio of loaded plugins> plugins loaded
Jeśli zostanie załadowana 1 z 5 wtyczek, zobaczysz komunikat „Załadowano 1/5 wtyczek” i tak dalej.
Ponadto, gdy wtyczka zostanie załadowana, klient zarejestruje jej nazwę w następujący sposób:
Loaded plugin MyPlugin
Czasami może się zdarzyć, że wtyczka nie załaduje się prawidłowo i zostanie zarejestrowany błąd z następującym komunikatem:
Error when loading plugin MyPlugin, error: {"isTrusted":true}
W tym przypadku adres URL prowadzący do wtyczki jest niedostępny lub prowadzi do błędu. Może jednak zarejestrować coś innego, więc zwróć uwagę na to, co powie Ci komunikat o błędzie.
Istnieją oczywiście inne scenariusze i różne dzienniki informacyjne, ale te są najpowszechniejsze i najważniejsze. Skontaktuj się z nami, jeśli uważasz, że coś pominęliśmy!