feat: implement Phase 11 — inline photo viewing with ratatui-image

Add feature-gated (`images`) inline photo support:
- New types: MediaInfo, PhotoInfo, PhotoDownloadState, ImagesConfig
- Media module: ImageCache (LRU filesystem cache), ImageRenderer (terminal protocol detection)
- Photo metadata extraction from TDLib MessagePhoto with download_file() API
- ViewImage command (v/м) to toggle photo expand/collapse in message selection
- Two-pass UI rendering: placeholder lines in message bubbles + StatefulImage overlay
- Collapse all expanded photos on Esc (exit selection mode)

Dependencies: ratatui-image 8.1, image 0.25 (optional, behind `images` feature flag)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Mikhail Kilin
2026-02-06 21:25:17 +03:00
parent 6845ee69bf
commit b0f1f9fdc2
29 changed files with 1505 additions and 102 deletions

View File

@@ -1,6 +1,6 @@
# Текущий контекст проекта
## Статус: Фазы 1-10, 13 завершены. Следующие: Фаза 11 (изображения) или 12 (голосовые)
## Статус: Фаза 11 — Inline просмотр фото (DONE)
### Завершённые фазы (краткий итог)
@@ -16,8 +16,19 @@
| 8 | Дополнительные фичи (markdown, edit/delete, reply/forward, блочный курсор) | DONE |
| 9 | Расширенные возможности (typing, pinned, поиск в чате, черновики, профиль, копирование, реакции, конфиг) | DONE |
| 10 | Desktop уведомления (notify-rust, muted фильтр, mentions, медиа) | DONE (83%) |
| 11 | Inline просмотр фото (ratatui-image, кэш, загрузка) | DONE |
| 13 | Глубокий рефакторинг архитектуры (7 этапов) | DONE |
### Фаза 11: Inline фото (подробности)
5 шагов, feature-gated (`images`):
1. **Типы + зависимости**: `MediaInfo`, `PhotoInfo`, `PhotoDownloadState`, `ImagesConfig`; `ratatui-image 8.1`, `image 0.25`
2. **Метаданные + API**: `extract_media_info()` из TDLib MessagePhoto; `download_file()` в TdClientTrait
3. **Media модуль**: `ImageCache` (LRU, `~/.cache/tele-tui/images/`), `ImageRenderer` (Picker + StatefulProtocol)
4. **ViewImage команда**: `v`/`м` toggle; collapse all on Esc; download → cache → expand
5. **UI рендеринг**: photo status в `message_bubble.rs` (Downloading/Error/placeholder); `render_images()` второй проход с `StatefulImage`
### Фаза 13: Рефакторинг (подробности)
Разбиты 5 монолитных файлов (4582 строк) на модульную архитектуру:
@@ -37,6 +48,7 @@ main.rs → event loop (16ms poll)
├── input/ → роутер + handlers/ (chat, chat_list, compose, modal, search)
├── app/ → App<T: TdClientTrait> + methods/ (5 traits, 67 методов)
├── ui/ → рендеринг (messages, chat_list, modals/, compose_bar, components/)
├── media/ → [feature=images] cache.rs, image_renderer.rs
└── tdlib/ → TDLib wrapper (client, auth, chats, messages/, users, reactions, types)
```
@@ -56,15 +68,18 @@ main.rs → event loop (16ms poll)
3. **FakeTdClient**: mock для тестов без TDLib (реализует TdClientTrait)
4. **Оптимизация рендеринга**: `needs_redraw` флаг, рендеринг только при изменениях
5. **Конфиг**: TOML `~/.config/tele-tui/config.toml`, credentials с приоритетом (XDG → .env)
6. **Feature-gated images**: `images` feature flag для ratatui-image + image deps
### Зависимости (основные)
```toml
ratatui = "0.29" # TUI фреймворк
crossterm = "0.28" # Терминальный backend
tdlib-rs = "1.1" # Telegram TDLib binding
tokio = "1" # Async runtime
notify-rust = "4.11" # Desktop уведомления (feature flag)
ratatui = "0.29" # TUI фреймворк
crossterm = "0.28" # Терминальный backend
tdlib-rs = "1.1" # Telegram TDLib binding
tokio = "1" # Async runtime
notify-rust = "4.11" # Desktop уведомления (feature flag)
ratatui-image = "8.1" # Inline images (feature flag)
image = "0.25" # Image decoding (feature flag)
```
Полная структура проекта: см. [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md)