Live Share Kernfunktionen
Das Live Share SDK kann mit minimalem Aufwand den sidePanel
und meetingStage
Kontexten Ihrer Besprechungserweiterung hinzugefügt werden. Sie können das SDK auch in Chat- und Kanalkontexten content
wie konfigurierbaren Registerkarten, statischen Registerkarten und der Phasenansicht für die Zusammenarbeit verwenden.
Hinweis
Live Share-Kontexte content
in Chats und Kanälen werden nur auf Teams-Desktop- und Webclients unterstützt.
Dieser Artikel konzentriert sich auf die Integration des Live Share SDK in Ihre App und wichtige Funktionen des SDK.
Voraussetzungen
Installieren des JavaScript SDK
Das Live Share SDK ist ein JavaScript-Paket, das auf npm veröffentlicht wird und sie über npm oder yarn herunterladen können. Sie müssen auch Live Share-Peerabhängigkeiten installieren, einschließlich fluid-framework
und @fluidframework/azure-client
. Wenn Sie Live Share in Ihrer Registerkartenanwendung verwenden, müssen Sie auch version 2.23.0
oder höher installieren@microsoft/teams-js
. Wenn Sie die -Klasse für die TestLiveShareHost
lokale Browserentwicklung verwenden möchten, müssen Sie und start-server-and-test
-Pakete in Ihrer devDependencies
installieren@fluidframework/test-client-utils
.
NPM
npm install @microsoft/live-share fluid-framework @fluidframework/azure-client --save
npm install @microsoft/teams-js --save
npm install @fluidframework/test-client-utils start-server-and-test --save-dev
Yarn
yarn add @microsoft/live-share fluid-framework @fluidframework/azure-client
yarn add @microsoft/teams-js
yarn add @fluidframework/test-client-utils -dev
Registrieren von RSC-Berechtigungen
Um das Live Share SDK für Ihre Registerkartenerweiterung zu aktivieren, müssen Sie ihrem App-Manifest zunächst die folgenden RSC-Berechtigungen hinzufügen:
{
// ...rest of your manifest here
"configurableTabs": [
{
"configurationUrl": "<<YOUR_CONFIGURATION_URL>>",
"canUpdateConfiguration": true,
"scopes": [
"groupchat",
"team"
],
"context": [
// meeting contexts
"meetingSidePanel",
"meetingStage",
// content contexts
"privateChatTab",
"channelTab",
"meetingChatTab"
]
}
],
"validDomains": [
"<<BASE_URI_ORIGIN>>"
],
"authorization": {
"permissions": {
"resourceSpecific": [
// ...other permissions here
{
"name": "LiveShareSession.ReadWrite.Chat",
"type": "Delegated"
},
{
"name": "LiveShareSession.ReadWrite.Group",
"type": "Delegated"
},
{
"name": "MeetingStage.Write.Chat",
"type": "Delegated"
},
{
"name": "ChannelMeetingStage.Write.Group",
"type": "Delegated"
}
]
}
}
}
Teilnehmen an einer Sitzung
Führen Sie die Schritte aus, um an einer Sitzung teilzunehmen, die der Besprechung, dem Chat oder kanal eines Benutzers zugeordnet ist:
- Initialisieren Sie
LiveShareClient
. - Definieren der vertraulichen Daten, die Sie schützen möchten. Zum Beispiel
LiveState
oderSharedMap
. - Dem Container beitreten.
Beispiel:
import { LiveShareClient, LiveState } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: {
liveState: LiveState,
sharedMap: SharedMap,
},
};
const { container } = await liveShare.joinContainer(schema);
// ... ready to start app sync logic
Das ist alles, was sie benötigt haben, um Ihren Container einzurichten und an der Sitzung teilzunehmen, die der Besprechung, dem Chat oder dem Kanal zugeordnet ist. Sehen wir uns nun die verschiedenen Arten von verteilten Datenstrukturen an, die Sie mit dem Live Share SDK verwenden können.
Tipp
Stellen Sie sicher, dass das Teams Client SDK initialisiert ist, bevor Sie aufrufen LiveShareHost.create()
.
Live Share-Datenstrukturen
Das Live Share SDK enthält eine Reihe neuer verteilter Datenstrukturen, die die Fluid-Klasse erweitern und neue Typen von zustandsbehafteten und zustandslosen DataObject
Objekten bereitstellen. Im Gegensatz zu Fluid-Datenstrukturen schreiben die Live Share-Klassen LiveDataObject
keine Änderungen an den Fluid-Container, was eine schnellere Synchronisierung ermöglicht. Darüber hinaus wurden diese Kurse von Grund auf für gängige Szenarien in Teams-Besprechungen, Chats und -Kanälen entwickelt. Häufige Szenarien sind die Synchronisierung der Inhalte, die der Referent anzeigt, das Anzeigen von Metadaten für jeden Benutzer in der Sitzung oder das Anzeigen eines Countdowntimers.
Live-Objekt | Beschreibung |
---|---|
LivePresence | Sehen Sie, welche Benutzer online sind, legen Sie benutzerdefinierte Eigenschaften für jeden Benutzer fest, und übertragen Sie Änderungen an ihren Anwesenheitsinformationen. |
LiveState | Synchronisieren Sie einen beliebigen serialisierbaren state JSON-Wert. |
LiveTimer | Synchronisieren sie einen Countdowntimer für ein bestimmtes Intervall. |
LiveEvent | Übertragen einzelner Ereignisse mit benutzerdefinierten Datenattributen in der Nutzlast. |
LiveFollowMode | Folgen Sie bestimmten Benutzern, präsentieren Sie alle Benutzer in der Sitzung, und starten oder beenden Sie das Anhalten. |
LivePresence-Beispiel
Die LivePresence
-Klasse macht die Nachverfolgung der Sitzungsteilnehmer einfacher als je zuvor. Wenn Sie die -Methode oder .updatePresence()
die .initialize()
-Methode aufrufen, können Sie diesem Benutzer benutzerdefinierte Metadaten zuweisen, z. B. profilbild, den Bezeichner für angezeigte Inhalte und vieles mehr. Durch das Lauschen auf presenceChanged
Ereignisse empfängt jeder Client das neueste LivePresenceUser
-Objekt, wobei alle Anwesenheitsaktualisierungen in einen einzelnen Datensatz für jede eindeutige userId
unterteilt werden.
Im Folgenden finden Sie einige Beispiele, die LivePresence
in Ihrer Anwendung verwendet werden können:
- Abrufen von Microsoft Teams
userId
,displayName
undroles
jedes Benutzers in der Sitzung. - Anzeigen benutzerdefinierter Informationen zu jedem Benutzer, der mit der Sitzung verbunden ist, z. B. eine Profilbild-URL.
- Synchronisieren der Koordinaten in einer 3D-Szene, in der sich der Avatar jedes Benutzers befindet.
- Melden der Cursorposition jedes Benutzers in einem Textdokument.
- Veröffentlichen der Antwort jedes Benutzers auf eine Eisbrecherfrage während einer Gruppenaktivität.
import {
LiveShareClient,
LivePresence,
PresenceState,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: {
presence: LivePresence,
},
};
const { container } = await liveShare.joinContainer(schema);
const presence = container.initialObjects.presence;
// Register listener for changes to each user's presence.
// This should be done before calling `.initialize()`.
presence.on("presenceChanged", (user, local) => {
console.log("A user presence changed:");
console.log("- display name:", user.displayName);
console.log("- state:", user.state);
console.log("- custom data:", user.data);
console.log("- change from local client", local);
console.log("- change impacts local user", user.isLocalUser);
});
// Define the initial custom data for the local user (optional).
const customUserData = {
picture: "DEFAULT_PROFILE_PICTURE_URL",
readyToStart: false,
};
// Start receiving incoming presence updates from the session.
// This will also broadcast the user's `customUserData` to others in the session.
await presence.initialize(customUserData);
// Send a presence update, in this case once a user is ready to start an activity.
// If using role verification, this will throw an error if the user doesn't have the required role.
await presence.update({
...customUserData,
readyToStart: true,
});
Benutzer, die einer Sitzung von einem einzelnen Gerät beitreten, verfügen über einen einzelnen LivePresenceUser
Datensatz, der für alle ihre Geräte freigegeben wird. Um auf die neuesten data
und state
für jede ihrer aktiven Verbindungen zuzugreifen, können Sie die getConnections()
API aus der LivePresenceUser
-Klasse verwenden. Dadurch wird eine Liste von LivePresenceConnection
-Objekten zurückgegeben. Mithilfe der -Eigenschaft können Sie sehen, ob eine bestimmte LivePresenceConnection
Instanz vom lokalen Gerät isLocalConnection
stammt.
Jede LivePresenceUser
- und LivePresenceConnection
-Instanz verfügt über eine state
-Eigenschaft, die entweder online
, offline
oder away
sein kann. Ein presenceChanged
Ereignis wird ausgegeben, wenn sich der Zustand eines Benutzers ändert. Wenn ein Benutzer beispielsweise die Verbindung mit der Sitzung trennt oder die Anwendung schließt, ändert sich sein Zustand in offline
.
Hinweis
Es kann bis zu 20 Sekunden dauern, bis eine LivePresenceUser
-Datei state
auf aktualisiert wird offline
, nachdem ein Benutzer die Verbindung mit der Sitzung getrennt hat.
LiveState-Beispiel
Die LiveState
-Klasse ermöglicht die Synchronisierung des einfachen Anwendungszustands für verbundene Teilnehmer.
LiveState
synchronisiert einen einzelnen state
Wert, sodass Sie jeden serialisierbaren JSON-Wert string
wie , number
oder object
synchronisieren können.
Im Folgenden finden Sie einige Beispiele, die LiveState
in Ihrer Anwendung verwendet werden können:
- Festlegen der Benutzer-ID des aktuellen Referenten zum Erstellen einer Funktion zum Übernehmen von Steuerelementen .
- Synchronisieren des aktuellen Routenpfads für Ihre Anwendung, um sicherzustellen, dass sich alle auf derselben Seite befinden. Beispiel:
/whiteboard/:whiteboardId
. - Beibehalten des Inhaltsbezeichners, den der aktuelle Referent anzeigt. Beispiel: ein
taskId
in einem Taskboard. - Synchronisieren des aktuellen Schritts in einer mehrrunden Gruppenaktivität. Zum Beispiel die Ratephase während des Agile Poker-Spiels.
- Synchronisieren einer Bildlaufposition für ein "Follow me "-Feature.
Hinweis
Im Gegensatz zu SharedMap
wird der state
Wert in LiveState
zurückgesetzt, nachdem alle Benutzer die Verbindung mit einer Sitzung getrennt haben.
Beispiel:
import { LiveShareClient, LiveState } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: { appState: LiveState },
};
const { container } = await liveShare.joinContainer(schema);
const { appState } = container.initialObjects;
// Register listener for changes to the state.
// This should be done before calling `.initialize()`.
appState.on("stateChanged", (planetName, local, clientId) => {
// Update app with newly selected planet.
// See which user made the change (optional)
const clientInfo = await appState.getClientInfo(clientId);
});
// Set a default value and start listening for changes.
// This default value will not override existing for others in the session.
const defaultState = "Mercury";
await appState.initialize(defaultState);
// `.set()` will change the state for everyone in the session.
// If using role verification, this will throw an error if the user doesn't have the required role.
await appState.set("Earth");
LiveEvent-Beispiel
LiveEvent
ist eine hervorragende Möglichkeit, einfache Ereignisse an andere verbundene Clients zu senden, die nur zum Zeitpunkt der Übermittlung benötigt werden. Dies ist nützlich für Szenarien wie das Senden von Sitzungsbenachrichtigungen oder das Implementieren benutzerdefinierter Reaktionen.
import { LiveEvent, LiveShareClient } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: { customReactionEvent: LiveEvent },
};
const { container } = await liveShare.joinContainer(schema);
const { customReactionEvent } = container.initialObjects;
// Register listener to receive events sent through this object.
// This should be done before calling `.initialize()`.
customReactionEvent.on("received", async (kudosReaction, local, clientId) => {
console.log("Received reaction:", kudosReaction, "from clientId", clientId);
// See which user made the change (optional)
const clientInfo = await customReactionEvent.getClientInfo(clientId);
// Display notification in your UI
});
// Start listening for incoming events
await customReactionEvent.initialize();
// `.send()` will send your event value to everyone in the session.
// If using role verification, this will throw an error if the user doesn't have the required role.
const kudosReaction = {
emoji: "❤️",
forUserId: "SOME_OTHER_USER_ID",
};
await customReactionEvent.send(kudosReaction);
LiveTimer-Beispiel
LiveTimer
stellt einen einfachen Countdown-Timer bereit, der für alle verbundenen Teilnehmer synchronisiert wird. Es ist nützlich für Szenarien mit einem Zeitlimit, z. B. einem Gruppenmeditationstimer oder einem runden Timer für ein Spiel. Sie können es auch verwenden, um Aufgaben für alle Benutzer in der Sitzung zu planen, z. B. das Anzeigen einer Erinnerungsaufforderung.
import { LiveShareClient, LiveTimer } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: { timer: LiveTimer },
};
const { container } = await liveShare.joinContainer(schema);
const { timer } = container.initialObjects;
// Register listeners for timer changes
// This should be done before calling `.initialize()`.
// Register listener for when the timer starts its countdown
timer.on("started", (config, local) => {
// Update UI to show timer has started
});
// Register listener for when a paused timer has resumed
timer.on("played", (config, local) => {
// Update UI to show timer has resumed
});
// Register listener for when a playing timer has paused
timer.on("paused", (config, local) => {
// Update UI to show timer has paused
});
// Register listener for when a playing timer has finished
timer.on("finished", (config) => {
// Update UI to show timer is finished
});
// Register listener for the timer progressed by 20 milliseconds
timer.on("onTick", (milliRemaining) => {
// Update UI to show remaining time
});
// Start synchronizing timer events for users in session
await timer.initialize();
// Start a 60 second timer for users in the session.
// If using role verification, this will throw an error if the user doesn't have the required role.
const durationInMilliseconds = 1000 * 60;
await timer.start(durationInMilliseconds);
// Pause the timer for users in session
// If using role verification, this will throw an error if the user doesn't have the required role.
await timer.pause();
// Resume the timer for users in session
// If using role verification, this will throw an error if the user doesn't have the required role.
await timer.play();
LiveFollowMode-Beispiel
Die LiveFollowMode
-Klasse kombiniert LivePresence
und LiveState
in einer einzigen Klasse, sodass Sie follower- und presenter-Modi problemlos in Ihre Anwendung implementieren können. Auf diese Weise können Sie vertraute Muster aus beliebten Apps für die Zusammenarbeit wie PowerPoint Live, Excel Live und Whiteboard implementieren. Im Gegensatz zur Bildschirmfreigabe LiveFollowMode
können Sie Inhalte mit hoher Qualität, verbesserter Barrierefreiheit und verbesserter Leistung rendern. Benutzer können ganz einfach zwischen ihren privaten Ansichten wechseln und anderen Benutzern folgen.
Sie können die startPresenting()
-Funktion verwenden, um die Kontrolle über die Anwendung für alle anderen Benutzer in der Sitzung zu übernehmen. Alternativ können Sie benutzern mithilfe der -Funktion erlauben, bestimmte Benutzer einzeln auszuwählen, denen followUser()
sie folgen möchten. In beiden Szenarien können Benutzer vorübergehend eine private Ansicht mit der beginSuspension()
Funktion eingeben oder mit endSuspension()
der Funktion mit dem Referenten synchronisieren. In der Zwischenzeit ermöglicht die update()
Funktion dem lokalen Benutzer, andere Clients in der Sitzung über ihren eigenen persönlichen stateValue
zu informieren. Ähnlich LivePresence
wie können Sie änderungen an jedem Benutzer stateValue
über einen presenceChanged
Ereignislistener überwachen.
LiveFollowMode
macht auch ein state
-Objekt verfügbar, das je nach Benutzer, dem der lokale Benutzer folgt, dynamisch aktualisiert wird. Wenn der lokale Benutzer z. B. niemandem folgt, entspricht die state.value
-Eigenschaft dem zuletzt stateValue
über update()
übertragenen lokalen Benutzer. Wenn der lokale Benutzer jedoch einem Referenten folgt, entspricht die state.value
-Eigenschaft dem aktuellen stateValue
des präsentierenden Benutzers.
LiveState
Ähnlich wie können Sie änderungen am state
Wert mithilfe eines stateChanged
Ereignislisteners überwachen. Weitere Informationen zum -Objekt finden Sie unter Referenz zur state
IFollowModeState-Schnittstelle.
Im Folgenden finden Sie einige Beispiele, in denen Sie in Ihrer Anwendung verwenden LiveFollowMode
können:
- Synchronisieren Sie Kamerapositionen in einer 3D-Szene, um während einer Entwurfsüberprüfung zusammenzubrowsen.
- Aktualisieren Sie ,
slideId
um in einem Karussell für produktive Präsentationen und Diskussionen zu öffnen. - Übertragen Sie die , um im
path
Router Ihrer Anwendung zu öffnen.
Beispiel:
import {
LiveShareClient,
LiveFollowMode,
FollowModeType,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: {
followMode: LiveFollowMode,
},
};
const { container } = await liveShare.joinContainer(schema);
const followMode = container.initialObjects.followMode;
// As an example, we will assume there is a button in the application document
const button = document.getElementById("action-button");
// As an example, we will assume there is a div with text showing the follow state
const infoText = document.getElementById("info-text");
// Register listener for changes to the `state` value to use in your app.
// This should be done before calling `.initialize()`.
followMode.on("stateChanged", (state, local, clientId) => {
console.log("The state changed:");
console.log("- state value:", state.value);
console.log("- follow mode type:", state.type);
console.log("- following user id:", state.followingUserId);
console.log(
"- count of other users also following user",
state.otherUsersCount
);
console.log(
"- state.value references local user's stateValue",
state.isLocalValue
);
// Can optionally get the relevant user's presence object
const followingUser = followMode.getUserForClient(clientId);
switch (state.type) {
case FollowModeType.local: {
// Update app to reflect that the user isn't following anyone and there is no presenter.
infoText.innerHTML = "";
// Show a "Start presenting" button in your app.
button.innerHTML = "Start presenting";
button.onclick = followMode.startPresenting;
// Note: state.isLocalValue will be true.
break;
}
case FollowModeType.activeFollowers: {
// Update app to reflect that the local user is being followed by other users.
infoText.innerHTML = `${state.otherUsersCount} users are following you`;
// Does not mean that the local user is presenting to everyone, so you can still show the "Start presenting" button.
button.innerHTML = "Present to all";
button.onclick = followMode.startPresenting;
// Note: state.isLocalValue will be true.
break;
}
case FollowModeType.activePresenter: {
// Update app to reflect that the local user is actively presenting to everyone.
infoText.innerHTML = `You are actively presenting to everyone`;
// Show a "Stop presenting" button in your app.
button.innerHTML = "Stop presenting";
button.onclick = followMode.stopPresenting;
// Note: state.isLocalValue will be true.
break;
}
case FollowModeType.followPresenter: {
// The local user is following a remote presenter.
infoText.innerHTML = `${followingUser?.displayName} is presenting to everyone`;
// Show a "Take control" button in your app.
button.innerHTML = "Take control";
button.onclick = followMode.startPresenting;
// Note: state.isLocalValue will be false.
break;
}
case FollowModeType.suspendFollowPresenter: {
// The local user is following a remote presenter but has an active suspension.
infoText.innerHTML = `${followingUser?.displayName} is presenting to everyone`;
// Show a "Sync to presenter" button in your app.
button.innerHTML = "Sync to presenter";
button.onclick = followMode.endSuspension;
// Note: state.isLocalValue will be true.
break;
}
case FollowModeType.followUser: {
// The local user is following a specific remote user.
infoText.innerHTML = `You are following ${followingUser?.displayName}`;
// Show a "Stop following" button in your app.
button.innerHTML = "Stop following";
button.onclick = followMode.stopFollowing;
// Note: state.isLocalValue will be false.
break;
}
case FollowModeType.suspendFollowUser: {
// The local user is following a specific remote user but has an active suspension.
infoText.innerHTML = `You were following ${followingUser?.displayName}`;
// Show a "Resume following" button in your app.
button.innerHTML = "Resume following";
button.onclick = followMode.endSuspension;
// Note: state.isLocalValue will be true.
break;
}
default: {
break;
}
}
const newCameraPosition = state.value;
// TODO: apply new camera position
});
// Register listener for changes to each user's personal state updates.
// This should be done before calling `.initialize()`.
followMode.on("presenceChanged", (user, local) => {
console.log("A user presence changed:");
console.log("- display name:", user.displayName);
console.log("- state value:", user.data?.stateValue);
console.log("- user id user is following:", user.data?.followingUserId);
console.log("- change from local client", local);
console.log("- change impacts local user", user.isLocalUser);
// As an example, we will assume there is a button for each user in the session.
document.getElementById(`follow-user-${user.userId}-button`).onclick = () => {
followMode.followUser(user.userId);
};
// Update 3D scene to reflect this user's camera position (e.g., orb + display name)
const userCameraPosition = user.data?.stateValue;
});
// Define the initial stateValue for the local user (optional).
const startingCameraPosition = {
x: 0,
y: 0,
z: 0,
};
// Start receiving incoming presence updates from the session.
// This will also broadcast the user's `startingCameraPosition` to others in the session.
await followMode.initialize(startingCameraPosition);
// Example of an event listener for a camera position changed event.
// For something like a camera change event, you should use a debounce function to prevent sending updates too frequently.
// Note: it helps to distinguish changes initiated by the local user (e.g., drag mouse) separately from other change events.
function onCameraPositionChanged(position, isUserAction) {
// Broadcast change to other users so that they have their latest camera position
followMode.update(position);
// If the local user changed the position while following another user, we want to suspend.
// Note: helps to distinguish changes initiated by the local user (e.g., drag mouse) separately from other change events.
if (!isUserAction) return;
switch (state.type) {
case FollowModeType.followPresenter:
case FollowModeType.followUser: {
// This will trigger a "stateChanged" event update for the local user only.
followMode.beginSuspension();
break;
}
default: {
// No need to suspend for other types
break;
}
}
}
In meetingStage
Kontexten arbeiten Ihre Benutzer synchron zusammen und präsentieren sie, um produktivere Diskussionen zu ermöglichen. Wenn ein Benutzer Inhalte in der Besprechungsphase präsentiert, sollten Sie die startPresenting()
API für den ursprünglichen Referenten aufrufen. In content
Kontexten wie der kollaborativen Stageview werden Inhalte am häufigsten asynchron genutzt. In diesem Fall ist es am besten, Benutzern die Möglichkeit zu geben, sich für die Zusammenarbeit in Echtzeit zu entscheiden, z. B. über eine Schaltfläche "Folgen". Mithilfe der teamsJs.app.getContext()
API im Teams JavaScript SDK können Sie Ihre Funktionalität ganz einfach entsprechend anpassen.
Beispiel:
import {
LiveShareClient,
LiveFollowMode,
FollowModeType,
} from "@microsoft/live-share";
import {
app,
meeting,
FrameContexts,
LiveShareHost,
} from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: {
followMode: LiveFollowMode,
},
};
const { container } = await liveShare.joinContainer(schema);
const followMode = container.initialObjects.followMode;
// Get teamsJs context
const context = await app.getContext();
// Take control if in meetingStage context and local user is initial presenter
if (context.page?.frameContext === FrameContexts.meetingStage) {
// Take control if in meetingStage context and local user is initial presenter
meeting.getAppContentStageSharingState((error, state) => {
const isShareInitiator = state?.isShareInitiator;
if (!isShareInitiator) return;
// The user is the initial presenter, so we "take control"
await followMode.startPresenting();
});
}
// TODO: rest of app logic
Rollenüberprüfung für Livedatenstrukturen
Besprechungen in Teams umfassen Anrufe, Besprechungen mit allen Händen und Onlineunterricht. Besprechungsteilnehmer können organisationsübergreifend sein, über unterschiedliche Berechtigungen verfügen oder unterschiedliche Ziele verfolgen. Daher ist es wichtig, die Berechtigungen verschiedener Benutzerrollen während Besprechungen zu respektieren. Liveobjekte sind so konzipiert, dass sie die Rollenüberprüfung unterstützen, sodass Sie die Rollen definieren können, die nachrichten für jedes einzelne Liveobjekt senden dürfen. Sie haben beispielsweise die Option ausgewählt, mit der nur Besprechungsreferenten und Organisatoren die Videowiedergabe steuern können. Gäste und Teilnehmer können jedoch weiterhin die nächsten Videos zum Ansehen anfordern.
Hinweis
Wenn Sie über einen content
Chat- oder Kanalkontext auf Live Share zugreifen, verfügen alle Benutzer über die Organizer
Rollen und Presenter
.
Im folgenden Beispiel, in dem nur Referenten und Organisatoren die Kontrolle übernehmen können, wird verwendet, LiveState
um zu synchronisieren, welcher Benutzer der aktive Referent ist:
import {
LiveShareClient,
LiveState,
UserMeetingRole,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: { appState: LiveState },
};
const { container } = await liveShare.joinContainer(schema);
const { appState } = container.initialObjects;
// Register listener for changes to state
appState.on("stateChanged", (state, local) => {
// Update local app state
});
// Set roles who can change state and start listening for changes
const initialState = {
documentId: "INITIAL_DOCUMENT_ID",
};
const allowedRoles = [UserMeetingRole.organizer, UserMeetingRole.presenter];
await appState.initialize(initialState, allowedRoles);
async function onSelectEditMode(documentId) {
try {
await appState.set({
documentId,
});
} catch (error) {
console.error(error);
}
}
async function onSelectPresentMode(documentId) {
try {
await appState.set({
documentId,
presentingUserId: "LOCAL_USER_ID",
});
} catch (error) {
console.error(error);
}
}
Achten Sie darauf, dass Ihre Kunden ihre Szenarien verstehen, bevor Sie die Rollenüberprüfung in Ihre App implementieren, insbesondere für die Rolle Organisator. Es gibt keine Garantie, dass ein Besprechungsorganisator in der Besprechung anwesend ist. Als allgemeine Faustregel gilt, dass alle Benutzer entweder Organisator oder Referent sind, wenn sie innerhalb einer Organisation zusammenarbeiten. Wenn ein Benutzer ein Teilnehmer ist, handelt es sich in der Regel um eine absichtliche Entscheidung im Namen eines Besprechungsorganisators.
In einigen Fällen kann ein Benutzer über mehrere Rollen verfügen. Beispielsweise ist ein Organisator auch ein Referent. Darüber hinaus verfügen Besprechungsteilnehmer außerhalb des Mandanten, der die Besprechung hostet, über die Rolle "Gast ", aber möglicherweise auch über Referentenberechtigungen . Dies bietet mehr Flexibilität bei der Verwendung der Rollenüberprüfung in Ihrer Anwendung.
Hinweis
Das Live Share SDK wird für Gastbenutzer in Kanalbesprechungen nicht unterstützt.
Fluid-verteilte Datenstrukturen
Das Live Share SDK unterstützt alle in Fluid Framework enthaltenen verteilten Datenstrukturen. Diese Features dienen als eine Reihe von Grundtypen, die Sie verwenden können, um stabile Szenarien für die Zusammenarbeit zu erstellen, z. B. Echtzeitaktualisierungen einer Aufgabenliste oder die gemeinsame Dokumenterstellung von Text in einem HTML-Code <textarea>
.
Im Gegensatz zu den LiveDataObject
in diesem Artikel erwähnten Klassen werden Fluid-Datenstrukturen nicht zurückgesetzt, nachdem Ihre Anwendung geschlossen wurde. Dies ist ideal für Szenarien wie die Besprechung sidePanel
und content
Kontexte, in denen Benutzer Ihre App häufig schließen und erneut öffnen.
Fluid Framework unterstützt offiziell die folgenden Arten von verteilten Datenstrukturen:
Freigegebenes Objekt | Beschreibung |
---|---|
SharedMap | Ein verteilter Schlüsselwertspeicher. Legen Sie ein beliebiges JSON-serialisierbares Objekt für einen bestimmten Schlüssel fest, um dieses Objekt für alle Teilnehmer der Sitzung zu synchronisieren. |
SharedSegmentSequence | Eine listenähnliche Datenstruktur zum Speichern einer Gruppe von Elementen (als Segmente bezeichnet) an festgelegten Positionen. |
SharedString | Eine verteilte Zeichenfolgensequenz, die für die Bearbeitung des Texts von Dokumenten oder Textbereichen optimiert ist. |
Sehen wir uns an, wie SharedMap
funktioniert. In diesem Beispiel haben wir SharedMap
verwendet, um ein Wiedergabelistenfeature zu erstellen.
import { LiveShareClient } from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";
// Join the Fluid container
const host = LiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: { playlistMap: SharedMap },
};
const { container } = await liveShare.joinContainer(schema);
const playlistMap = container.initialObjects.playlistMap;
// Register listener for changes to values in the map
playlistMap.on("valueChanged", (changed, local) => {
const video = playlistMap.get(changed.key);
// Update UI with added video
});
function onClickAddToPlaylist(video) {
// Add video to map
playlistMap.set(video.id, video);
}
Hinweis
Kern-Fluid Framework DDS-Objekte unterstützen die Überprüfung der Besprechungsrolle nicht. Jeder In der Besprechung kann die über diese Objekte gespeicherten Daten ändern.
Testen des lokalen Browsers
Sie können das Live Share SDK lokal in Ihrem Browser mit der TestLiveShareHost
-Klasse testen, ohne Ihre App in Teams zu installieren. Dies ist nützlich, um die wichtigsten Funktionen für die Zusammenarbeit Ihrer Anwendung in einer vertrauten localhost
Umgebung zu testen.
Beispiel:
import {
LiveShareClient,
TestLiveShareHost,
LiveState,
} from "@microsoft/live-share";
import { LiveShareHost } from "@microsoft/teams-js";
import { SharedMap } from "fluid-framework";
/**
* Detect whether you are in Teams or local environment using your preferred method.
* Options for this include: environment variables, URL params, Teams FX, etc.
*/
const inTeams = process.env.IN_TEAMS;
// Join the Fluid container
const host = inTeams ? LiveShareHost.create() : TestLiveShareHost.create();
const liveShare = new LiveShareClient(host);
const schema = {
initialObjects: {
liveState: LiveState,
sharedMap: SharedMap,
},
};
const { container } = await liveShare.joinContainer(schema);
// ... ready to start app sync logic
Die TestLiveShareHost
-Klasse verwendet den Testserver von Fluid Framework anstelle unseres Produktionsdiensts tinylicious
Azure Fluid Relay. Dazu müssen Sie ihrer package.json
einige Skripts hinzufügen, um den Testserver zu starten. Sie müssen auch die @fluidframework/test-client-utils
Pakete und start-server-and-test
dem devDependencies
in Ihrem package.json
hinzufügen.
{
"scripts": {
"start": "start-server-and-test start:server 7070 start:client",
"start:client": "{YOUR START CLIENT COMMAND HERE}",
"start:server": "npx tinylicious@latest"
},
"devDependencies": {
"@fluidframework/test-client-utils": "^1.3.6",
"start-server-and-test": "^2.0.0"
}
}
Wenn Sie Ihre Anwendung auf diese Weise starten, wird ihrer LiveShareClient
URL hinzugefügt #{containerId}
, wenn sie nicht vorhanden ist. Anschließend können Sie die URL kopieren und in ein neues Browserfenster einfügen, um eine Verbindung mit demselben Fluid-Container herzustellen.
Hinweis
Standardmäßig verfügen presenter
alle Clients, die über TestLiveShareHost
verbunden sind, über die Rollen undorganizer
.
Codebeispiele
Beispielname | Beschreibung | JavaScript | TypeScript |
---|---|---|---|
Dice Roller | Ermöglichen Sie allen verbundenen Clients, einen Würfel zu rollen und das Ergebnis anzuzeigen. | View | Anzeigen |
Agile Poker | Ermöglichen Sie allen verbundenen Clients, Agile Poker zu spielen. | Anzeigen | – |
3D-Modell | Ermöglichen Sie es allen verbundenen Clients, ein 3D-Modell zusammen anzuzeigen. | – | View |
Timer | Ermöglichen Sie allen verbundenen Clients, einen Countdown-Timer anzuzeigen. | – | View |
Anwesenheits-Avatare | Anzeigen von Anwesenheits-Avataren für alle verbundenen Clients. | – | View |
Nächster Schritt
Siehe auch
Platform Docs