# chatgui ## 1. Назначение Десктопный GUI-чат (Telegram-подобный) со встроенным P2P uTun-узлом. Приложение объединяет полнофункциональный интерфейс обмена сообщениями и децентрализованный транспортный слой в едином процессе. Рассчитан на работу без центральных серверов — вся маршрутизация, синхронизация и доставка сообщений идут напрямую между узлами по ETCP-протоколу. ## 2. Архитектура ### 2.1. Уровни приложения ``` ┌──────────────────────────────────────┐ │ GUI (Qt 6/5 Widgets, C++20) │ поток GUI │ ├─ MainWindow (QSplitter) │ │ ├─ ChannelList / MessageList │ │ ├─ MessageDelegate (бабблы+реакции) │ │ ├─ EmojiPanel (статика+анимация) │ │ └─ LottieIcon / AnimTimer │ ├──────────────────────────────────────┤ │ GuiBridge (Qt signals ↔ uasync) │ очередь событий │ gui_bridge_post / uasync_post │ ├──────────────────────────────────────┤ │ Транспорт (C, поток uasync) │ поток uasync │ ├─ UtunNode (std::thread + UTUN_INSTANCE)│ │ ├─ ChatCore (отправка, БД, invite) │ │ ├─ ChatSync (P2P синхронизация) │ │ ├─ MemberSync (мемберы через Merkle)│ │ └─ MerkleSync (Merkle-дерево, 5 ур.)│ ├──────────────────────────────────────┤ │ libutun (C, статическая библиотека) │ uasync │ ├─ uasync (event loop, таймеры) │ │ ├─ ETCP (надежная доставка, ACK) │ │ ├─ SecureChannel (X25519+AES-CCM) │ │ ├─ conn_mgr (управление подключ.) │ │ ├─ topo_node/topo_group (BGP) │ │ └─ ntp_time (синхронизация времени) │ ├──────────────────────────────────────┤ │ SQLite3 (WAL mode) │ чтение+запись │ ├─ DbManager (C++, read-only для GUI)│ │ └─ chat_core (C, write из uasync) │ └──────────────────────────────────────┘ ``` ### 2.2. Потоковая модель Приложение работает в двух потоках: - **Поток GUI** — QApplication, все виджеты, отрисовка, QTimer для анимаций (AnimTimer 30fps). Только *чтение* из SQLite через DbManager. - **Поток uasync** — UTUN_INSTANCE в выделенном std::thread. Вся сеть, криптография, ETCP, синхронизация, *запись* в SQLite. Один uasync-экземпляр на поток (правило u_async). **Мост между потоками (gui_bridge):** - **uasync → GUI:** `gui_bridge_post(event_type, data, len)` — сериализованные события в Qt main event loop через `QMetaObject::invokeMethod` с `Qt::QueuedConnection`. 10 типов событий: MSG_RECEIVED, CONNECT_RESULT, NEW_PEER, CHANNEL_UPDATED, MEMBERS_CHANGED, MY_NODE_ID, AUTO_CONNECT_STATUS, CHANNEL_PEERS_ONLINE, DB_READY, STATUS_REFRESH. - **GUI → uasync:** `gui_bridge_post_uasync_fn(fn, arg)` — выполнение функции в uasync-потоке через `uasync_post`. Используется для отправки сообщений, создания каналов, invite-подключений. Всё взаимодействие с БД (INSERT/UPDATE/DELETE) выполняется только из uasync-потока. GUI читает через DbManager (read-only), синхронизация не требуется — SQLite в WAL-режиме обеспечивает одновременное чтение. ## 3. Ключевые компоненты ### 3.1. GUI-слой **MainWindow** (`src/mainwindow.h`) — главное окно 900×600. Горизонтальный QSplitter из трёх панелей: - **ChannelList** — список каналов (QListView + QStandardItemModel), контекстное меню (invite, join, create group, settings). - **MessageList** — список сообщений канала (ChatView + QStandardItemModel), поле ввода InputBar, EmojiPanel. - **AccountList** — список участников канала (MemberListModel), онлайн-статус, имена. Системный трей: QSystemTrayIcon + QMenu (показать/скрыть/выход). Закрытие окна сворачивает в трей. **ChatView** (`src/chatview.h`) — QListView с фоновым изображением и drag-to-select. При движении >5px от точки нажатия стартует выделение сообщений. Ctrl+C копирует: для одного — выделенный текст, для нескольких — `[time] author: text`. Сигнал `hoveredIndexChanged` используется для активации анимаций эмодзи в MessageList. **MessageList / MessageDelegate** — баббл-интерфейс сообщений: - Аватары (32×32, цвет зависит от node_id), бабблы со скруглёнными углами (r=10px) и хвостиком. - Цитаты: цветная полоса + мини-аватар + автор + текст. - Реакции (эмодзи) в status bar под бабблом. - Inline-анимированные эмодзи: при hover над сообщением — перебор кадров из LottieIcon, отрисовка поверх текста через QTextLayout. - Растягивающийся InputBar (QTextEdit, Enter — отправка, Shift+Enter — перевод строки). **EmojiPanel** (`src/emojipanel.h`) — QTabWidget с категориями (смайлики, жесты, символы, анимации). Каждая категория — QGridLayout из EmojiButton (QPushButton без Q_OBJECT, hover-анимация через per-widget QTimer). Статические эмодзи — Unicode символы. Анимированные — TGS-файлы, рендерятся в EmojiButton::paintEvent. **LottieIcon** (`src/lottieicon.h`) — загрузка и рендер TGS-анимаций: 1. Gzip-декомпрессия через zlib (`inflateInit2` с `16+MAX_WBITS`) 2. Парсинг Lottie JSON через rlottie C API (`lottie_animation_from_data`) 3. Рендер кадра: `lottie_animation_render` → ARGB32 буфер → QImage 5 встроенных TGS-анимаций (вшиты в бинарник через chatgui.qrc): sparkles, white_flag, greeting, stop_hand, robot. **AnimTimer** (`src/animtimer.h`) — синглтон-таймер 30fps с refcount-механизмом: - `activate()` / `deactivate()` увеличивают/уменьшают счётчик ссылок. - Срабатывает только когда есть активные анимации в видимых сообщениях. - Сигнал `ticked` обновляет кадры всех зарегистрированных LottieIcon. **Invite-ссылки** (`src/invite_link.h`) — кодирование/декодирование приглашений в формат `utun://...` (base64, содержит channel_id, pubkey, список адресов). QR-коды через zxing-cpp. ### 3.2. Транспортный слой **UtunNode** (`transport/utun_node.h`) — C++ обёртка над UTUN_INSTANCE: - Запускает выделенный std::thread с `runLoop()` — создаёт UTUN_INSTANCE, вызывает `utun_instance_start()`, входит в uasync event loop. - Приём сообщений: ETCP callback → `QByteArray` → сигнал `messageReceived(uint64_t src, QByteArray data)`. - Отправка: `send(dstNodeId, data)` через ETCP поверх экземпляра uTun. - Конфигурация: NodeConfig (INI-файл), генерация X25519/Ed25519 ключей при первом запуске. - Включает отладку NTP-синхронизации для временных меток сообщений. **NodeConfig** (`transport/node_config.h`) — управление INI-конфигом uTun-узла: - Генерация ключей (X25519 + Ed25519), сохранение/загрузка. - Секции `[server]` и `[client]` для подключения к другим узлам. - `[gui]` секция: путь к БД, настройки отладки. - ConfigUpdater — утилита для программного изменения конфиг-файлов (append/replace). **ChatCore** (`transport/chat_core.h`) — центральный API чата в потоке uasync: - `chat_core_submit_message` — отправка сообщения: сохранение в локальную БД (таблица `msg_`), рассылка онлайн-пирам через etcp_send. - `chat_core_create_channel` — создание канала: генерация X25519/Ed25519 ключей канала, подпись Ed25519, запись в `channels`, членство владельца. - `chat_core_connect_from_invite` — подключение к пиру из invite-ссылки. - `chat_core_connect_auto` — авто-подключение к узлу из SQLite (topo_node), коллбэк с результатом. - Работа с БД: цепочка хешей (chain hash = SHA256(prev_hash || timestamp || data_hash)), список каналов, список пиров. **ChatSync** (`transport/chat_sync.h`) — P2P синхронизация каналов: - ETCP-сервисы: `0x30` (chat_sync — синхронизация каналов), `0x31` (member_sync — синхронизация участников). - Протокол сообщений: INIT_SYNC → INIT_RESP → SEND_DATA ↔ PUSH+ACK_PUSH → SYNC_DONE. - Batch-загрузка: до 32 сообщений за запрос, sparse-синхронизация (до 16 диапазонов). - Таймаут пира: 5 секунд. - Auto-connect: параллельное подключение до 10 узлов, останавливается при 3 успешных. Переключение группы при смене канала. **MemberSync** (`transport/member_sync.h`) — синхронизация участников канала на основе Merkle-деревьев: - Данные: таблицы `peers_`, `nodes`, `node_addresses`. - Хеш мембера = SHA256(node_id || x25519 || ed25519 || join_sig || join_ts || update_sig || update_ts || addrs). - Автоматический пересчёт дерева при добавлении/удалении/обновлении мембера. - Онлайн-статус: `member_sync_set_online(node_id, 0/1)`. **MerkleSync** (`transport/merkle_sync.h`) — универсальный протокол синхронизации на Merkle-деревьях: - 5-уровневое префиксное дерево над 64-битными ключами (node_id). 32 бакета на уровень (по 5 бит). - SHA256-хеши бакетов. Два пира обмениваются хешами, находят различающиеся бакеты, передают только их. - Wire-протокол: MSG_HASHES → MSG_REQUEST → MSG_BATCH, рекурсивно до совпадения хешей. - Таймаут 10s, 3 ретрая. Фоновая проверка консистентности (`merkle_sync_bg_check`). - Не зависит от типа данных — потребитель предоставляет три коллбэка (update_bucket_hash, get_items, apply_items). member_sync адаптирует это под мемберов каналов. ### 3.3. База данных **DbManager** (`db/db_manager.h`) — C++/Qt обёртка над SQLite3 (read-only для GUI-потока): - **Схема:** `channels` (каналы с ключами X25519/Ed25519, подписи), `msg_` (per-channel таблицы сообщений с chain_hash), `peers_` (участники), `nodes` (узлы), `node_addresses`, `accounts`, `ui_state`, `merkle_tree_hash`. - Чтение: `getChannels()`, `getMessages()`, `getChannelMembers()`, `loadNodeInfo()`, `getAccounts()`. - Методы для GUI: список каналов, сообщения с пагинацией, участники, онлайн-статус. - Sync-операции (курсоры): `syncListChannels()`, `syncCount()`, `syncChainHashAt()`, `syncCursorOpen/Next/Close()`. - Проверка целостности: `integrityCheckQuick()` (PRAGMA quick_check), `integrityCheckFull()` (PRAGMA integrity_check), `integrityOptimize()` (PRAGMA optimize). ## 4. Сборка **Система сборки:** CMake 3.16+ **Стандарты:** C++20 (GUI), C99 (транспорт/libutun) **Зависимости:** - Qt 6 (Widgets + Network) или Qt 5.15+ - rlottie (анимированные эмодзи) - zlib (gzip-декомпрессия TGS) - OpenSSL (X25519, Ed25519, SHA256, AES-CCM) - zxing-cpp (QR-коды, встроен как submodule) **Структура сборки:** - `libutun/` — статическая библиотека uTun: все исходники из `src/` (кроме utun.c) + lib/ (uasync, ll_queue, memory_pool, etc) + транспорт (chat_sync, member_sync, merkle_sync) - `chatgui` — финальный бинарник: GUI-исходники + транспортные C++/C файлы + SQLite3 amalgamation - Платформенный TUN: `tun_linux.c` / `tun_freebsd.c` / `tun_windows.c` ```bash mkdir -p build && cd build cmake .. && make -j4 ./chatgui ``` ## 5. Файловая структура ``` tools/chatgui/ ├── CMakeLists.txt # проект CMake ├── build.sh / build.bat # скрипты сборки ├── src/ # GUI-слой (Qt C++) │ ├── main.cpp # точка входа, QApplication │ ├── mainwindow.cpp # главное окно, трей │ ├── channellist.cpp # список каналов │ ├── chatview.cpp # QListView с фоном и drag-to-select │ ├── messagelist.cpp # модель сообщений, инициализация анимаций │ ├── messagedelegate.cpp # отрисовка бабблов, цитат, реакций, эмодзи │ ├── inputbar.cpp # поле ввода + кнопка эмодзи │ ├── emojipanel.cpp # QTabWidget с категориями эмодзи │ ├── emojitabbar.cpp # кастомный QTabBar │ ├── emoji.cpp # данные эмодзи, builtinEmojiSet() │ ├── lottieicon.cpp # загрузка TGS, рендер через rlottie │ ├── animtimer.cpp # синглтон-таймер 30fps с refcount │ ├── accountlist.cpp # список участников канала │ ├── memberlistmodel.cpp # модель для AccountList │ ├── invite_link.cpp # кодирование/декодирование utun:// ссылок │ ├── invitedialog.cpp # диалог приглашения │ ├── joindialog.cpp # диалог входа по invite-ссылке │ ├── settingsdialog.cpp # окно настроек │ ├── networksettingspage.cpp # страница сетевых настроек │ ├── databasesettingspage.cpp # настройки БД │ ├── statuspage.cpp # страница статуса │ ├── creategroupdialog.cpp # создание группы │ └── qrcode_utils.cpp # генерация QR-кодов ├── transport/ # транспортный слой (C/C++) │ ├── utun_node.cpp # C++ обёртка UTUN_INSTANCE в std::thread │ ├── node_config.cpp # INI-конфиг узла (ключи, серверы, клиенты) │ ├── config_updater.cpp # утилита редактирования INI-файлов │ ├── gui_bridge_impl.cpp # мост uasync↔Qt (10 типов событий) │ ├── chat_core.c # центральный API чата (отправка, БД, invite) │ ├── chat_sync.c # P2P синхронизация каналов (ETCP 0x30) │ ├── member_sync.c # синхронизация мемберов через Merkle │ └── merkle_sync.c # универсальный Merkle-протокол синхронизации ├── db/ # база данных │ ├── db_manager.h/cpp # C++/Qt обёртка SQLite3 (read-only для GUI) │ └── sqlite3.c/h # SQLite3 amalgamation (из ../../lib/) ├── libutun/ # сборка статической библиотеки uTun │ └── CMakeLists.txt # uasync + utun = все .c из lib/ и src/ ├── resources/ # ресурсы │ ├── chatgui.qrc # Qt resource file (TGS вшиты в бинарник) │ └── animations/ # TGS-анимации (5 шт.) └── doc/ # документация ├── desc.txt # описание схемы БД └── db_schema.md # детальная схема таблиц SQLite ```