BigBlueButton.plNiezależny serwis po polsku

Wtyczki

Mechanizm wtyczek, SDK, konfiguracja manifestów i przykłady rozszerzeń klienta.

Tłumaczenie automatyczne 4.0 Stan źródeł:
Ilustracja rozdziału: Wtyczki
Ilustracja z repozytorium dokumentacji BigBlueButton, tag v4.0.0. Niektóre obrazy źródłowe przedstawiają starszy interfejs. Źródło ilustracji.

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

  1. Uruchom serwer deweloperski:

    cd $HOME/src/bigbluebutton-html-plugin-sdk/samples/sample-action-button-dropdown-plugin
    npm install
    npm start
    
  2. Dodaj odniesienie do niego w wywołaniu /create BigBlueButton 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ć:

  1. Załóż konto na https://ngrok.com/ (Oficjalna strona NGROK);

  2. Zainstaluj NGROK na swoim komputerze. Mają na to przewodnik zaraz po utworzeniu konta;

  3. Uruchom serwer rozwoju wtyczki:

cd $HOME/src/plugin-pick-random-user-plugin
npm install
npm start
  1. 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

  1. 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:

  • /create Parametr pluginManifests – Dotyczy tylko tworzonego spotkania. Musisz wyraźnie wymienić wtyczki w żądaniu.
  • parametr /create pluginManifestsFetchUrl – 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.
  • pluginManifests w /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-sdk używaną przez bigbluebutton-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 z 1.0 (np.: 1 dla 1.0.0-beta.3 i dla 1.2.0), Major + Minor dla wersji 0.x, gdzie każdy Minor jest zmianą przełomową (np.: 0.1 dla 0.1.26) - używany przez bigbluebutton-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.0 dla 3.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:

  1. Weryfikacja: Zapewnia, że wszystkie wymagane ustawienia są dostępne dla wtyczki. Jeśli brakuje któregoś z wymaganych ustawień, wtyczka nie zostanie załadowana.
  2. 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 integrity w znaczniku <script>, ale nie ustawia atrybutu crossorigin. Przeglądarki wymagają zarówno integrity, jak i crossorigin="anonymous" (plus nagłówki CORS z serwera) do kontroli SRI skryptów pochodzących z różnych źródeł. Bez crossorigin sprawdzenie 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.

Plugin template GitHub page showing where to click


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.json
  • webpack.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 obecnie 0.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.

  • setOptionsDropdownItems dodaje nowy przycisk do menu rozwijanego. — moduł obsługi onClick uruchamia 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.

  1. 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-web pobiera 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 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.

  1. Wykonaj fork repozytorium bigbluebutton-html-plugin-sdk;
  2. Utwórz rozwidlenie repozytorium główny bigbluebutton;
  3. 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-sdk
  • bigbluebutton

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-html5 nie podawaj jeszcze numeru wersji pakietu SDK w package.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-sdk i bigbluebutton).

9. Finalizowanie przy użyciu oficjalnej wersji SDK

Po zatwierdzeniu żądań PR:

  1. Opiekunowie najpierw połączą SDK PR.
  2. Nowa wersja zostanie opublikowana na npmjs.com (np.: 0.0.99).
  3. Następnie zaktualizujesz package.json w bigbluebutton-html5, aby używać oficjalnej wersji:
"dependencies": {
  ...
  "bigbluebutton-html-plugin-sdk": "0.0.99"
}
  1. Uruchom:
npm install
  1. 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

  1. 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
  1. Zatwierdź zmiany etapowe i wypchnij do źródła, aby zaktualizować bigbluebutton/bigbluebutton PR.

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.

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: primary na pasku nawigacji i pasku akcji, default na pasku narzędzi prezentacji.
  • circle — renderuj jako okrągłą ikonę przycisku. Domyślnie: true na pasku akcji, false na pasku narzędzi prezentacji i pasku nawigacyjnym.
  • hideLabel — ukryj etykietę tekstową i pokaż tylko ikonę. Domyślnie: true na pasku akcji, false na pasku narzędzi prezentacji i pasku nawigacyjnym.
  • size — rozmiar przycisku (sm, md, lg). Domyślnie: lg na pasku akcji, md na 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życie react-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;
  • useLoadedUserList hook: dostarcza informacji o załadowanej liście użytkowników (wyświetlanej na ekranie);
  • useCurrentUser hook: 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ść zawiera senderUserId, a od wersji BigBlueButton 3.0.33 senderRole — 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); Hak
  • useCustomSubscription: 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.
  • usePluginSettings hook: zapewnia wszystkie specyficzne ustawienia dotyczące bieżącej wtyczki, z której został załadowany. — hak useTalkingIndicator: 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. — hak useMeetingData: zapewnia szczegółowe dane dotyczące spotkań z obsługą projekcji, oferując większą elastyczność niż useMeeting.
  • hak useCustomQuery: podobny do useCustomSubscription, 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 to active i running, czy jest w trybie stopwatch, skonfigurowane time, accumulated i timePassed wartości, startedAt, czy ma elapsed i wybrany songTrack (wymaga wtyczki SDK 0.0.104 lub 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 komunikat windowEvent;
  • 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

  • useDataChannel hook: 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

  • getUiData funkcja asynchroniczna: Zwróci określone dane z interfejsu użytkownika w zależności od parametru używanego przez programistę. W przeciwieństwie do useUiData ta 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) i newName (string).
  • renameGenericContentSection: ta funkcja zmienia nazwę sekcji (sekcji, do której należy opcja) ogólnej zawartości dodatkowej. Jako parametry przyjmuje id (string) i newName (string).
  • setMenuBadge: ta funkcja ustawia plakietkę w menu opcji pomocnika. Jako parametry przyjmuje id (string) i badgeContent (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 useLoadedChatMessages i useChatMessageDomElements.

  • 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.; — hak useUserCameraDomElements: 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.upsertUserData
  • pluginApi.learningAnalyticsDashboard.deleteUserData
  • pluginApi.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 w manifest.json, ale zalecamy przekazanie go jako parametru meta_);
  • 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 wybierzesz onMeetingCreate, 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 w manifest.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 pluginApi jako 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!