Обмен данными при взаимодействии с интерфейсом Canvas App
Когда пользователь нажимает на элементы на экране, фронтенд может передавать необходимую информацию в сценарий с помощью запросов SERVER_ACTION
.
Такой же тип запросов используется и для обмена данными в фоне.
Описание обработки взаимодействия с экраном приложения:
Пользователь отмечает запись как сделанную.
Ассистент запрашивает данные об экране приложения (состояние фронтенда) с помощью метода
getState()
.Фронтенд создает сообщение с типом
done
, которое ассистент должен передать в сценарий./src/components/PageNote.tsxconst mutation = useAssistantMutation<DoneNoteCommandInput, DoneNoteCommandOutput, string>(
(noteTitle) => ({ type: 'done', payload: { note: noteTitle } }),
{
onSuccess: (data) => {
markNoteDone(data.id);
},
},
);Ассистент формирует запрос
SERVER_ACTION
и передает его в сценарий.Тип
done
передается в полеpayload.server_action.action_id
.Сценарий определяет запрос по идентификатору:
/src/scenario/scenario.tsDoneNoteAction: {
match: action('done'),
handle: doneNote,
},Для обработки запроса используется функция
doneNote
:/src/scenario/handlers.tsexport const doneNote: SaluteHandler<SaluteRequest<NoteVariable>> = ({ req, res }) => {
const { note } = req.variables;
const item = selectItem({ title: note })(req);
if (note && item?.id) {
//Создание сообщения ANSWER_TO_USER с командой smartapp_data и идентификатором заметки, которую нужно отметить
res.appendCommand<DoneNoteCommand>({
type: 'done_note',
payload: { id: item.id },
});
//Голосовая реплика ассистента
res.setPronounceText('Умничка');
//Реплика ассистента для отображения в чате
res.appendBubble('Умничка');
}
};Сценарий возвращает ассистенту сообщение
ANSWER_TO_USER
с описанием ответа ассистента и изменений фронтенда.Ассистент передает данные для отображения на фронтенде.
Фронтенд использует метод
assistant.on('data', dataHandler);
в файлеsrc/utils/assistant.ts
чтобы обработать сообщение от ассистента.Метод использует обработчик
dataHandler
, логика которого меняется в зависимости от типа команды:/src/utils/assistant.tsexport const dataHandler = (command: AssistantClientCustomizedCommand<AssistantSmartAppData>) => {
let navigation: AssistantNavigationCommand['navigation'] | undefined;
switch (command.type) {
// Обработка голоса ассистента
case 'character':
if (Router.router) {
replaceRouterCharacter(command.character.id);
} else {
waitForRouter().then(() => replaceRouterCharacter(command.character.id));
}
break;
// Обработка навигационной команды
case 'navigation':
navigation = (command as AssistantNavigationCommand).navigation;
break;
// Обработка коанды smart_app_data, которая содержит данные о записи
case 'smart_app_data':
smartAppDataHandler(command.smart_app_data);
break;
default:
break;
}
// Обработка навигационных команд
if (navigation) {
switch (navigation.command) {
case 'UP':
window.scrollTo(0, window.scrollY - 500);
break;
case 'DOWN':
window.scrollTo(0, window.scrollY + 500);
break;
default:
break;
}
}
};Ассистент сообщает пользователю, что дело сделано:
/src/scenario/handlers.ts// Обработчик doneNote
// Задает реплику, которую нужно произнести
res.setPronounceText('Умничка');
// Задает текст сообщения в чате
res.appendBubble('Умничка');Изменение состояния фронтенда и оповещение пользователя выполняются параллельно.