Live Share Kernfunktionen

Screenshot: Beispiel für Benutzer, die agile Pokerspiele in einer Teams-Besprechung spielen, in der die Funktion

Das Live Share SDK kann mit minimalem Aufwand den sidePanel und meetingStage Kontexten Ihrer Besprechungserweiterung hinzugefügt werden.

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.11.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 devDependenciesinstallieren@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

Garn

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 Besprechungserweiterung 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": [
            "meetingSidePanel",
            "meetingStage"
        ]
    }
  ],
  "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"
        }
      ]​
    }​
  }​
}

Beitreten einer Besprechungssitzung

Führen Sie die Schritte aus, um an einer Sitzung teilzunehmen, die der Besprechung eines Benutzers zugeordnet ist:

  1. Initialisieren Sie LiveShareClient.
  2. Definieren der vertraulichen Daten, die Sie schützen möchten. Zum Beispiel LiveState oder SharedMap.
  3. 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 war alles, was zum Einrichten des Containers und zum Teilnehmen an der Besprechungssitzung erforderlich war. 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 Besprechungsszenarien in Teams-Besprechungen entwickelt. Häufige Szenarien sind die Synchronisierung der Inhalte, die der Referent anzeigt, das Anzeigen von Metadaten für jeden Benutzer in der Besprechung 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

Screenshot: Beispiel für Personen, die in einer Sitzung verfügbar sindTeams mit Live Share-Anwesenheit

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 userIdunterteilt werden.

Im Folgenden finden Sie einige Beispiele, die LivePresence in Ihrer Anwendung verwendet werden können:

  • Abrufen von Microsoft Teams userId, displayNameund roles 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 instance vom lokalen Gerät isLocalConnection stammt.

Jede LivePresenceUser und LivePresenceConnection instance verfügt über eine state -Eigenschaft, die entweder online, offlineoder awaysein kann. Ein presenceChanged Ereignis wird ausgegeben, wenn sich der Zustand eines Benutzers ändert. Wenn ein Benutzer beispielsweise eine Besprechung verlässt, ändert sich sein Status in offline.

Hinweis

Es kann bis zu 20 Sekunden dauern, bis ein LivePresenceUser's state aktualisiert wird, offline nachdem eine Besprechung verlassen wurde.

LiveState-Beispiel

Der Screenshot zeigt ein Beispiel für den Live Share-Zustand, um zu synchronisieren, welcher Planet im Sonnensystem der Besprechung aktiv präsentiert wird.

Die LiveState -Klasse ermöglicht die Synchronisierung des einfachen Anwendungszustands für alle Teilnehmer einer Besprechung. LiveState synchronisiert einen einzelnen state Wert, sodass Sie jeden serialisierbaren JSON-Wert stringwie , numberoder objectsynchronisieren 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 SharedMapwird 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

Screenshot: Beispiel für den Teams-Client, der eine Benachrichtigung anzeigt, wenn eine Änderung des Ereignisses vorliegt.

LiveEvent ist eine hervorragende Möglichkeit, einfache Ereignisse an andere Clients in einer Besprechung 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

Screenshot: Beispiel für einen Timer für die Anzahl von Abzählungen mit verbleibenden 9 Sekunden

LiveTimer stellt einen einfachen Countdowntimer bereit, der für alle Teilnehmer einer Besprechung 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 Abbildung zeigt drei Clients mit drei separaten Ansichten: ein Referent, ein Benutzer, der dem Referenten folgt, und ein Benutzer mit eigener privater Ansicht mit der Option, sich wieder mit dem Referenten zu synchronisieren.

Hinweis

LiveFollowMode ist als Betaversion verfügbar und wird nur als Vorschauversion bereitgestellt. Verwenden Sie diese API nicht in einer Produktionsumgebung.

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 stateValuezu informieren. Ähnlich LivePresencewie 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 stateValuedes 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 stateIFollowModeState-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 is not currently 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;
      }
    }
}

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 anfordern, um watch.

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 eines organization 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 den Besprechungsseitenbereich, in dem Benutzer Ihre App häufig schließen und erneut öffnen, während sie andere Registerkarten in der Besprechung verwenden, z. B. chatten.

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.jsonhinzufü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. Anzeigen
Timer Ermöglichen Sie allen verbundenen Clients, einen Countdown-Timer anzuzeigen. Anzeigen
Anwesenheits-Avatare Anzeigen von Anwesenheits-Avataren für alle verbundenen Clients. Anzeigen

Nächster Schritt

Siehe auch