67 lines
6.3 KiB
Markdown
67 lines
6.3 KiB
Markdown
# Приглашение в группу через PM
|
||
|
||
В desktop chatgui и Android кнопка «+» доступна в строке другого участника
|
||
и в шапке личной беседы. Она открывает один диалог с фиксированным получателем
|
||
и выбором группы, в которой отправитель состоит. Группа не выбирается автоматически.
|
||
|
||
После нажатия «Пригласить» клиент создаёт свежую ссылку через `invite_build`,
|
||
ожидает подтверждения регистрации ключа и отправляет PM с `ct="invite"`.
|
||
Зашифрованное тело: `[group_name:UTF8][NUL][полная ссылка:UTF8]`, без конечного NUL.
|
||
Снимок для GUI содержит полную ссылку в `data` и название в `tags.group_name`.
|
||
GUI добавляет заголовок «Приглашение в группу «название»» из перевода интерфейса;
|
||
язык отправителя не фиксирует язык сообщения у получателя.
|
||
Успех означает сохранение сообщения и исходящей задачи в одной транзакции.
|
||
Доставку, повтор и шифрование обеспечивает существующий механизм DM.
|
||
После успешной отправки открывается личная беседа с получателем.
|
||
|
||
Срок действия ключа — **10 минут с момента создания**, а не получения PM.
|
||
Он указан в диалогах отправки и подключения. Поздняя offline-доставка
|
||
может принести уже просроченную ссылку; в этом случае нужно новое приглашение.
|
||
Ссылка не содержит время истечения, поэтому клиент показывает длительность,
|
||
без обратного отсчёта и вычисления оставшегося времени.
|
||
|
||
Нажатие на `utun://` в сообщении запускает существующий JOIN и показывает его результат.
|
||
Если клиент уже состоит в группе, открывается эта группа. Ссылка приглашения отображается
|
||
одной строкой с многоточием; нажатие и копирование используют полный адрес.
|
||
В Android долгое нажатие копирует ссылку, в desktop выделение сокращённой строки
|
||
копирует ссылку целиком без запуска JOIN. Обычные текстовые PM с вручную
|
||
вставленными ссылками сохраняют текстовое отображение.
|
||
|
||
## Контракт операции
|
||
|
||
`dm_invite_trampoline` выполняется в uasync-потоке. Запрос содержит `request_id`,
|
||
ID получателя, выбранную группу и исходную общую группу для создания PM.
|
||
Из шапки существующей PM исходная группа может быть пустой.
|
||
|
||
На instance допускается одно ожидание регистрации приглашения в PM.
|
||
Повтор во время ожидания возвращает BUSY. Закрытие диалога отменяет только
|
||
соответствующий `request_id`; уже отправленное сообщение не отзывается.
|
||
Отмена и остановка DM завершают принятый запрос ровно один раз.
|
||
|
||
`CHAT_EVT_DM_INVITE_RESULT` содержит 28 байт:
|
||
`[request_id:u64][result:i32][peer:u64][conv_id:u64]` в порядке байтов ядра.
|
||
Desktop и Android сопоставляют результат с запросом и получателем.
|
||
Ошибки регистрации или сохранения сообщения оставляют диалог открытым для повторной попытки.
|
||
|
||
JOIN во вторую группу может использовать уже открытый транспорт общей группы.
|
||
Поэтому обработчики JOIN_REQUEST и JOIN_READY явно планируют member_sync,
|
||
а JOIN_READY обновляет кеш каналов до запуска синхронизации.
|
||
|
||
## Проверка и диагностика
|
||
|
||
- `tests/test_dm_invite`: настоящая UDP-доставка ссылки в другую группу, JOIN,
|
||
репликация участника и отправка группового сообщения после вступления;
|
||
отмена, BUSY, неверная группа, rollback при ошибке commit и остановка DM;
|
||
передача названия с Unicode, кавычками и переводом строки.
|
||
- `tests/test_chat_join`, `tests/test_chat_join_e2e`, `tests/test_dm_e2e`:
|
||
существующие сценарии регистрации ключей, JOIN и PM-доставки.
|
||
- Qt `test_invite_links`: одна строка приглашения на разных ширинах, полный адрес
|
||
при нажатии и копировании, переносы двух обычных ссылок, их полное содержимое при нажатии,
|
||
выделение текста и выбор получателя кнопкой в строке участника.
|
||
- Qt `test_emoji_playback`: перетаскивание ссылки не активирует подключение.
|
||
|
||
Для сетевого теста подробности включаются через `UTUN_TEST_DEBUG=1`.
|
||
В приложении полезны категории `dm=debug`, `chat_sync=debug`, `member_sync=debug`.
|
||
Операция пишет request, peer, group, результат и TTL; сообщения диагностики
|
||
новой операции не выводят саму invite-ссылку.
|