Руководство по коду Dice Roller
В примере приложения Dice Roller для пользователей отображаются кости с кнопкой для его наката. При накате костей пакет SDK для Live Share использует Fluid Framework для синхронизации данных между клиентами, поэтому каждый видит один и тот же результат. Чтобы синхронизировать данные, выполните следующие действия в файле app.js.
- Настройка приложения
- Присоединение к контейнеру Fluid
- Создание представления этапа собрания
- Подключение этапа собрания к Live Share
- Запись представления боковой панели
- Запись представления параметров
Настройка приложения
Вы можете начать с импорта необходимых модулей. В примере используются LiveState DDS и LiveShareClient из пакета SDK для Live Share. Этот пример поддерживает расширяемость собраний Teams, поэтому необходимо включить клиентскую библиотеку JavaScript (TeamsJS) Microsoft Teams. Наконец, пример предназначен для локального выполнения и в собрании Teams, поэтому для локального тестирования примера необходимо включить дополнительные компоненты Fluid Framework.
Приложения создают контейнеры Fluid с помощью схемы, определяющей набор начальных объектов , доступных контейнеру. В примере используется LiveState для хранения текущего значения костей, которое было свернуто.
Для приложений для собраний Teams требуется несколько представлений, таких как содержимое, конфигурация и этап. Вы можете создать start()
функцию для идентификации представления. Эта функция помогает отрисовывать и выполнять любую необходимую инициализацию. Приложение поддерживает запуск как локально в веб-браузере, так и из собрания Teams. Функция start()
ищет параметр запроса, inTeams=true
чтобы определить, выполняется ли он в Teams.
Примечание.
При запуске в Teams приложение должно вызвать app.initialize()
перед вызовом любых других методов teams-js.
В дополнение к параметру inTeams=true
запроса можно использовать view=content|config|stage
параметр запроса для определения представления, которое необходимо отобразить.
import { app, pages, LiveShareHost } from "@microsoft/teams-js";
import { LiveShareClient, TestLiveShareHost, LiveState } from "@microsoft/live-share";
const searchParams = new URL(window.location).searchParams;
const root = document.getElementById("content");
// Define container schema
const containerSchema = {
initialObjects: { diceState: LiveState },
};
// STARTUP LOGIC
async function start() {
// Check for page to display
let view = searchParams.get("view") || "stage";
// Check if we are running on stage.
if (!!searchParams.get("inTeams")) {
// Initialize teams app
await app.initialize();
}
// Load the requested view
switch (view) {
case "content":
renderSidePanel(root);
break;
case "config":
renderSettings(root);
break;
case "stage":
default:
const { container } = await joinContainer();
renderStage(container.initialObjects.diceState, root);
break;
}
}
start().catch((error) => console.error(error));
Присоединение к контейнеру Fluid
Не все представления приложения должны быть совместными. Представлению stage
всегда требуются функции совместной работы, представлению content
могут потребоваться функции совместной работы, а представлению config
никогда не нужны функции совместной работы. Для представлений, которым требуются функции совместной работы, необходимо присоединиться к контейнеру Fluid, связанному с текущим собранием.
Присоединить контейнер для собрания так же просто, как инициализировать LiveShareClient
с экземпляром LiveShareHost
из пакета SDK для клиента Teams, а затем вызвать его joinContainer()
метод.
При локальном запуске можно инициализировать LiveShareClient
с помощью экземпляра TestLiveShareHost
.
async function joinContainer() {
// Are we running in Teams? If so, use LiveShareHost, otherwise use TestLiveShareHost
const host = !!searchParams.get("inTeams")
? LiveShareHost.create()
: TestLiveShareHost.create();
// Create client
const client = new LiveShareClient(host);
// Join container
return await client.joinContainer(containerSchema, onContainerFirstCreated);
}
При локальном тестировании обновляет URL-адрес браузера, TestLiveShareHost
чтобы он содержал идентификатор созданного тестового контейнера. Копирование этой ссылки на другие вкладки браузера приводит к присоединению LiveShareClient
созданного тестового контейнера. Если изменение URL-адреса приложения мешает работе приложения, стратегию, используемую для хранения идентификатора тестовых контейнеров, можно настроить с помощью параметров setLocalTestContainerId и getLocalTestContainerId , передаваемых в LiveShareClient
.
Написание представления Stageview
Многие приложения расширяемости собраний Teams предназначены для использования React для своей платформы представления, но это необязательно. Например, в этом примере используются стандартные методы HTML/DOM для отрисовки представления.
Начало со статического представления
Вы можете легко создать представление с использованием локальных данных без функций Fluid, а затем добавить функции Fluid, изменив некоторые ключевые части приложения.
Функция renderStage
добавляет в переданный stageTemplate
HTML-элемент и создает рабочий ролик кости со случайным значением кости при каждом нажатии кнопки Roll . diceState
используется в следующих нескольких действиях.
const stageTemplate = document.createElement("template");
stageTemplate["innerHTML"] = `
<div class="wrapper">
<div class="dice"></div>
<button class="roll"> Roll </button>
</div>
`;
function renderStage(diceState, elem) {
elem.appendChild(stageTemplate.content.cloneNode(true));
const rollButton = elem.querySelector(".roll");
const dice = elem.querySelector(".dice");
const updateDice = () => {
// Get a random value between 1 and 6
const diceValue = Math.floor(Math.random() * 6) + 1;
// Unicode 0x2680-0x2685 are the sides of a die (⚀⚁⚂⚃⚄⚅).
dice.textContent = String.fromCodePoint(0x267f + value);
};
rollButton.onclick = () => updateDice();
updateDice(1);
}
Подключение этапа собрания к Live Share
Изменение LiveState
Чтобы начать использовать Live Share в приложении, первое, что нужно изменить, это то, что происходит, когда пользователь выбирает rollButton
. Вместо обновления локального состояния напрямую кнопка обновляет число, хранящееся state
в качестве значения в diceState
. При каждом вызове .set()
с новым state
значением это значение распространяется на все клиенты. Любые изменения в diceState
могут привести stateChanged
к возникновению события, а обработчик событий может активировать обновление представления.
Этот шаблон распространен в распределенных структурах данных Fluid и Live Share, так как он позволяет представлению вести себя одинаково при локальных и удаленных изменениях.
rollButton.onclick = () =>
diceState.set(Math.floor(Math.random() * 6) + 1);
Использование данных Fluid
Следующее изменение, которое необходимо внести, — изменить функцию updateDice
, чтобы получить последнее значение костей LiveState
из каждого updateDice
вызова.
const updateDice = () => {
const diceValue = diceState.state;
dice.textContent = String.fromCodePoint(0x267f + diceValue);
};
Обработка удаленных изменений
Значения, возвращаемые из diceState
, являются только моментальным снимком во времени. Чтобы данные обновлялись по мере их изменения, необходимо зарегистрировать diceState
обработчик событий для вызова updateDice
при каждой отправке stateChanged
события.
diceState.on("stateChanged", updateDice);
Инициализация LiveState
Прежде чем начать получать изменения Live Share в приложении, необходимо сначала вызвать initialize()
LiveState
объект с начальным значением. Это начальное значение не перезаписывает существующее состояние, отправленное другими пользователями.
После инициализации LiveState
stateChanged
зарегистрированное ранее событие начинает активироваться при каждом изменении. Однако для обновления пользовательского интерфейса в исходном значении вызовите .updateDice()
await diceState.initialize(1);
updateDice();
Запись представления боковой панели
Представление боковой панели, загруженное с помощью вкладки contentUrl
с контекстом фрейма sidePanel
, отображается пользователю на боковой панели, когда он открывает ваше приложение на собрании. Цель представления боковой панели — позволить пользователю выбрать содержимое приложения, прежде чем предоставлять доступ к приложению на этапе собрания. Для приложений пакета SDK Live Share представление боковой панели также можно использовать в качестве вспомогательного интерфейса приложения. Вызов joinContainer()
из представления боковой панели подключается к тому же контейнеру Fluid, к которому подключено представление Stageview. Затем этот контейнер можно использовать для взаимодействия с Stageview. Убедитесь, что вы взаимодействуете с представлением Stageview и боковой панели всех пользователей.
В представлении боковой панели примера пользователю предлагается нажать кнопку демонстрации на сцене.
const sidePanelTemplate = document.createElement("template");
sidePanelTemplate["innerHTML"] = `
<style>
.wrapper { text-align: center }
.title { font-size: large; font-weight: bolder; }
.text { font-size: medium; }
</style>
<div class="wrapper">
<p class="title">Lets get started</p>
<p class="text">Press the share to stage button to share Dice Roller to the meeting stage.</p>
</div>
`;
function renderSidePanel(elem) {
elem.appendChild(sidePanelTemplate.content.cloneNode(true));
}
Запись представления параметров
Представление параметров, загруженное configurationUrl
в манифесте приложения, отображается пользователю при первом добавлении приложения в собрание Teams. Это представление позволяет разработчику настроить contentUrl
для вкладки, закрепленной на собрании с учетом введенных пользователем данных. Эта страница является обязательной, даже если для задания значения не требуется вводить данные пользователем contentUrl
.
Примечание.
Live Share' joinContainer()
не поддерживается в контексте вкладки settings
.
В представлении параметров примера пользователю предлагается нажать кнопку "Сохранить".
const settingsTemplate = document.createElement("template");
settingsTemplate["innerHTML"] = `
<style>
.wrapper { text-align: center }
.title { font-size: large; font-weight: bolder; }
.text { font-size: medium; }
</style>
<div class="wrapper">
<p class="title">Welcome to Dice Roller!</p>
<p class="text">Press the save button to continue.</p>
</div>
`;
function renderSettings(elem) {
elem.appendChild(settingsTemplate.content.cloneNode(true));
// Save the configurable tab
pages.config.registerOnSaveHandler((saveEvent) => {
pages.config.setConfig({
websiteUrl: window.location.origin,
contentUrl: window.location.origin + "?inTeams=1&view=content",
entityId: "DiceRollerFluidLiveShare",
suggestedDisplayName: "DiceRollerFluidLiveShare",
});
saveEvent.notifySuccess();
});
// Enable the Save button in config dialog
pages.config.setValidityState(true);
}
Локальное тестирование
Вы можете протестировать свое приложение локально с помощью npm run start
. Дополнительные сведения см. в кратком руководстве по началу работы.
Тестирование в Teams
После запуска приложения локально с помощью npm run start
можно протестировать приложение в Teams. Если вы хотите протестировать приложение без развертывания, скачайте и используйте службу туннелирования ngrok
.
Создание туннеля ngrok, чтобы разрешить Teams доступ к вашему приложению
Скачайте ngrok.
Используйте ngrok для создания туннеля с портом 8080. Выполните следующую команду:
ngrok http 8080 --host-header=localhost
Откроется новый терминал ngrok с новым URL-адресом, например
https:...ngrok.io
. Новый URL-адрес — это туннель, указывающий на ваше приложение, который необходимо обновить вmanifest.json
приложения.
Создание пакета приложения для отправки в Teams
Перейдите в папку примера Dice Roller
live-share-sdk\samples\javascript\01.dice-roller
на своем компьютере. Вы также можете проверить manifest.json из примера Dice Roller на сайте GitHub.Откройте файл manifest.json и обновите URL-адрес конфигурации.
Замените
https://<<BASE_URI_DOMAIN>>
своей конечной точкой HTTP из ngrok.Вы можете обновить следующие поля.
- Настройте для
developer.name
ваше имя. - Обновите
developer.websiteUrl
с использованием вашего веб-сайта. - Обновите
developer.privacyUrl
с использованием вашей политики конфиденциальности. - Обновите
developer.termsOfUseUrl
с применением ваших условий использования.
- Настройте для
Заархивируйте содержимое папки манифеста для создания
manifest.zip
. Убедитесь, чтоmanifest.zip
содержит только исходный файлmanifest.json
, значокcolor
и значокoutline
.- В Windows выберите все файлы в каталоге
.\manifest
и сожмите их.
Примечание.
- Не запаковывайте содержащую папку.
- Присвойте ZIP-файлу описательное имя. Например,
DiceRollerLiveShare
.
Дополнительные сведения о манифесте см. в документации манифеста Teams
- В Windows выберите все файлы в каталоге
Отправка пользовательского приложения на собрание
Откройте Teams.
Запланируйте собрание в календаре Teams. Убедитесь, что вы приглашаете хотя бы одного участника собрания.
Присоединитесь к собранию.
В верхней части окна собрания выберите + Приложения>Управление приложениями.
В области Управление приложениями выберите Отправить пользовательское приложение.
- Если вы не видите параметр Отправить пользовательское приложение, следуйте инструкциям, чтобы включить пользовательские приложения в клиенте.
Выберите и отправьте файл
manifest.zip
со своего компьютера.Нажмите Добавить, чтобы добавить пример приложения в собрание.
Выберите + Приложения, введите "Dice Roller" в поле поиска Найти приложение.
Выберите приложение, чтобы активировать его на собрании.
Нажмите кнопку Сохранить.
Приложение Dice Roller добавляется на панель собрания Teams.
На боковой панели щелкните значок демонстрации на сцене. Teams начинает динамическую синхронизацию с пользователями на сцене текущего собрания.
Теперь на сцене собрания должно появиться приложение Dice-Roller.
Пользователи, приглашенные на собрание, смогут увидеть ваше приложение на сцене после присоединения к собранию.
Развертывание
Когда вы будете готовы развернуть код, вы можете использовать набор средств Teams или портал разработчика Teams для подготовки и отправки ZIP-файла приложения.
Примечание.
Перед отправкой или распространением приложения необходимо добавить подготовленный идентификатор приложения в manifest.json
.
Примеры кода
Название примера | Описание | JavaScript |
---|---|---|
Dice Roller | Включение во всех подключенных клиентах возможности прокрутки игральной кости и просмотра результата. | View |
Следующий этап
См. также
Platform Docs