Funcionalidades principales de Live Share
El SDK de Live Share se puede agregar a los contextos de sidePanel
y meetingStage
de la extensión de reunión con un esfuerzo mínimo. También puede usar el SDK en contextos de chat y canal content
, como pestañas configurables, pestañas estáticas y vista previa de colaboración.
Nota:
Los contextos de Live Share content
en chats y canales solo se admiten en los clientes de escritorio y web de Teams.
Este artículo se centra en cómo integrar el SDK de Live Share en la aplicación y las funcionalidades clave del SDK.
Requisitos previos
Instalación del SDK de JavaScript
El SDK de Live Share es un paquete de JavaScript publicado en npm y se puede descargar a través de npm o yarn. También debe instalar las dependencias del mismo nivel de Live Share, que incluyen fluid-framework
y @fluidframework/azure-client
. Si usa Live Share en la aplicación de pestaña, también debe instalar @microsoft/teams-js
la versión 2.23.0
o posterior. Si desea usar la clase para el TestLiveShareHost
desarrollo del explorador local, debe instalar @fluidframework/test-client-utils
y start-server-and-test
paquetes en 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
Registrar permisos de RSC
Para habilitar el SDK de Live Share para la extensión de pestaña, primero debe agregar los siguientes permisos de RSC al manifiesto de la aplicación:
{
// ...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"
}
]
}
}
}
Unirse a una sesión
Siga los pasos para unirse a una sesión asociada a la reunión, el chat o el canal de un usuario:
- Inicialice
LiveShareClient
. - Defina las estructuras de datos que desea sincronizar. Por ejemplo,
LiveState
oSharedMap
. - Únase al contenedor.
Ejemplo:
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
Eso es todo lo que se tardó en configurar el contenedor y unirse a la sesión asignada a la reunión, el chat o el canal. Ahora, vamos a revisar los distintos tipos de estructuras de datos distribuidos que puede usar con el SDK de Live Share.
Sugerencia
Asegúrese de que el SDK de cliente de Teams se inicializa antes de llamar a LiveShareHost.create()
.
Estructuras de datos de Live Share
El SDK de Live Share incluye un conjunto de nuevas estructuras de datos distribuidos que amplían la clase de DataObject
Fluid, lo que proporciona nuevos tipos de objetos con estado y sin estado. A diferencia de las estructuras de datos de Fluid, las clases de LiveDataObject
Live Share no escriben cambios en el contenedor de Fluid, lo que permite una sincronización más rápida. Además, estas clases se diseñaron desde cero para escenarios comunes en reuniones, chats y canales de Teams. Los escenarios comunes incluyen la sincronización del contenido que está viendo el moderador, la visualización de metadatos para cada usuario de la sesión o la visualización de un temporizador de cuenta atrás.
Objeto Live | Descripción |
---|---|
LivePresence | Vea qué usuarios están en línea, establezca propiedades personalizadas para cada usuario y difunda los cambios en su presencia. |
LiveState | Sincronice cualquier valor serializable state JSON. |
LiveTimer | Sincronice un temporizador de cuenta atrás para un intervalo determinado. |
LiveEvent | Difunda eventos individuales con atributos de datos personalizados en la carga. |
LiveFollowMode | Siga usuarios específicos, presente a todos los usuarios de la sesión e inicie o finalice las suspensiones. |
Ejemplo de LivePresence
La LivePresence
clase hace que el seguimiento de quién está en la sesión sea más fácil que nunca. Al llamar a los .initialize()
métodos o .updatePresence()
, puede asignar metadatos personalizados para ese usuario, como la imagen de perfil, el identificador del contenido que está viendo, etc. Al escuchar presenceChanged
eventos, cada cliente recibe el objeto más reciente LivePresenceUser
y contrae todas las actualizaciones de presencia en un único registro para cada único userId
.
A continuación se muestran algunos ejemplos en los que LivePresence
se puede usar en la aplicación:
- Obtención de Microsoft Teams
userId
,displayName
yroles
de cada usuario de la sesión. - Mostrar información personalizada sobre cada usuario conectado a la sesión, como una dirección URL de imagen de perfil.
- Sincronizar las coordenadas en una escena 3D donde se encuentra el avatar de cada usuario.
- Informe de la posición del cursor de cada usuario en un documento de texto.
- Publicar la respuesta de cada usuario a una pregunta de separador de hielo durante una actividad de grupo.
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,
});
Los usuarios que se unen a una sesión desde un único dispositivo tienen un único LivePresenceUser
registro que se comparte con todos sus dispositivos. Para acceder a la versión más reciente data
y state
a cada una de sus conexiones activas, puede usar la getConnections()
API desde la LivePresenceUser
clase . Esto devuelve una lista de LivePresenceConnection
objetos. Puede ver si una instancia determinada LivePresenceConnection
procede del dispositivo local mediante la isLocalConnection
propiedad .
Cada LivePresenceUser
instancia de y LivePresenceConnection
tiene una state
propiedad , que puede ser online
, offline
o away
. Cuando presenceChanged
cambia el estado de un usuario, se genera un evento. Por ejemplo, si un usuario se desconecta de la sesión o cierra la aplicación, su estado cambia a offline
.
Nota:
Los datos pueden tardar hasta 20 segundos LivePresenceUser
en actualizarse offline
después de state
que un usuario se desconecte de la sesión.
Ejemplo de LiveState
La LiveState
clase permite sincronizar el estado de la aplicación simple para los participantes conectados.
LiveState
sincroniza un único state
valor, lo que le permite sincronizar cualquier valor serializable json, como string
, number
o object
.
A continuación se muestran algunos ejemplos en los que LiveState
se puede usar en la aplicación:
- Establecer el identificador de usuario del moderador actual para compilar una característica de toma de control .
- Sincronizar la ruta de acceso de ruta actual de la aplicación para asegurarse de que todos están en la misma página. Por ejemplo,
/whiteboard/:whiteboardId
. - Mantener el identificador de contenido que está viendo el moderador actual. Por ejemplo, en
taskId
un panel de tareas. - Sincronización del paso actual en una actividad de grupo de varias rondas. Por ejemplo, la fase de adivinación durante el juego agile poker.
- Mantener una posición de desplazamiento sincronizada para una característica de sígueme .
Nota:
A diferencia SharedMap
de , el state
valor de LiveState
se restablece después de que todos los usuarios se desconecten de una sesión.
Ejemplo:
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");
Ejemplo de LiveEvent
LiveEvent
es una excelente manera de enviar eventos simples a otros clientes conectados que solo son necesarios en el momento de la entrega. Resulta útil para escenarios como el envío de notificaciones de sesión o la implementación de reacciones personalizadas.
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);
Ejemplo de LiveTimer
LiveTimer
proporciona un temporizador de cuenta atrás simple que se sincroniza para todos los participantes conectados. Es útil para escenarios que tienen un límite de tiempo, como un temporizador de meditación en grupo o un temporizador de ronda para un juego. También puede usarlo para programar tareas para todos los usuarios de la sesión, como mostrar un aviso.
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();
Ejemplo de LiveFollowMode
La LiveFollowMode
clase combina LivePresence
y LiveState
en una sola clase, lo que le permite implementar fácilmente modos de seguidor y moderador en la aplicación. Esto le permite implementar patrones conocidos de aplicaciones colaborativas populares como PowerPoint Live, Excel Live y Whiteboard. A diferencia del uso compartido de pantalla, LiveFollowMode
permite representar contenido con alta calidad, accesibilidad mejorada y rendimiento mejorado. Los usuarios pueden cambiar fácilmente entre sus vistas privadas y seguir a otros usuarios.
Puede usar la startPresenting()
función para tomar el control de la aplicación para todos los demás usuarios de la sesión. Como alternativa, puede permitir que los usuarios seleccionen individualmente usuarios específicos que quieran seguir mediante la followUser()
función . En ambos escenarios, los usuarios pueden escribir temporalmente una vista privada con la beginSuspension()
función o sincronizar de nuevo con el moderador con la endSuspension()
función. Mientras tanto, la update()
función permite al usuario local informar a otros clientes de la sesión de su propio personal stateValue
. De forma similar a LivePresence
, puede escuchar los cambios de cada usuario a través de un presenceChanged
agente de escucha de stateValue
eventos.
LiveFollowMode
también expone un state
objeto, que se actualiza dinámicamente en función del usuario que sigue el usuario local. Por ejemplo, si el usuario local no sigue a nadie, la state.value
propiedad coincide con la difusión más reciente stateValue
del usuario local a través de update()
. Sin embargo, si el usuario local sigue a un moderador, la state.value
propiedad coincide con la más reciente stateValue
del usuario que la presenta. De forma similar a LiveState
, puede escuchar los cambios en el state
valor mediante un stateChanged
agente de escucha de eventos. Para obtener más información sobre el objeto , vea Referencia de interfazstate
IFollowModeState.
A continuación se muestran algunos ejemplos en los que puede usar LiveFollowMode
en la aplicación:
- Sincronice las posiciones de la cámara en una escena 3D con cobrowse durante una revisión de diseño.
- Actualice para
slideId
que se abra en un carrusel para presentaciones y discusiones productivas. - Difunda para que se abra en el
path
enrutador de la aplicación.
Ejemplo:
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;
}
}
}
En meetingStage
contextos, los usuarios colaboran y presentan sincrónicamente para facilitar discusiones más productivas. Cuando un usuario presenta contenido a la fase de reunión, debe llamar a la startPresenting()
API para el moderador inicial. En content
contextos como la vista previa de colaboración, el contenido se consume de forma asincrónica con mayor frecuencia. En este caso, es mejor permitir que los usuarios opten por la colaboración en tiempo real, como mediante un botón "Seguir". Con la teamsJs.app.getContext()
API del SDK de JavaScript de Teams, puede ajustar fácilmente la funcionalidad en consecuencia.
Ejemplo:
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
Comprobación de roles para estructuras de datos activas
Las reuniones en Teams incluyen llamadas, reuniones de manos y clases en línea. Los participantes de la reunión pueden abarcar organizaciones, tener privilegios diferentes o tener objetivos diferentes. Por lo tanto, es importante respetar los privilegios de los distintos roles de usuario durante las reuniones. Los objetos dinámicos están diseñados para admitir la comprobación de roles, lo que le permite definir los roles que pueden enviar mensajes para cada objeto dinámico individual. Por ejemplo, ha seleccionado la opción que permite que solo los moderadores y organizadores de reuniones controlen la reproducción de vídeo. Sin embargo, los invitados y asistentes todavía pueden solicitar los siguientes vídeos para verlos.
Nota:
Al acceder a Live Share desde un content
contexto de chat o canal, todos los usuarios tendrán los Organizer
roles y Presenter
.
En el ejemplo siguiente, donde solo los moderadores y organizadores pueden tomar el control, LiveState
se usa para sincronizar qué usuario es el moderador activo:
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);
}
}
Escuche a los clientes para comprender sus escenarios antes de implementar la comprobación de roles en la aplicación, especialmente para el rol Organizador. No hay ninguna garantía de que un organizador de la reunión esté presente en la reunión. Como regla general, todos los usuarios son Organizador o Moderador al colaborar dentro de una organización. Si un usuario es un Asistente, suele ser una decisión intencionada en nombre de un organizador de la reunión.
En algunos casos, un usuario podría tener varios roles. Por ejemplo, un organizador también es un moderador. Además, los participantes de la reunión que son externos al inquilino que hospeda la reunión tienen el rol Invitado , pero también pueden tener privilegios de moderador . Esto proporciona más flexibilidad en el uso de la verificación de roles en la aplicación.
Nota:
El SDK de Live Share no es compatible con los usuarios invitados en las reuniones de canal.
Estructuras de datos distribuidos fluidos
El SDK de Live Share admite cualquier estructura de datos distribuida incluida en Fluid Framework. Estas características sirven como un conjunto de primitivos que puede usar para crear escenarios de colaboración sólidos, como actualizaciones en tiempo real de una lista de tareas o coautoría de texto dentro de un html <textarea>
.
A diferencia de las LiveDataObject
clases mencionadas en este artículo, las estructuras de datos fluid no se restablecen después de cerrar la aplicación. Esto es ideal para escenarios como la reunión sidePanel
y content
los contextos, donde los usuarios cierran y vuelven a abrir la aplicación con frecuencia.
Fluid Framework admite oficialmente los siguientes tipos de estructuras de datos distribuidas:
Objeto compartido | Descripción |
---|---|
SharedMap | Almacén de clave-valor distribuido. Establezca cualquier objeto serializable con JSON para que una clave determinada sincronice ese objeto para todos los usuarios de la sesión. |
SharedSegmentSequence | Estructura de datos de tipo lista para almacenar un conjunto de elementos (denominados segmentos) en posiciones de conjunto. |
SharedString | Secuencia de cadena distribuida optimizada para editar el texto de documentos o áreas de texto. |
Veamos cómo funciona SharedMap
. En este ejemplo, hemos usado SharedMap
para crear una característica de lista de reproducción.
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);
}
Nota:
Los objetos DDS de Core Fluid Framework no admiten la comprobación de roles de reunión. Todos los usuarios de la reunión pueden cambiar los datos almacenados a través de estos objetos.
Pruebas del explorador local
Puede probar localmente el SDK de Live Share en el explorador mediante la clase sin instalar la TestLiveShareHost
aplicación en Teams. Esto es útil para probar las capacidades de colaboración básicas de la aplicación dentro de un entorno familiar localhost
.
Ejemplo:
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
clase usa el tinylicious
servidor de prueba de Fluid Framework, en lugar de nuestro servicio de producción de Azure Fluid Relay. Para ello, debe agregar algunos scripts a package.json
para iniciar el servidor de prueba. También debe agregar los @fluidframework/test-client-utils
paquetes y start-server-and-test
a en devDependencies
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"
}
}
Al iniciar la aplicación de esta manera, se agrega #{containerId}
a la LiveShareClient
dirección URL, si no existe. A continuación, puede copiar y pegar la dirección URL en una nueva ventana del explorador para conectarse al mismo contenedor Fluid.
Nota:
De forma predeterminada, todos los clientes conectados a través TestLiveShareHost
de tendrán presenter
roles y organizer
.
Ejemplos de código
Ejemplo de nombre | Descripción | JavaScript | TypeScript |
---|---|---|---|
Dice Roller | Habilite a todos los clientes conectados para que lancen el dado y vean el resultado. | View | Ver |
Agile Poker | Permitir que todos los clientes conectados jueguen a Agile Poker. | View | ND |
Modelo 3D | Permitir que todos los clientes conectados vean un modelo 3D juntos. | ND | View |
Temporizador | Habilite todos los clientes conectados para ver un temporizador de cuenta atrás. | ND | Ver |
Avatares de presencia | Mostrar avatares de presencia para todos los clientes conectados. | ND | View |
Paso siguiente
Vea también
- Aplicaciones para reuniones de Teams
- Repositorio de GitHub
- Consentimiento específico del recurso
- Documentos de referencia del SDK de Live Share
- Documentos de referencia del SDK multimedia de Live Share
- Preguntas más frecuentes sobre Live Share
- Uso de Fluid con Teams
- Compilación de Agile Poker mediante el SDK de Live Share
- Tutorial de código de Dice Roller