Browse Source

Document avatar storage, profile exchange and client caching

master
evgeny 6 days ago
parent
commit
9842de7ab7
  1. 62
      doc/member_files.txt
  2. 2
      src/chat/chat_join.h

62
doc/member_files.txt

@ -245,6 +245,9 @@ member_files_transfer_start(request, callback, arg) копирует request и
отдельный mf_transfer* на каждый файл. upload задаёт направление, group/server/owner
выбираются для каждой операции. id=0 выбирает случайный ID; id в callback — фактический.
NULL означает отказ запуска без callback; причина пишется в лог.
max_bytes=0 оставляет прежний лимит; ненулевое значение ограничивает размер файла.
Upload проверяет размер источника до хеширования, download — ответ STAT до открытия
локального temp. STREAM привязан к проверенным размеру/version; превышение — INVALID_RANGE.
callback(arg, mf_transfer_progress*) получает id/done/total/status/finished.
Прогресс заимствован до возврата callback. done для отправителя означает байты,
@ -259,6 +262,65 @@ Stop сервиса/группы завершает все принадлежа
тот же API и превращают callback в существующие события прогресса; Qt не делает I/O.
Один локальный файл назначения не может одновременно принадлежать двум download.
Аватарки пользователей
---------------------
Относительный путь avatars/<sha256>.png находится внутри обычного дерева UID:
<корень>/<group>/<UID>/avatars/<sha256>.png. Дополнительного UID в API/пути нет.
Аватарка по умолчанию копируется в каждую группу, где выбранный сервер имеет
подписанную storage-роль. Ссылка каждого канала публикуется только после COMMIT
соответствующей копии; отсутствующий сервер в другом канале не создаёт битую ссылку.
Новое членство обнаруживается через снимки участников и повторяет публикацию.
Между серверами автоматического копирования нет.
userinfo содержит строковые avatar_server (16 hex цифр) и avatar_file (64 hex SHA256 + .png).
Оба поля отсутствуют при удалённой аватарке. Профиль подписан ключом участника;
смена имени/адресов сохраняет остальные плоские JSON-атрибуты. userinfo ограничен
1024 байтами UTF-8. Merkle, JOIN_INFO_RESP, CHANNEL_INVITE и JOIN_REQUEST используют
длину userinfo:u16 BE вместо прежнего u8. Bootstrap передаёт существующий подписанный
профиль инвайтера, не создавая более свежую запись только с именем. Обе стороны
нужно обновить: обратной совместимости нет.
Снимок участника CHAT_MEMBER_DISPLAY_SIZE теперь 157 байт: прежние 79 байт,
avatar_server:8LE, avatar_file:69 (с NUL), storage_role:1. storage_role обозначает
подписанную роль сервера, независимо от существующей колонки storage — сетевого
приоритета, который может быть 0 у сервера за NAT. Потребители используют общий
chat_member.h; локальное изменение профиля также вызывает MEMBER_UPDATED.
В Settings → Profile доступны Upload avatar, выбор storage-сервера, предпросмотр
и Remove avatar. Изменения применяются сразу, независимо от Save других настроек.
Worker проверяет размер входного изображения (до 16 мегапикселей), обрезает центральный
квадрат и сохраняет статический PNG 256×256. Файл ограничен 1 МиБ. Сервер проверяет
каноническое имя/SHA256, размер и запрещает замену под прежним именем и rename
в/из avatars. Файлы и каталог входят в обычные инкрементальные квоты/счётчики.
Прежние версии сохраняются на сервере; владелец может удалить их через файловый браузер.
AvatarManager общий для списка участников и сообщений, максимум две операции
одновременно, одинаковые хеши не скачиваются параллельно. Изменение своего профиля
имеет приоритет перед фоновыми загрузками. Для DM используются ссылки из общих
каналов; при отсутствии доступной ссылки остаются инициалы. Онлайн-статус списка
отображается отдельной точкой поверх фотографии. Поздний результат старой ссылки
пополняет кеш, но не заменяет картинку новой ссылки.
Кеш аккаунта: <db_path>/avatar_cache/<local_UID_hex>/<sha256>.png; без db_path
используется Qt AppLocalDataLocation. Проверяются SHA256 и квадратный PNG до 512×512;
превышение/битая картинка не публикуются. Публикация кеша атомарна через QSaveFile,
незавершённые download/part очищаются при старте. Готовые файлы не требуют TTL/STAT:
смена содержимого меняет имя. Дисковый LRU — 100 МиБ, кеш QImage — 32 МиБ;
собственная аватарка и источники незавершённых upload сохраняются при вытеснении.
Дисковое I/O и декодирование выполняются вне GUI/uasync. Повторы неудачных загрузок:
5/10/20/40/80/160 секунд; новая ссылка сбрасывает задержку. RTT/online не меняют ссылку
и не вызывают повторной загрузки. Желаемая собственная ссылка/удаление сохраняются
атомарно одной строкой ui_state.avatar_default, незавершённая публикация повторяется
после запуска при наличии локального источника.
test_avatars проверяет нормализацию, хеш/размеры, очистку temp, настоящее storage
в двух каналах, публикацию, сохранение при смене имени, DM-кеш, restart без сети,
автоматический download после потери кеша и удаление ссылок. test_member_adapter
проверяет подписанные профили 191/255/256/512/1023/1024 байт вместе с adm_tags до 8192.
Категория media=debug показывает discovery, cache hit/eviction, направление,
group/owner/server/hash, ошибки проверки и retry; media=info — передачи/публикации.
Проверки и диагностика
---------------------

2
src/chat/chat_join.h

@ -109,7 +109,7 @@ struct join_member_data {
uint64_t join_ts; /* время подписи вступления, Unix seconds */
const uint8_t* update_sig; /* 64, может быть NULL */
uint64_t update_ts; /* версия подписанного блока участника */
char userinfo[1025]; /* JSON до MS_USERINFO_MAX байт, null-terminated */
char userinfo[MS_USERINFO_MAX + 1]; /* JSON, null-terminated */
};
/* Сериализовать member-блок (без join_key). Возвращает 0 и *out_len, -1 если не влез. */

Loading…
Cancel
Save