Principais recursos do Live Share
O SDK do Live Share pode ser adicionado aos contextos sidePanel
e meetingStage
da extensão da sua reunião com o mínimo de esforço. Também pode utilizar o SDK em contextos de chat e de canal content
, como separadores configuráveis, separadores estáticos e visão de palco colaborativa.
Observação
Os contextos de Partilha content
em Direto em chat e canais só são suportados em clientes Web e de ambiente de trabalho do Teams.
Este artigo se concentra em como integrar o SDK do Live Share ao seu aplicativo e aos principais recursos do SDK.
Pré-requisitos
Instalar o SDK do JavaScript
O SDK live share é um pacote JavaScript publicado no npm e pode transferir através de npm ou yarn. Também tem de instalar dependências de peering do Live Share, que incluem fluid-framework
e @fluidframework/azure-client
. Se estiver a utilizar o Live Share na sua aplicação de separador, também tem de instalar @microsoft/teams-js
a versão 2.23.0
ou posterior. Se quiser utilizar a classe para o TestLiveShareHost
desenvolvimento do browser local, tem de instalar @fluidframework/test-client-utils
e start-server-and-test
empacotar no seu 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 permissões de RSC
Para ativar o SDK live share para a sua extensão de separador, primeiro tem de adicionar as seguintes permissões RSC ao manifesto da aplicação:
{
// ...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"
}
]
}
}
}
Participar numa sessão
Siga os passos para participar numa sessão associada à reunião, conversa ou canal de um utilizador:
- Inicialize
LiveShareClient
. - Defina as estruturas de dados que você deseja sincronizar. Por exemplo:
LiveState
ouSharedMap
. - Ingressar no contêiner.
Exemplo:
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
Foi tudo o que foi preciso para configurar o contentor e participar na sessão mapeada para a reunião, chat ou canal. Agora, vamos revisar os diferentes tipos de estruturas de dados distribuídos que você pode usar com o SDK do Live Share.
Dica
Certifique-se de que o SDK do Cliente do Teams é inicializado antes de chamar LiveShareHost.create()
.
Estruturas de dados do Live Share
O SDK live share inclui um conjunto de novas estruturas de dados distribuídos que expandem a classe do DataObject
Fluid, fornecendo novos tipos de objetos com monitorização de estado e sem estado. Ao contrário das estruturas de dados fluidas, as classes do LiveDataObject
Live Share não escrevem alterações no contentor Fluid, permitindo uma sincronização mais rápida. Além disso, estas turmas foram concebidas de raiz para cenários comuns em reuniões, conversas e canais do Teams. Os cenários comuns incluem sincronizar o conteúdo que o apresentador está a ver, apresentar metadados para cada utilizador na sessão ou apresentar um temporizador de contagem decrescente.
Objeto Dinâmico | Descrição |
---|---|
LivePresence | Veja quais usuários estão online, defina propriedades personalizadas para cada usuário e transmita as alterações em sua presença. |
LiveState | Sincronize qualquer valor serializável state JSON. |
LiveTimer | Sincronize um temporizador de contagem decrescente para um determinado intervalo. |
LiveEvent | Transmita eventos individuais com quaisquer atributos de dados personalizados no conteúdo. |
LiveFollowMode | Siga utilizadores específicos, apresente-os a todas as pessoas na sessão e inicie ou termine as suspensões. |
Exemplo de LivePresence
A LivePresence
classe torna o controlo de quem está na sessão mais fácil do que nunca. Ao chamar os .initialize()
métodos ou .updatePresence()
, pode atribuir metadados personalizados a esse utilizador, como a imagem de perfil, o identificador do conteúdo que está a ver e muito mais. Ao ouvir presenceChanged
eventos, cada cliente recebe o objeto mais recenteLivePresenceUser
, ao fechar todas as atualizações de presença num único registo para cada .userId
Seguem-se alguns exemplos nos quais LivePresence
pode ser utilizado na sua aplicação:
- Obter o Microsoft Teams
userId
,displayName
eroles
de cada utilizador na sessão. - Apresentar informações personalizadas sobre cada utilizador ligado à sessão, como um URL de imagem de perfil.
- Sincronizar as coordenadas numa cena 3D onde está localizado o avatar de cada utilizador.
- Comunicar a posição do cursor de cada utilizador num documento de texto.
- Publicar a resposta de cada utilizador a uma pergunta de quebra-gelo durante uma atividade 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,
});
Os utilizadores que participam numa sessão a partir de um único dispositivo têm um único LivePresenceUser
registo que é partilhado com todos os respetivos dispositivos. Para aceder às ligações mais recentes data
e state
para cada uma das respetivas ligações ativas, pode utilizar a getConnections()
API da LivePresenceUser
classe . Esta ação devolve uma lista de LivePresenceConnection
objetos. Pode ver se uma determinada LivePresenceConnection
instância é do dispositivo local com a isLocalConnection
propriedade .
Cada LivePresenceUser
instância e LivePresenceConnection
tem uma state
propriedade, que pode ser online
, offline
ou away
. Um presenceChanged
evento é emitido quando o estado de um utilizador é alterado. Por exemplo, se um utilizador se desligar da sessão ou fechar a aplicação, o estado será alterado para offline
.
Observação
Pode demorar até 20 segundos para que um LivePresenceUser
's state
atualize para offline
depois de um utilizador se desligar da sessão.
Exemplo de LiveState
A LiveState
classe permite sincronizar o estado da aplicação simples para os participantes ligados.
LiveState
sincroniza um único state
valor, permitindo-lhe sincronizar qualquer valor serializável JSON, como string
, number
ou object
.
Seguem-se alguns exemplos nos quais LiveState
pode ser utilizado na sua aplicação:
- Definir o identificador de utilizador do apresentador atual para criar uma funcionalidade assumir o controlo .
- Sincronizar o caminho de rota atual da sua aplicação para garantir que todos estão na mesma página. Por exemplo,
/whiteboard/:whiteboardId
. - Manter o identificador de conteúdo que o apresentador atual está a ver. Por exemplo, um num
taskId
quadro de tarefas. - Sincronizar o passo atual numa atividade de grupo de várias voltas. Por exemplo, a fase de adivinhação durante o jogo do Poker Ágil.
- Manter uma posição de deslocamento sincronizada para uma funcionalidade seguir-me .
Observação
Ao contrário SharedMap
de , o state
valor em LiveState
é reposto depois de todos os utilizadores se desligarem de uma sessão.
Exemplo:
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");
Exemplo de LiveEvent
LiveEvent
é uma excelente forma de enviar eventos simples para outros clientes ligados que só são necessários no momento da entrega. É útil para cenários como enviar notificações de sessão ou implementar reações 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);
Exemplo de LiveTimer
LiveTimer
fornece um temporizador de contagem decrescente simples que é sincronizado para todos os participantes ligados. É útil para cenários que têm um limite de tempo, como um temporizador de meditação de grupo ou um temporizador redondo para um jogo. Também pode utilizá-lo para agendar tarefas para todas as pessoas na sessão, como apresentar um pedido de lembrete.
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();
Exemplo de LiveFollowMode
A LiveFollowMode
classe combina LivePresence
e LiveState
numa única classe, permitindo-lhe implementar facilmente os modos de seguidor e apresentador na sua aplicação. Isto permite-lhe implementar padrões familiares a partir de aplicações colaborativas populares, como o PowerPoint Live, Excel Live e Whiteboard. Ao contrário da partilha de ecrã, LiveFollowMode
permite-lhe compor conteúdos com elevada qualidade, acessibilidade melhorada e desempenho melhorado. Os utilizadores podem alternar facilmente entre as suas vistas privadas e seguir outros utilizadores.
Pode utilizar a startPresenting()
função para assumir o controlo da aplicação para todos os outros utilizadores na sessão. Em alternativa, pode permitir que os utilizadores selecionem individualmente utilizadores específicos que pretendam seguir com a followUser()
função . Em ambos os cenários, os utilizadores podem introduzir temporariamente uma vista privada com a beginSuspension()
função ou sincronizar novamente com o apresentador com a endSuspension()
função . Entretanto, a update()
função permite que o utilizador local informe outros clientes na sessão do seu pessoal stateValue
. Semelhante a LivePresence
, pode ouvir as alterações efetuadas a cada utilizador através de stateValue
um presenceChanged
serviço de escuta de eventos.
LiveFollowMode
também expõe um state
objeto, que atualiza dinamicamente consoante o utilizador local que o utilizador local está a seguir. Por exemplo, se o utilizador local não estiver a seguir ninguém, a state.value
propriedade corresponde à transmissão mais recente stateValue
do utilizador local através update()
de . No entanto, se o utilizador local estiver a seguir um apresentador, a state.value
propriedade corresponde à mais recente stateValue
do utilizador a apresentar. Semelhante a LiveState
, pode ouvir as alterações ao state
valor através de um stateChanged
serviço de escuta de eventos. Para obter mais informações sobre o state
objeto, veja IFollowModeState interface reference (Referência da interface IFollowModeState).
Seguem-se alguns exemplos nos quais pode utilizar LiveFollowMode
na sua aplicação:
- Sincronize as posições da câmara numa cena 3D para cocriar durante uma revisão da estrutura.
- Atualize o
slideId
para abrir num carrossel para apresentações e debates produtivos. - Difunda o
path
para abrir no router da sua aplicação.
Exemplo:
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;
}
}
}
Em meetingStage
contextos, os seus utilizadores estão a colaborar e a apresentar de forma síncrona para facilitar debates mais produtivos. Quando um utilizador apresenta conteúdo à fase da reunião, deve ligar para a startPresenting()
API do apresentador inicial. Em content
contextos como a visão de fase de colaboração, o conteúdo é mais frequentemente consumido de forma assíncrona. Neste caso, é melhor permitir que os utilizadores optem pela colaboração em tempo real, como através de um botão "Seguir". Ao utilizar a teamsJs.app.getContext()
API no SDK JavaScript do Teams, pode ajustar facilmente a sua funcionalidade em conformidade.
Exemplo:
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
Verificação de funções para estruturas de dados dinâmicos
As reuniões no Teams incluem chamadas, reuniões com todas as mãos e salas de aula online. Os participantes da reunião podem abranger organizações, ter privilégios diferentes ou ter objetivos diferentes. Por conseguinte, é importante respeitar os privilégios de diferentes funções de utilizador durante as reuniões. Os objetos dinâmicos foram concebidos para suportar a verificação de funções, permitindo-lhe definir as funções que têm permissão para enviar mensagens para cada objeto dinâmico individual. Por exemplo, selecionou a opção que permite que apenas os apresentadores e organizadores da reunião controlem a reprodução de vídeo. No entanto, os convidados e participantes ainda podem pedir os próximos vídeos para ver.
Observação
Ao aceder ao Live Share a partir de um content
chat ou contexto de canal, todos os utilizadores terão as Organizer
funções e Presenter
.
No exemplo seguinte, em que apenas os apresentadores e organizadores podem assumir o controlo, LiveState
é utilizado para sincronizar o utilizador que é o apresentador ativo:
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);
}
}
Ouça seus clientes para entender seus cenários antes de implementar a verificação de função em seu aplicativo, principalmente para a função de Organizador. Não há garantias de que um organizador da reunião esteja presente na reunião. Regra geral, todos os utilizadores são Organizador ou Apresentador ao colaborar numa organização. Se um usuário for um Participante, geralmente é uma decisão intencional do organizador.
Em alguns casos, um utilizador pode ter várias funções. Por exemplo, um Organizador também é um Apresentador. Além disso, os participantes da reunião externos ao inquilino que aloja a reunião têm a função convidado , mas também podem ter privilégios de Apresentador . Isto proporciona mais flexibilidade na forma como utiliza a verificação de funções na sua aplicação.
Observação
O SDK live share não é suportado para utilizadores convidados em reuniões de canal.
Estruturas de dados distribuídos do Fluid
O SDK do Live Share dá suporte a qualquer estrutura de dados distribuída incluída no Fluid Framework. Estas funcionalidades servem como um conjunto de primitivos que pode utilizar para criar cenários de colaboração robustos, como atualizações em tempo real de uma lista de tarefas ou cocriação de texto num HTML <textarea>
.
Ao contrário das LiveDataObject
classes mencionadas neste artigo, as estruturas de dados fluidas não são repostas depois de a aplicação ser fechada. Isto é ideal para cenários como a reunião sidePanel
e content
os contextos, em que os utilizadores fecham e reabrem frequentemente a sua aplicação.
O Fluid Framework suporta oficialmente os seguintes tipos de estruturas de dados distribuídas:
Objeto Compartilhado | Descrição |
---|---|
SharedMap | Um repositório de chave-valor distribuído. Defina qualquer objeto serializável JSON de uma determinada chave para sincronizar esse objeto para todos na sessão. |
SharedSegmentSequence | Uma estrutura de dados semelhante à lista para armazenar um conjunto de itens (chamados segmentos) em posições definidas. |
SharedString | Uma sequência de cadeia distribuída otimizada para editar o texto de documentos ou áreas de texto. |
Vamos ver como o SharedMap
funciona. Neste exemplo, usamos SharedMap
para criar um recurso de playlist.
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);
}
Observação
Os objetos DDS do Fluid Framework principal não dão suporte à verificação de função de reunião. Todas as pessoas na reunião podem alterar os dados armazenados através destes objetos.
Teste do browser local
Pode testar localmente o SDK live share no seu browser através da TestLiveShareHost
classe sem instalar a sua aplicação no Teams. Isto é útil para testar as principais capacidades de colaboração da sua aplicação num ambiente familiar localhost
.
Exemplo:
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
A TestLiveShareHost
classe utiliza tinylicious
o servidor de teste do Fluid Framework, em vez do nosso serviço de produção do Azure Fluid Relay. Para tal, tem de adicionar alguns scripts ao seu package.json
para iniciar o servidor de teste. Também tem de adicionar os @fluidframework/test-client-utils
pacotes e start-server-and-test
ao devDependencies
no no .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"
}
}
Quando inicia a sua aplicação desta forma, o LiveShareClient
adiciona #{containerId}
ao URL, se não existir. Em seguida, pode copiar e colar o URL numa nova janela do browser para ligar ao mesmo contentor fluido.
Observação
Por predefinição, todos os clientes ligados através TestLiveShareHost
do terão presenter
funções e organizer
.
Exemplos de código
Nome do exemplo | Descrição | JavaScript | TypeScript |
---|---|---|---|
Dice Roller | Habilite todos os clientes conectados para rolar um dado e exibir o resultado. | View | Exibir |
Agile Poker | Permita que todos os clientes conectados joguem o Agile Poker. | Exibir | NA |
Modelo 3D | Permitir que todos os clientes ligados vejam um modelo 3D em conjunto. | NA | View |
Timer | Ative todos os clientes ligados para ver um temporizador de contagem decrescente. | NA | View |
Avatares de presença | Apresentar avatares de presença para todos os clientes ligados. | NA | View |
Próxima etapa
Confira também
- Aplicativos para reuniões do Teams
- Repositório do GitHub
- Consentimento específico do recurso
- Documentos de referência do SDK do Live Share
- Documentos de referência do SDK de Mídia do Live Share
- Perguntas frequentes do Live Share
- Utilizar o Fluid com o Teams
- Criar o Agile Poker com o SDK Live Share
- Tutorial de código do Dice Roller