Refresh both AGENTS guides and clarify module purpose, usage, ownership, threading, return values and wire formats in headers. Remove the unused timeout_heap freed_count field and unimplemented getter.
Add battery optimization controls and configurable boot startup. Keep message sounds in the application and render general settings lazily to avoid ANRs. Add animated emoji controls and live BGP availability for direct-message calls on Android and desktop.
Новый модуль src/radio (radio/radio_audio/radio_headless) — push-to-talk
радио поверх topo-групп, доставка аудио в канал, headless-режим и тесты.
Интеграция в chatgui (ptt_hotkey_manager, radio_audio_engine, радионастройки,
вызовы) и chatgui-android (RadioAudioEngine, RadioOverlayService, UI).
- chatgui: просмотрщик изображений (ImageViewerWindow) с зумом/поворотом
- chatgui: отправка картинок как image с определением разрешения и типа
- chatgui: у видео-пузыря строка info (res·size·bitrate) и бейдж только длительность
- chatgui: контекстное меню медиа (сохранить в файл/скачать)
- chatgui-android: большие emoji-only сообщения, битрейт/разрешение у видео
- chatgui-android: сохранение неактивных интерфейсов как закомментированные секции
- chatgui-android: отправка картинок по расширению (jpg/png/gif/bmp/webp)
- photo_sender: content-type и расширение по типу файла
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
Root cause: librlottie RleTaskScheduler creates 32 worker threads on first
lottie_animation_from_data call. These pthreads wait in WaitForMultipleObjects(INFINITE)
and never exit. On MinGW, exit()/pthread_join blocks forever.
Changes:
- messagelist: s_icons moved to file-static; cleanupAnimations() clears them,
calling lottie_animation_destroy BEFORE static destruction
- mainwindow: ~MainWindow calls MessageList::cleanupAnimations() after node stop
- main: ShutdownSentinel counts threads at exit; if >4 remaining, calls
ExitProcess(0) to bypass CRT pthread_join hang
- main: if rlottie properly shuts down (<=4 threads), normal return (no ExitProcess)
- Same-channel refresh: save scroll pos in memory, restore from memory (no DB race)
- Force m_readDebounce->start() after loadChannel (scrollToBottom may not trigger valueChanged)
- DEBUG_DEBUG logs in updateReadPosition, saveChannelState, onMessageReceived, setChannelUnreadCount
- Debounce timer (300ms) advances lastReadMsgId only when message is fully in viewport
- Unread badge no longer resets on channel select — only when actual scroll reads msgs
- saveChannelState() uses tracked m_lastReadMsgId instead of viewport bottom
- getChannels() reads lastReadMsgId from ui_state (was reading unused channels column)
Store read/scroll positions per channel via ui_state table (key-value).
Draw red +N badge on channel list items for unread messages.
Fix getMessages() to fetch last N messages (was fetching first N).