feat: implement photo albums (media groups) and persist account selection

Group photos with shared media_album_id into single album bubbles with
grid layout (up to 3x cols). Album navigation treats grouped photos as
one unit (j/k skip entire album). Persist selected account to
accounts.toml so it survives app restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-22 16:18:04 +03:00
parent 8bd08318bb
commit 78fe09bf11
18 changed files with 1011 additions and 30 deletions

View File

@@ -2,6 +2,48 @@
## Статус: Фаза 14 — Мультиаккаунт (IN PROGRESS)
### Photo Albums (Media Groups) — DONE
Фото-альбомы (несколько фото в одном сообщении) теперь группируются в один пузырь с сеткой фото.
**Проблема**: TDLib отправляет альбомы как отдельные `Message` с общим `media_album_id: i64`. Ранее проект это поле игнорировал — каждое фото отображалось как отдельный пузырь.
**Решение:**
1. **Data Model**`media_album_id: i64` в `MessageMetadata`, `MessageBuilder`, getter `MessageInfo::media_album_id()`. Оба конвертера (async + sync) передают поле из TDLib.
2. **Message Grouping** — новый вариант `MessageGroup::Album(Vec<MessageInfo>)`. Сообщения с одинаковым `media_album_id != 0` группируются; одиночное сообщение с album_id остаётся `Message`.
3. **Album Grid Constants**`ALBUM_PHOTO_WIDTH: 16`, `ALBUM_PHOTO_HEIGHT: 8`, `ALBUM_PHOTO_GAP: 1`, `ALBUM_GRID_MAX_COLS: 3` (3×16 + 2×1 = 50 = `INLINE_IMAGE_MAX_WIDTH`).
4. **`render_album_bubble()`** — сетка фото (до 3 в ряд), `DeferredImageRender` с `x_offset` для каждого фото, общая подпись и timestamp, индикация выбора, статусы загрузки.
5. **Integration**`Album` arm в `render_message_list`, `x_offset` в second pass. Без feature `images` — fallback через отдельные bubble.
**Модифицированные файлы:**
- `src/tdlib/types.rs``media_album_id` в `MessageMetadata`, `MessageBuilder`, getter
- `src/tdlib/messages/convert.rs` — передача `media_album_id` в builder
- `src/tdlib/message_converter.rs` — передача `media_album_id` в builder
- `src/message_grouping.rs``Album` variant + album detection + 4 новых теста
- `src/constants.rs` — album grid constants
- `src/ui/components/message_bubble.rs``x_offset` в `DeferredImageRender`, `render_album_bubble()`
- `src/ui/components/mod.rs` — export `render_album_bubble`
- `src/ui/messages.rs``Album` arm + `x_offset` в second pass
6. **Навигация j/k по альбомам** — альбом обрабатывается как одно сообщение. `select_previous_message()` / `select_next_message()` перескакивают через все сообщения альбома. `start_message_selection()` встаёт на первый элемент альбома если последнее сообщение — часть альбома.
7. **Тесты** — 4 unit-теста в `message_grouping.rs`, 5 snapshot-тестов в `tests/messages.rs`, 3 теста навигации в `tests/input_navigation.rs`.
**Дополнительно модифицированные файлы:**
- `src/app/methods/messages.rs` — навигация перескакивает альбомы
- `tests/helpers/test_data.rs``TestMessageBuilder::media_album_id()`
- `tests/messages.rs` — 5 snapshot-тестов для альбомов
- `tests/input_navigation.rs` — 3 теста навигации по альбомам
**Что НЕ меняется:** image modal (v), auto-download, одиночные фото.
---
### Оптимизация: Ленивая загрузка сообщений при открытии чата (DONE)
Чат открывается мгновенно (< 1 сек) вместо 5-30 сек для больших чатов.