← Cloudflare Realtime / realtime / realtimekit / ui-kit
Vytváření vlastního UI
Tento návod vysvětluje, jak pomocí komponent RealtimeKit UI Kit vytvořit vlastní rozhraní schůzky namísto výchozího zobrazení schůzky na celou obrazovku.
Předpoklady
Tato stránka navazuje na Inicializujte SDK, Vykreslit výchozí uživatelské rozhraní schůzky, a Stavy UI Kit průvodců. Nejprve si projděte tyto stránky, abyste porozuměli základním konceptům.
Příklady kódu na této stránce předpokládají, že jste již importovali potřebné balíčky a inicializovali SDK.
Vytváření vlastního UI pomocí UI Kit
Pokud výchozí komponenta schůzky neposkytuje dostatečnou kontrolu nad rozvržením nebo chováním, použijte komponenty UI Kit k vytvoření vlastního rozhraní. UI Kit poskytuje předpřipravené komponenty nad Core SDK. Jednotlivé části můžete kombinovat podle potřeby a ušetřit tak čas oproti stavbě od nuly.
Vlastní uživatelské rozhraní vyžaduje, abyste sami spravovali zvuk účastníků, oznámení, dialogy, rozložení komponent a přechody mezi obrazovkami.
Podobně jako rtk-meeting, rtk-ui-provider, další komponenta UI Kit, která funguje jako provider, také naslouchá stavy a synchronizuje je s komponentami UI Kit.
Na rozdíl od rtk-meeting, rtk-ui-provider umožňuje předávat mu libovolné podřízené komponenty. Pokud je některá podřízená komponenta komponentou RealtimeKit začínající na rtk-, rtk-ui-provider se s ním zkoordinuje a synchronizuje stavy.
Podobně jako RtkMeeting, RtkUiProvider, další komponenta UI Kit, která funguje jako provider, také naslouchá stavy a synchronizuje je s komponentami UI Kit.
Na rozdíl od RtkMeeting, RtkUiProvider umožňuje předávat mu libovolné podřízené komponenty. Pokud je některá podřízená komponenta komponentou RealtimeKit začínající na Rtk, RtkUiProvider se s ním zkoordinuje a synchronizuje stavy.
Podobně jako rtk-meeting, rtk-ui-provider, další komponenta UI Kit, která funguje jako provider, také naslouchá stavy a synchronizuje je s komponentami UI Kit.
Na rozdíl od rtk-meeting, rtk-ui-provider umožňuje předávat mu libovolné podřízené komponenty. Pokud je některá podřízená komponenta komponentou RealtimeKit začínající na rtk-, rtk-ui-provider se s ním zkoordinuje a synchronizuje stavy.
iOS SDK používá vzor delegování pro vlastní uživatelská rozhraní. Místo obalení podřízených zobrazení do provideru implementujte RtkUIFlowCoordinatorDelegate a vraťte vlastní view controllery pro každou obrazovku v průběhu schůzky.
K dispozici jsou dvě úrovně přizpůsobení:
- Nahraďte celé obrazovky, Odpovídá
RtkUIFlowCoordinatorDelegatea vraťte vlastníUIViewControllerpro obrazovku nastavení, obrazovku skupinového hovoru nebo obrazovku webináře. Vraťtenilk použití výchozí obrazovky. - Nahraďte dílčí komponenty, Odpovídá
MeetingViewControllerDataSourcea vyměňte horní lištu, střední zobrazení (mřížku účastníků) nebo spodní ovládací lištu v rámci výchozíMeetingViewController.
public protocol RtkUIFlowCoordinatorDelegate {
func showSetUpScreen(completion: () -> Void) -> SetupViewControllerDataSource?
func showGroupCallMeetingScreen(meeting: RealtimeKitClient, completion: @escaping () -> Void) -> UIViewController?
func showWebinarMeetingScreen(meeting: RealtimeKitClient, completion: @escaping () -> Void) -> UIViewController?
}Jakmile se uživatel úspěšně připojí, SDK zavolá showGroupCallMeetingScreen(meeting:completion:) nebo showWebinarMeetingScreen(meeting:completion:). Použijte RealtimeKitClient parametr pro propojení jednotlivých komponent UI Kit (například RtkMeetingHeaderView, RtkMeetingControlBar, nebo RtkParticipantTileView) do schůzky.
Android SDK nepoužívá vzor provider/wrapper. Místo toho má každá jednotlivá komponenta View activate(meeting) metoda, která ji naváže na schůzku.
Vzor je:
- Vytvořte
RealtimeKitUIinstanci sRealtimeKitUIBuilder.build(). - Přistupte k
RealtimeKitClientprostřednictvímrtkUI.meeting. - Jednotlivé views z UI Kit umístěte do vlastního XML layoutu, nebo je vytvořte v kódu.
- Zavolejte
activate(meeting)na každou komponentu, abyste ji propojili se schůzkou.
Komponenty na úrovni Meeting (mřížka, hlavička, ovládací lišta) přijímají RealtimeKitClient:
gridView.activate(meeting)
headerView.activate(meeting)
controlBarView.activate(meeting)Komponenty na úrovni účastníka (dlaždice, avatar, jmenovka) přijímají RtkMeetingParticipant:
tileView.activate(meeting.localUser)
tileView.activate(remoteParticipant)Podobně jako RtkMeeting, RtkUIProvider je obalová komponenta, která všem podřízeným komponentám poskytuje kontext designového systému a stavu uživatelského rozhraní.
Na rozdíl od RtkMeeting, RtkUIProvider umožňuje předávat mu libovolné podřízené komponenty. Všechny komponenty RealtimeKit UI Kit čtou z RtkUIContext pro designové tokeny a stav.
Použijte useContext(RtkUIContext) a přečíst tak storeStates.meeting a určete, jakou obrazovku vykreslit. Při vytváření bez RtkMeeting, musíte naslouchat událostem SDK a zavolat setStates a řídit tak přechody stavů sami.
Příklad kódu
<!DOCTYPE html>
<html>
<head>
<script type="module">
import { defineCustomElements } from "https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit-ui@latest/loader/index.es2017.js";
defineCustomElements();
</script>
<script src="https://cdn.jsdelivr.net/npm/@cloudflare/realtimekit@latest/dist/browser.js"></script>
</head>
<body style="margin: 0;">
<rtk-ui-provider
id="rtk-ui-provider"
style="display: flex; flex-direction: column; height: 100vh; margin: 0;"
>
<div
id="meeting-container"
style="display: flex; flex-direction: column; flex: 1; flex-grow: 1; flex-shrink: 1;"
>
Meeting will render here...
</div>
<rtk-participants-audio></rtk-participants-audio>
<rtk-dialog-manager></rtk-dialog-manager>
<rtk-notifications></rtk-notifications>
</rtk-ui-provider>
<script type="module">
async function initializeMeeting() {
let currentState = "idle";
const meeting = await RealtimeKitClient.init({
authToken: "participant_auth_token",
});
function renderSetupScreen() {
document.querySelector("#meeting-container").innerHTML = `
<rtk-setup-screen></rtk-setup-screen>
`;
}
function renderWaitingScreen() {
document.querySelector("#meeting-container").innerHTML = `
<rtk-waiting-screen></rtk-waiting-screen>
`;
}
function renderJoinedScreen() {
document.querySelector("#meeting-container").innerHTML = `
<rtk-header style="display: flex; justify-content: space-between;"></rtk-header>
<rtk-stage style="flex: 1; flex-grow: 1; flex-shrink: 1;">
<rtk-grid></rtk-grid>
<rtk-sidebar style="position: fixed; top:0px;"></rtk-sidebar>
</rtk-stage>
<rtk-controlbar style="display: flex; justify-content: space-between;"></rtk-controlbar>
`;
}
function renderEndedScreen() {
document.querySelector("#meeting-container").innerHTML = `
<rtk-ended-screen></rtk-ended-screen>
`;
}
// Listen for state updates from rtk-ui-provider
document
.querySelector("rtk-ui-provider")
.addEventListener("rtkStatesUpdate", (event) => {
// Store states to update your custom UI
const states = event.detail;
if (states.meeting === "idle" && currentState !== "idle") {
currentState = "idle";
document
.querySelector("rtk-ui-provider")
.querySelector("#meeting-container").innerHTML =
"Meeting is loading...";
} else if (states.meeting === "setup" && currentState !== "setup") {
currentState = "setup";
renderSetupScreen();
} else if (
states.meeting === "waiting" &&
currentState !== "waiting"
) {
currentState = "waiting";
renderWaitingScreen();
} else if (
states.meeting === "joined" &&
currentState !== "joined"
) {
currentState = "joined";
renderJoinedScreen();
} else if (states.meeting === "ended" && currentState !== "ended") {
currentState = "ended";
renderEndedScreen();
}
const sidebarComponent = document
.querySelector("rtk-ui-provider")
.querySelector("#meeting-container")
.querySelector("rtk-sidebar");
if (sidebarComponent) {
if (states.activeSidebar) {
sidebarComponent.style.display = "block";
} else {
sidebarComponent.style.display = "none";
}
}
});
document.querySelector("rtk-ui-provider").showSetupScreen = true;
document.querySelector("rtk-ui-provider").meeting = meeting;
}
initializeMeeting();
</script>
</body>
</html>Rozdělení první úrovně rtk-meeting pomocí rtk-ui-provider má následující komponenty:
rtk-header je komponenta header, která zobrazuje název relace a její ovládací prvky.
rtk-stage je kontejnerová komponenta, která obsahuje komponenty grid a sidebar.
rtk-grid je komponenta grid, která zobrazuje účastníky relace.
rtk-sidebar je komponenta sidebar, která zobrazuje postranní panel, v němž se zobrazuje obsah chatu a anket.
rtk-controlbar je komponenta controlbar, která zobrazuje ovládací prvky, jako je kamera, mikrofon a podobně.
rtk-notifications je komponenta notifications, která zobrazuje oznámení pro relaci.
rtk-participants-audio je audio komponenta, která vám umožňuje poslouchat ostatní účastníky relace.
rtk-dialog-manager je komponenta dialog-manager, která zobrazuje všechny podporované dialogy, jako jsou nastavení, breakout rooms a podobně.
Všechny tyto komponenty můžete dále rozdělit. Další podobné komponenty najdete v knihovna komponent.
Náš UI Kit je open source a najdete ho na GitHubu, konkrétně zde ↗.
import {
RealtimeKitProvider,
useRealtimeKitClient,
} from "@cloudflare/realtimekit-react";
import {
RtkUiProvider,
RtkHeader,
RtkStage,
RtkGrid,
RtkSidebar,
RtkControlbar,
RtkNotifications,
RtkParticipantsAudio,
RtkDialogManager,
RtkSetupScreen,
RtkWaitingScreen,
RtkEndedScreen,
States,
} from "@cloudflare/realtimekit-react-ui";
import { useEffect, useState } from "react";
function MeetingContainer() {
const [meeting, initMeeting] = useRealtimeKitClient();
const [currentState, setCurrentState] = useState("idle");
const [showSidebar, setShowSidebar] = useState(false);
useEffect(() => {
initMeeting({
authToken: "participant_auth_token",
});
}, []);
const renderSetupScreen = () => {
return <RtkSetupScreen />;
};
const renderWaitingScreen = () => {
return <RtkWaitingScreen />;
};
const renderJoinedScreen = () => {
return (
<>
<RtkHeader
style={{ display: "flex", justifyContent: "space-between" }}
/>
<RtkStage style={{ flex: 1, flexGrow: 1, flexShrink: 1 }}>
<RtkGrid />
<RtkSidebar
style={{
position: "fixed",
top: "0px",
display: showSidebar ? "block" : "none",
}}
/>
</RtkStage>
<RtkControlbar
style={{ display: "flex", justifyContent: "space-between" }}
/>
</>
);
};
const renderEndedScreen = () => {
return <RtkEndedScreen />;
};
// Listen for state updates from RtkUiProvider
const handleStatesUpdate = (event: { detail: States }) => {
const meetingState = event.detail.meeting;
const states = event.detail;
// Store states to update your custom UI
if (meetingState === "idle" && currentState !== "idle") {
setCurrentState("idle");
} else if (meetingState === "setup" && currentState !== "setup") {
setCurrentState("setup");
} else if (meetingState === "waiting" && currentState !== "waiting") {
setCurrentState("waiting");
} else if (meetingState === "joined" && currentState !== "joined") {
setCurrentState("joined");
} else if (meetingState === "ended" && currentState !== "ended") {
setCurrentState("ended");
}
// Update sidebar visibility based on state
if (states.activeSidebar !== undefined) {
setShowSidebar(states.activeSidebar);
}
};
return (
<RealtimeKitProvider value={meeting}>
<RtkUiProvider
meeting={meeting}
showSetupScreen={true}
onRtkStatesUpdate={handleStatesUpdate}
style={{
display: "flex",
flexDirection: "column",
height: "100vh",
margin: 0,
}}
>
<div
id="meeting-container"
style={{
display: "flex",
flexDirection: "column",
flex: 1,
flexGrow: 1,
flexShrink: 1,
}}
>
{currentState === "idle" && <div>Meeting is loading...</div>}
{currentState === "setup" && renderSetupScreen()}
{currentState === "waiting" && renderWaitingScreen()}
{currentState === "joined" && renderJoinedScreen()}
{currentState === "ended" && renderEndedScreen()}
</div>
<RtkParticipantsAudio />
<RtkDialogManager />
<RtkNotifications />
</RtkUiProvider>
</RealtimeKitProvider>
);
}
function App() {
return <MeetingContainer />;
}Rozdělení první úrovně RtkMeeting pomocí RtkUiProvider má následující komponenty:
RtkHeader je komponenta header, která zobrazuje název relace a její ovládací prvky.
RtkStage je kontejnerová komponenta, která obsahuje komponenty grid a sidebar.
RtkGrid je komponenta grid, která zobrazuje účastníky relace.
RtkSidebar je komponenta sidebar, která zobrazuje postranní panel, v němž se zobrazuje obsah chatu a anket.
RtkControlbar je komponenta controlbar, která zobrazuje ovládací prvky, jako je kamera, mikrofon a podobně.
RtkNotifications je komponenta notifications, která zobrazuje oznámení pro relaci.
RtkParticipantsAudio je audio komponenta, která vám umožňuje poslouchat ostatní účastníky relace.
RtkDialogManager je komponenta dialog-manager, která zobrazuje dialogy pro danou relaci.
Všechny tyto komponenty můžete dále rozdělit. Další podobné komponenty najdete v knihovna komponent.
Náš UI Kit je open source a najdete ho na GitHubu, konkrétně zde ↗.
V souboru app.module.ts importujte RealtimeKitComponentsModule spolu se všemi vlastními moduly, které jste vytvořili pomocí knihovny komponent (příklad je uveden níže).
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
import { CustomRtkMeetingComponent } from "./components/custom-rtk-meeting.component";
import { SetupScreenComponent } from "./components/setup-screen.component";
import { InMeetingComponent } from "./components/in-meeting.component";
import { MeetingHeaderComponent } from "./components/meeting-header.component";
import { MeetingControlBarComponent } from "./components/meeting-control-bar.component";
import { MeetingSidebarComponent } from "./components/meeting-sidebar.component";
import { MediaPreviewModalComponent } from "./components/media-preview-modal.component";
import { AudioPreviewComponent } from "./components/audio-preview.component";
import { VideoPreviewComponent } from "./components/video-preview.component";
import { RealtimeKitComponentsModule } from "@cloudflare/realtimekit-angular-ui";
@NgModule({
declarations: [
AppComponent,
CustomRtkMeetingComponent,
SetupScreenComponent,
InMeetingComponent,
MeetingHeaderComponent,
MeetingControlBarComponent,
MeetingSidebarComponent,
MediaPreviewModalComponent,
AudioPreviewComponent,
VideoPreviewComponent,
],
imports: [BrowserModule, FormsModule, RealtimeKitComponentsModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}Inicializujte schůzku v souboru app.component.ts
import { Component, OnInit, Inject } from "@angular/core";
import { DOCUMENT } from "@angular/common";
import { StatesService } from "./services/states.service";
import RealtimeKitClient from "@cloudflare/realtimekit";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
})
export class AppComponent implements OnInit {
meeting: any = null;
constructor(
private statesService: StatesService,
@Inject(DOCUMENT) private document: Document,
) {}
async ngOnInit() {
await this.initializeMeeting();
}
private async initializeMeeting() {
const searchParams = new URLSearchParams(
this.document.defaultView?.location.search,
);
const authToken = searchParams.get("authToken");
if (!authToken) {
alert(
"An authToken wasn't passed, please pass an authToken in the URL query to join a meeting.",
);
return;
}
if (!this.meeting) {
try {
// Initialize RealtimeKit client
const meeting = await RealtimeKitClient.init({
authToken,
});
this.meeting = meeting;
// Expose meeting object to window for debugging
Object.assign(this.document.defaultView as any, {
meeting: this.meeting,
});
} catch (error) {
console.error("Failed to initialize meeting:", error);
}
}
}
onRtkStatesUpdate(event: any) {
this.statesService.setStates(event.detail);
}
}<rtk-ui-provider
[meeting]="meeting"
(rtkStatesUpdate)="onRtkStatesUpdate($event)"
[showSetupScreen]="true"
style="height: 100%; width: 100%; display: block;"
>
<app-custom-rtk-meeting></app-custom-rtk-meeting>
<rtk-dialog-manager></rtk-dialog-manager>
</rtk-ui-provider>Zde je příklad, jak může vypadat vlastní element vytvořený pomocí komponent UI Kit:
import { Component, OnInit, OnDestroy } from "@angular/core";
import { Subject, takeUntil } from "rxjs";
import { StatesService, CustomStatesService } from "../services/states.service";
import { States } from "@cloudflare/realtimekit-ui";
import { CustomStates } from "../types";
@Component({
selector: "app-custom-rtk-meeting",
template: `
<rtk-idle-screen *ngIf="states.meeting === 'idle'"></rtk-idle-screen>
<app-setup-screen *ngIf="states.meeting === 'setup'"></app-setup-screen>
<rtk-waiting-screen
*ngIf="states.meeting === 'waiting'"
></rtk-waiting-screen>
<rtk-ended-screen *ngIf="states.meeting === 'ended'"></rtk-ended-screen>
<app-in-meeting
*ngIf="states.meeting === 'joined' || !states.meeting"
></app-in-meeting>
`,
})
export class CustomRtkMeetingComponent implements OnInit, OnDestroy {
states: States = { meeting: "idle" } as States;
customStates: CustomStates = {};
private destroy$ = new Subject<void>();
constructor(
private statesService: StatesService,
private customStatesService: CustomStatesService,
) {}
ngOnInit() {
this.statesService.states$
.pipe(takeUntil(this.destroy$))
.subscribe((states) => {
this.states = states;
console.log(states, this.customStates);
});
this.customStatesService.customStates$
.pipe(takeUntil(this.destroy$))
.subscribe((customStates) => {
this.customStates = customStates;
console.log(this.states, customStates);
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}Rozdělení první úrovně rtk-meeting pomocí rtk-ui-provider má následující komponenty:
rtk-header je komponenta header, která zobrazuje název relace a její ovládací prvky.
rtk-stage je kontejnerová komponenta, která obsahuje komponenty grid a sidebar.
rtk-grid je komponenta grid, která zobrazuje účastníky relace.
rtk-sidebar je komponenta sidebar, která zobrazuje postranní panel, v němž se zobrazuje obsah chatu a anket.
rtk-controlbar je komponenta controlbar, která zobrazuje ovládací prvky, jako je kamera, mikrofon a podobně.
rtk-notifications je komponenta notifications, která zobrazuje oznámení pro relaci.
rtk-participants-audio je audio komponenta, která vám umožňuje poslouchat ostatní účastníky relace.
rtk-dialog-manager je komponenta dialog-manager, která zobrazuje všechny podporované dialogy, jako jsou nastavení, breakout rooms a podobně.
Všechny tyto komponenty můžete dále rozdělit. Další podobné komponenty najdete v knihovna komponent.
Náš UI Kit je open source a najdete ho na GitHubu, konkrétně zde ↗.
Následující příklad nahrazuje obrazovku skupinového hovoru vlastním view controllerem, který používá jednotlivé komponenty UI Kitu:
import UIKit
import RealtimeKit
import RealtimeKitUI
class CustomFlowDelegate: RtkUIFlowCoordinatorDelegate {
// Return nil to use the default setup screen
func showSetUpScreen(completion: () -> Void) -> SetupViewControllerDataSource? {
return nil
}
// Return a custom view controller for group calls
func showGroupCallMeetingScreen(
meeting: RealtimeKitClient,
completion: @escaping () -> Void
) -> UIViewController? {
return CustomMeetingViewController(meeting: meeting, completion: completion)
}
// Return nil to use the default webinar screen
func showWebinarMeetingScreen(
meeting: RealtimeKitClient,
completion: @escaping () -> Void
) -> UIViewController? {
return nil
}
}
class CustomMeetingViewController: UIViewController {
private let meeting: RealtimeKitClient
private let completion: () -> Void
private var selfListener: RtkEventSelfListener?
init(meeting: RealtimeKitClient, completion: @escaping () -> Void) {
self.meeting = meeting
self.completion = completion
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) { fatalError("init(coder:) not supported") }
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
// Header
let header = RtkMeetingHeaderView(meeting: meeting)
header.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(header)
// Control bar
let controlBar = RtkMeetingControlBar(
meeting: meeting,
delegate: nil,
presentingViewController: self
)
controlBar.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controlBar)
NSLayoutConstraint.activate([
header.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
header.leadingAnchor.constraint(equalTo: view.leadingAnchor),
header.trailingAnchor.constraint(equalTo: view.trailingAnchor),
header.heightAnchor.constraint(equalToConstant: 50),
controlBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
controlBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
controlBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
controlBar.heightAnchor.constraint(equalToConstant: 80),
])
// Listen for meeting events
selfListener = RtkEventSelfListener(rtkClient: meeting)
selfListener?.observeSelfRemoved { [weak self] _ in
self?.dismiss(animated: true, completion: self?.completion)
}
selfListener?.observeSelfMeetingEndForAll { [weak self] _ in
self?.dismiss(animated: true, completion: self?.completion)
}
}
}Zobrazte schůzku pomocí vlastního flow delegate:
let delegate = CustomFlowDelegate()
let rtkUI = RealtimeKitUI(
meetingInfo: RtkMeetingInfo(
authToken: "<auth-token>",
enableAudio: true,
enableVideo: true
),
flowDelegate: delegate
)
let controller = rtkUI.startMeeting {
self.dismiss(animated: true)
}
controller.modalPresentationStyle = .fullScreen
present(controller, animated: true)Jednotlivé komponenty dostupné pro vlastní obrazovky schůzky:
| Komponenta | Popis |
|---|---|
RtkMeetingHeaderView |
Záhlaví s názvem schůzky, počtem účastníků, hodinami a indikátorem nahrávání |
RtkMeetingControlBar |
Ovládací lišta s tlačítky pro mikrofon, kameru a ukončení schůzky |
RtkParticipantTileView |
Video dlaždice jediného účastníka se záložním avatarem a jmenovkou |
RtkVideoView |
Zobrazení pro vykreslování nezpracovaného videa |
RtkAvatarView |
Avatar účastníka s iniciálami |
RtkNameTag |
Jméno účastníka s ikonou stavu mikrofonu |
RtkAudioButtonControlBar |
Samostatné tlačítko přepínače mikrofonu |
RtkVideoButtonControlBar |
Samostatné tlačítko přepínače kamery |
RtkEndMeetingControlBarButton |
Tlačítko pro ukončení nebo opuštění schůzky |
RtkEventSelfListener |
Observer pro stav zvuku/videa, odebrání, opětovné připojení a oprávnění |
Následující příklad vytváří vlastní obrazovku schůzky pomocí jednotlivých zobrazení UI Kitu v XML rozvržení s activate(meeting) vzor:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#000000">
<com.cloudflare.realtimekit.ui.view.headers.RtkMeetingHeaderView
android:id="@+id/headerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.cloudflare.realtimekit.ui.view.grid.RtkGridView
android:id="@+id/gridView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.cloudflare.realtimekit.ui.view.controlbars.RtkMeetingControlBarView
android:id="@+id/controlBarView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.cloudflare.realtimekit.RealtimeKitClient
import com.cloudflare.realtimekit.RtkMeetingRoomEventListener
import com.cloudflare.realtimekit.models.RtkMeetingInfo
import com.cloudflare.realtimekit.ui.RealtimeKitUIBuilder
import com.cloudflare.realtimekit.ui.RealtimeKitUIInfo
import com.cloudflare.realtimekit.ui.view.controlbars.RtkMeetingControlBarView
import com.cloudflare.realtimekit.ui.view.grid.RtkGridView
import com.cloudflare.realtimekit.ui.view.headers.RtkMeetingHeaderView
class CustomMeetingActivity : AppCompatActivity() {
private lateinit var headerView: RtkMeetingHeaderView
private lateinit var gridView: RtkGridView
private lateinit var controlBarView: RtkMeetingControlBarView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_custom_meeting)
headerView = findViewById(R.id.headerView)
gridView = findViewById(R.id.gridView)
controlBarView = findViewById(R.id.controlBarView)
val meetingInfo = RtkMeetingInfo(authToken = "<auth-token>")
val uiKitInfo = RealtimeKitUIInfo(
activity = this,
rtkMeetingInfo = meetingInfo,
)
val rtkUI = RealtimeKitUIBuilder.build(uiKitInfo)
val meeting: RealtimeKitClient = rtkUI.meeting
// Listen for meeting lifecycle events
meeting.addMeetingRoomEventListener(object : RtkMeetingRoomEventListener {
override fun onMeetingRoomJoinCompleted(meeting: RealtimeKitClient) {
runOnUiThread {
// Activate all components once the meeting is joined
headerView.activate(meeting)
gridView.activate(meeting)
controlBarView.activate(meeting)
}
}
override fun onMeetingEnded() {
finish()
}
override fun onMeetingRoomLeaveCompleted() {
finish()
}
})
}
}Jednotlivé komponenty dostupné pro vlastní rozvržení:
| Komponenta | Aktivujte pomocí | Popis |
|---|---|---|
RtkGridView |
RealtimeKitClient |
Stránkovaná mřížka videí účastníků |
RtkMeetingHeaderView |
RealtimeKitClient |
Záhlaví s názvem, počtem účastníků, hodinami a indikátorem nahrávání |
RtkMeetingControlBarView |
RealtimeKitClient |
Ovládací lišta s tlačítky pro mikrofon, kameru, další možnosti a opuštění schůzky |
RtkParticipantTileView |
RtkMeetingParticipant |
Video dlaždice jediného účastníka s avatarem a jmenovkou |
RtkMicToggleButton |
RealtimeKitClient |
Samostatný přepínač mikrofonu |
RtkCameraToggleButton |
RealtimeKitClient |
Samostatný přepínač kamery |
RtkLeaveButton |
RealtimeKitClient |
Tlačítko pro opuštění/ukončení schůzky |
RtkAvatarView |
RtkMeetingParticipant |
Avatar účastníka |
RtkNameTagView |
RtkMeetingParticipant |
Name tag with audio indicator |
RtkJoinButton |
RealtimeKitClient |
Tlačítko pro připojení ke schůzce na obrazovkách nastavení |
Následující příklad používá RtkUIProvider a jednotlivé komponenty se stavově řízeným vykreslováním obrazovek, podobně jako u webového vzoru React:
import React, { useContext, useEffect } from "react";
import { View, Text } from "react-native";
import {
useRealtimeKitClient,
RealtimeKitProvider,
} from "@cloudflare/realtimekit-react-native";
import {
RtkUIProvider,
RtkUIContext,
RtkHeader,
RtkGrid,
RtkControlbar,
RtkSidebar,
RtkDialogManager,
RtkSetupScreen,
RtkWaitingScreen,
RtkEndedScreen,
} from "@cloudflare/realtimekit-react-native-ui";
function MeetingScreens({ meeting }) {
const { storeStates, setStates } = useContext(RtkUIContext);
const currentState = storeStates.meeting;
useEffect(() => {
// Listen for meeting events and drive state transitions
const onRoomJoined = () => {
setStates({ ...storeStates, meeting: "joined" });
};
const onRoomLeft = ({ state }) => {
if (state === "ended" || state === "left") {
setStates({ ...storeStates, meeting: "ended" });
}
};
meeting.self.addListener("roomJoined", onRoomJoined);
meeting.self.addListener("roomLeft", onRoomLeft);
return () => {
meeting.self.removeListener("roomJoined", onRoomJoined);
meeting.self.removeListener("roomLeft", onRoomLeft);
};
}, [meeting]);
if (currentState === "setup") {
return <RtkSetupScreen meeting={meeting} />;
}
if (currentState === "waiting") {
return <RtkWaitingScreen />;
}
if (currentState === "joined") {
return (
<View style={{ flex: 1 }}>
<RtkHeader meeting={meeting} />
<View style={{ flex: 1 }}>
<RtkGrid meeting={meeting} />
{storeStates.activeSidebar && <RtkSidebar meeting={meeting} />}
</View>
<RtkControlbar meeting={meeting} />
<RtkDialogManager meeting={meeting} />
</View>
);
}
if (currentState === "ended") {
return <RtkEndedScreen meeting={meeting} />;
}
return <Text>Loading...</Text>;
}
function CustomMeeting({ authToken }) {
const [meet, initMeeting] = useRealtimeKitClient();
const { setStates, storeStates } = useContext(RtkUIContext);
useEffect(() => {
initMeeting({
authToken,
defaults: { audio: true, video: true },
});
}, [authToken]);
useEffect(() => {
if (meet) {
setStates({ ...storeStates, meeting: "setup" });
}
}, [meet]);
if (!meet) return <Text>Initializing...</Text>;
return (
<RealtimeKitProvider value={meet}>
<MeetingScreens meeting={meet} />
</RealtimeKitProvider>
);
}
export default function App() {
return (
<RtkUIProvider>
<CustomMeeting authToken="<auth-token>" />
</RtkUIProvider>
);
}Rozdělení první úrovně RtkMeeting má následující komponenty:
| Komponenta | Povinný prop | Popis |
|---|---|---|
RtkHeader |
meeting |
Záhlaví s názvem schůzky, počtem účastníků, hodinami a indikátorem nahrávání |
RtkGrid |
meeting |
Stránkovaná mřížka videí účastníků |
RtkControlbar |
meeting |
Ovládací lišta s přepínači pro mikrofon, kameru, sdílení obrazovky a další možnosti |
RtkSidebar |
meeting |
Postranní panel s panely chatu, anket, účastníků a doplňků |
RtkDialogManager |
meeting |
Spravuje všechna dialogová okna (nastavení, potvrzení odchodu, vstup na pódium) |
RtkSetupScreen |
meeting |
Obrazovka před připojením s náhledem videa a výběrem zařízení |
RtkWaitingScreen |
, | Obrazovka čekárny |
RtkEndedScreen |
meeting |
Obrazovka ukončení schůzky |
RtkMicToggle |
meeting |
Samostatné tlačítko přepínače mikrofonu |
RtkCameraToggle |
meeting |
Samostatné tlačítko přepínače kamery |
RtkLeaveButton |
, | Tlačítko pro opuštění/ukončení schůzky |
RtkParticipantTile |
meeting, participant |
Video dlaždice jediného účastníka |
RtkNotifications |
meeting |
Toastová oznámení o připojení, odchodu a chatových událostech |