Fonctionnalités principales de Live Share
Le Kit de développement logiciel (SDK) Live Share peut être ajouté aux contextes sidePanel
et meetingStage
de l’extension de votre réunion avec un minimum d’efforts. Vous pouvez également utiliser le Kit de développement logiciel (SDK) dans des contextes de conversation et de canal content
, tels que des onglets configurables, des onglets statiques et une vue d’étape collaborative.
Remarque
Les contextes live share content
dans les conversations et les canaux sont pris en charge uniquement sur les clients web et de bureau Teams.
Cet article se concentre sur la façon d’intégrer le Kit de développement logiciel (SDK) Live Share dans votre application et les fonctionnalités clés du Kit de développement logiciel (SDK).
Conditions préalables
Installer le Kit de développement logiciel (SDK) JavaScript
Le Kit de développement logiciel (SDK) Live Share est un package JavaScript publié sur npm, que vous pouvez télécharger via npm ou yarn. Vous devez également installer les dépendances d’homologue Live Share, notamment fluid-framework
et @fluidframework/azure-client
. Si vous utilisez Live Share dans votre application d’onglet, vous devez également installer @microsoft/teams-js
la version ou une version 2.23.0
ultérieure. Si vous souhaitez utiliser la classe pour le TestLiveShareHost
développement de navigateur local, vous devez installer @fluidframework/test-client-utils
les packages et start-server-and-test
dans votre devDependencies
.
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
Inscrire des autorisations RSC
Pour activer le Kit de développement logiciel (SDK) Live Share pour votre extension d’onglet, vous devez d’abord ajouter les autorisations RSC suivantes dans le manifeste de votre application :
{
// ...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"
}
]
}
}
}
Rejoindre une session
Suivez les étapes pour rejoindre une session associée à la réunion, à la conversation ou au canal d’un utilisateur :
- Initialisez
LiveShareClient
. - Définir les structure de données que vous voulez synchroniser. Par exemple :
LiveState
ouSharedMap
. - Rejoindre le conteneur.
Exemple :
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
C’est tout ce qu’il faut pour configurer votre conteneur et rejoindre la session mappée à la réunion, à la conversation ou au canal. À présent, examinons les différents types de structures des données distribuées que vous pouvez utiliser avec le Kit de développement logiciel (SDK) Live Share.
Conseil
Vérifiez que le Kit de développement logiciel (SDK) du client Teams est initialisé avant d’appeler LiveShareHost.create()
.
Structures de données Live Share
Le Kit de développement logiciel (SDK) Live Share inclut un ensemble de nouvelles structures de données distribuées qui étendent la classe de DataObject
Fluid, fournissant de nouveaux types d’objets avec état et sans état. Contrairement aux structures de données Fluid, les classes de LiveDataObject
Live Share n’écrivent pas les modifications dans le conteneur Fluid, ce qui permet une synchronisation plus rapide. En outre, ces classes ont été conçues de bout en bout pour des scénarios courants dans les réunions, conversations et canaux Teams. Les scénarios courants incluent la synchronisation du contenu affiché par le présentateur, l’affichage des métadonnées pour chaque utilisateur de la session ou l’affichage d’un minuteur de compte à rebours.
Objet en direct | Description |
---|---|
LivePresence | Découvrez quels utilisateurs sont en ligne, définissez des propriétés personnalisées pour chaque utilisateur et diffusez les modifications apportées à leur participation. |
LiveState | Synchronisez toute valeur json sérialisable state . |
LiveTimer | Synchronisez un minuteur de compte à rebours pour un intervalle donné. |
LiveEvent | Diffusez des événements individuels avec des attributs de données personnalisés dans la charge utile. |
LiveFollowMode | Suivez des utilisateurs spécifiques, présentez-les à tous les participants de la session et commencez ou terminez les suspensions. |
Exemple LivePresence
La LivePresence
classe facilite plus que jamais le suivi des personnes présentes dans la session. Lorsque vous appelez les .initialize()
méthodes ou .updatePresence()
, vous pouvez affecter des métadonnées personnalisées à cet utilisateur, telles que l’image de profil, l’identificateur du contenu qu’il affiche, etc. En écoutant presenceChanged
les événements, chaque client reçoit le dernier LivePresenceUser
objet, en réduisant toutes les mises à jour de présence dans un enregistrement unique pour chaque unique userId
.
Voici quelques exemples qui LivePresence
peuvent être utilisés dans votre application :
- Obtention de Microsoft Teams
userId
,displayName
etroles
de chaque utilisateur de la session. - Affichage d’informations personnalisées sur chaque utilisateur connecté à la session, telles qu’une URL d’image de profil.
- Synchronisation des coordonnées dans une scène 3D où se trouve l’avatar de chaque utilisateur.
- Signaler la position du curseur de chaque utilisateur dans un document texte.
- Publication de la réponse de chaque utilisateur à une question de brise-glace pendant une activité de groupe.
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,
});
Les utilisateurs qui rejoignent une session à partir d’un seul appareil ont un enregistrement unique LivePresenceUser
qui est partagé sur tous leurs appareils. Pour accéder à la dernière version data
et state
pour chacune de leurs connexions actives, vous pouvez utiliser l’API getConnections()
à partir de la LivePresenceUser
classe . Cette opération renvoie une liste d’objets LivePresenceConnection
. Vous pouvez voir si une instance donnée LivePresenceConnection
provient de l’appareil local à l’aide de la isLocalConnection
propriété .
Chaque LivePresenceUser
instance et LivePresenceConnection
a une state
propriété , qui peut être online
, offline
ou away
. Un presenceChanged
événement est émis lorsque l’état d’un utilisateur change. Par exemple, si un utilisateur se déconnecte de la session ou ferme l’application, son état devient offline
.
Remarque
La mise à jour offline
d’un LivePresenceUser
state
objet vers peut prendre jusqu’à 20 secondes après la déconnexion d’un utilisateur de la session.
Exemple LiveState
La LiveState
classe permet de synchroniser l’état d’application simple pour les participants connectés.
LiveState
synchronise une valeur unique state
, ce qui vous permet de synchroniser toute valeur sérialisable JSON, telle qu’une string
valeur , number
ou object
.
Voici quelques exemples qui LiveState
peuvent être utilisés dans votre application :
- Définition de l’identificateur d’utilisateur du présentateur actuel pour créer une fonctionnalité de prise de contrôle .
- Synchronisation du chemin d’itinéraire actuel de votre application pour vous assurer que tout le monde est sur la même page. Par exemple :
/whiteboard/:whiteboardId
. - Gestion de l’identificateur de contenu affiché par le présentateur actuel. Par exemple, sur
taskId
un tableau de tâches. - Synchronisation de l’étape actuelle dans une activité de groupe à plusieurs tours. Par exemple, la phase de devinette pendant le jeu Agile Poker.
- Maintien d’une position de défilement synchronisée pour une fonctionnalité Suivez-moi .
Remarque
Contrairement à SharedMap
, la state
valeur dans LiveState
est réinitialisée une fois que tous les utilisateurs se déconnectent d’une session.
Exemple :
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");
Exemple LiveEvent
LiveEvent
est un excellent moyen d’envoyer des événements simples à d’autres clients connectés qui ne sont nécessaires qu’au moment de la livraison. Il est utile pour les scénarios tels que l’envoi de notifications de session ou l’implémentation de réactions personnalisées.
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);
Exemple LiveTimer
LiveTimer
fournit un compte à rebours simple qui est synchronisé pour tous les participants connectés. Il est utile pour les scénarios qui ont une limite de temps, comme un minuteur de méditation de groupe ou un minuteur d’arrondi pour un jeu. Vous pouvez également l’utiliser pour planifier des tâches pour tous les participants à la session, telles que l’affichage d’une invite de rappel.
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();
Exemple LiveFollowMode
La LiveFollowMode
classe combine et LiveState
en une seule classe, ce qui vous permet d’implémenter facilement les LivePresence
modes d’utilisateur et de présentateur dans votre application. Cela vous permet d’implémenter des modèles familiers à partir d’applications collaboratives populaires telles que PowerPoint Live, Excel Live et Tableau blanc. Contrairement au partage d’écran, LiveFollowMode
vous permet d’afficher du contenu avec une qualité élevée, une meilleure accessibilité et des performances améliorées. Les utilisateurs peuvent facilement basculer entre leurs vues privées et suivre d’autres utilisateurs.
Vous pouvez utiliser la startPresenting()
fonction pour prendre le contrôle de l’application pour tous les autres utilisateurs de la session. Vous pouvez également autoriser les utilisateurs à sélectionner individuellement des utilisateurs spécifiques qu’ils souhaitent suivre à l’aide de la followUser()
fonction . Dans les deux scénarios, les utilisateurs peuvent entrer temporairement une vue privée avec la beginSuspension()
fonction ou se synchroniser à nouveau avec le présentateur avec la endSuspension()
fonction. Pendant ce temps, la update()
fonction permet à l’utilisateur local d’informer d’autres clients dans la session de leur propre personnel stateValue
. Comme pour LivePresence
, vous pouvez écouter les modifications apportées à chaque utilisateur via un écouteur d’événements stateValue
presenceChanged
.
LiveFollowMode
expose également un state
objet, qui se met à jour dynamiquement en fonction de l’utilisateur que l’utilisateur local suit. Par exemple, si l’utilisateur local ne suit personne, la state.value
propriété correspond à la dernière stateValue
diffusion de l’utilisateur local via update()
. Toutefois, si l’utilisateur local suit un présentateur, la state.value
propriété correspond au plus récent stateValue
de l’utilisateur de présentation. Comme pour LiveState
, vous pouvez écouter les modifications apportées à la valeur à l’aide state
d’un écouteur d’événements stateChanged
. Pour plus d’informations sur l’objet, consultez Informations de référence sur l’interface state
IFollowModeState.
Voici quelques exemples que vous pouvez utiliser LiveFollowMode
dans votre application :
- Synchroniser les positions de la caméra dans une scène 3D avec cobrowse pendant une révision de conception.
- Mettez à jour pour
slideId
ouvrir dans un carrousel pour des présentations et des discussions productives. - Diffusez le
path
à ouvrir dans le routeur de votre application.
Exemple :
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;
}
}
}
Dans meetingStage
les contextes, vos utilisateurs collaborent et présentent de manière synchrone pour faciliter des discussions plus productives. Lorsqu’un utilisateur présente du contenu à la phase de réunion, vous devez appeler l’API startPresenting()
pour le présentateur initial. Dans content
des contextes tels que la vue d’étape collaborative, le contenu est le plus souvent consommé de manière asynchrone. Dans ce cas, il est préférable de laisser les utilisateurs opter pour la collaboration en temps réel, par exemple via un bouton « Suivre ». À l’aide de l’API teamsJs.app.getContext()
dans le Kit de développement logiciel (SDK) JavaScript Teams, vous pouvez facilement ajuster vos fonctionnalités en conséquence.
Exemple :
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
Vérification des rôles pour les structures de données actives
Les réunions dans Teams incluent des appels, des réunions toutes mains et des salles de classe en ligne. Les participants à la réunion peuvent s’étendre à plusieurs organisations, avoir des privilèges différents ou avoir des objectifs différents. Par conséquent, il est important de respecter les privilèges des différents rôles d’utilisateur pendant les réunions. Les objets en direct sont conçus pour prendre en charge la vérification des rôles, ce qui vous permet de définir les rôles autorisés à envoyer des messages pour chaque objet actif individuel. Par exemple, vous avez sélectionné l’option qui autorise uniquement les présentateurs de réunion et les organisateurs à contrôler la lecture vidéo. Toutefois, les invités et les participants peuvent toujours demander les prochaines vidéos à regarder.
Remarque
Lors de l’accès à Live Share à partir d’une conversation ou d’un content
contexte de canal, tous les utilisateurs auront les Organizer
rôles et Presenter
.
Dans l’exemple suivant, où seuls les présentateurs et les organisateurs peuvent prendre le contrôle, LiveState
est utilisé pour synchroniser quel utilisateur est le présentateur actif :
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);
}
}
Écoutez vos clients pour comprendre leurs scénarios avant d’implémenter la vérification de rôle dans votre application, en particulier pour le rôle d’Organisateur. Il n’existe aucune garantie qu’un organisateur de réunion sera présent dans la réunion. En règle générale, tous les utilisateurs sont organisateurs ou présentateurs lors de la collaboration au sein d’une organisation. Si un utilisateur est un Participant, il s’agit généralement d’une décision intentionnelle au nom d’un organisateur de la réunion.
Dans certains cas, un utilisateur peut avoir plusieurs rôles. Par exemple, un organisateur est également un présentateur. En outre, les participants à la réunion qui sont externes au locataire hébergeant la réunion ont le rôle Invité , mais peuvent également avoir des privilèges de présentateur . Cela offre plus de flexibilité dans la façon dont vous utilisez la vérification des rôles dans votre application.
Remarque
Le Kit de développement logiciel (SDK) Live Share n’est pas pris en charge pour les utilisateurs invités dans les réunions de canal.
Structures de données distribuées Fluid
Le Kit de développement logiciel (SDK) Live Share prend en charge toute structure de données distribuées incluse dans Infrastructure Fluid. Ces fonctionnalités servent d’ensemble de primitives que vous pouvez utiliser pour créer des scénarios de collaboration robustes, tels que des mises à jour en temps réel d’une liste de tâches ou la co-création de texte dans un code HTML <textarea>
.
LiveDataObject
Contrairement aux classes mentionnées dans cet article, les structures de données Fluid ne se réinitialisent pas après la fermeture de votre application. Cela est idéal pour les scénarios tels que la réunion sidePanel
et content
les contextes, où les utilisateurs ferment et rouvrent fréquemment votre application.
Fluid Framework prend officiellement en charge les types de structures de données distribuées suivants :
Objet partagé | Description |
---|---|
SharedMap | Un magasin de valeurs clés distribué. Définissez un objet JSON sérialisable pour une clé donnée afin de synchroniser cet objet pour tous les membres de la session. |
SharedSegmentSequence | Structure de données de type liste permettant de stocker un groupe d’éléments (appelés segments) dans des positions définies. |
SharedString | Séquence de chaîne distribuée optimisée pour la modification du texte des documents ou des zones de texte. |
Voyons comment SharedMap
fonctionne. Dans cet exemple, nous avons utilisé SharedMap
pour créer une fonctionnalité de sélection.
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);
}
Remarque
Les objets principaux DDS Infrastructure Fluid ne prennent pas en charge la vérification du rôle de la réunion. Tous les participants à la réunion peuvent modifier les données stockées via ces objets.
Test du navigateur local
Vous pouvez tester localement le Kit de développement logiciel (SDK) Live Share dans votre navigateur à l’aide de la TestLiveShareHost
classe sans installer votre application dans Teams. Cela est utile pour tester les principales fonctionnalités collaboratives de votre application dans un environnement familier localhost
.
Exemple :
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
La TestLiveShareHost
classe utilise le tinylicious
serveur de test de Fluid Framework, plutôt que notre service Relais Azure Fluid de production. Pour ce faire, vous devez ajouter quelques scripts à votre package.json
pour démarrer le serveur de test. Vous devez également ajouter les @fluidframework/test-client-utils
packages et start-server-and-test
au devDependencies
dans votre package.json
.
{
"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"
}
}
Lorsque vous démarrez votre application de cette façon, le LiveShareClient
ajoute #{containerId}
à votre URL, si elle n’existe pas. Vous pouvez ensuite copier et coller l’URL dans une nouvelle fenêtre de navigateur pour vous connecter au même conteneur Fluid.
Remarque
Par défaut, tous les clients connectés via TestLiveShareHost
auront presenter
des rôles et organizer
.
Exemples de code
Exemple de nom | Description | JavaScript | TypeScript |
---|---|---|---|
Lanceur de dés | Permettre à tous les clients connectés de lancer un dé et de visualiser le résultat. | View | View |
Agile Poker | Permettre à tous les clients connectés de jouer à Agile Poker. | View | N/A |
Modèle 3D | Permettre à tous les clients connectés d’afficher un modèle 3D ensemble. | N/A | View |
Minuteur | Permettre à tous les clients connectés d’afficher un minuteur de compte à rebours. | N/A | View |
Avatars de présence | Afficher les avatars de présence pour tous les clients connectés. | N/A | View |
Étape suivante
Voir aussi
- Applications pour les réunions Teams
- Référentiel GitHub
- Consentement spécifique à la ressource
- Documents de référence du kit SDK Live Share
- Documents de référence du kit SDK Live Share Media
- FAQ Live Share
- Utiliser Fluid avec Teams
- Créer Agile Poker à l’aide du Kit de développement logiciel (SDK) Live Share
- Tutoriel de code pour le lanceur de dés