Files
telegram-tui/ROADMAP.md
Mikhail Kilin 8bd08318bb
Some checks failed
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
fixes
2026-02-14 17:57:37 +03:00

171 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Roadmap
## Завершённые фазы
| Фаза | Описание | Ключевые результаты |
|------|----------|---------------------|
| 1 | Базовая инфраструктура | ratatui + crossterm, vim-навигация, русская раскладка |
| 2 | TDLib интеграция | tdlib-rs, авторизация, загрузка чатов и сообщений |
| 3 | Улучшение UX | Отправка, поиск, скролл, realtime обновления |
| 4 | Папки и фильтрация | Загрузка папок из Telegram, переключение 1-9 |
| 5 | Расширенный функционал | Онлайн-статус, галочки прочтения, медиа-заглушки, muted |
| 6 | Полировка | 60 FPS, оптимизация памяти, graceful shutdown, динамический инпут |
| 7 | Рефакторинг памяти | Единый источник данных, LRU-кэш (500 users), lazy loading |
| 8 | Дополнительные фичи | Markdown, edit/delete, reply/forward, блочный курсор |
| 9 | Расширенные возможности | Typing, pinned, поиск в чате, черновики, профиль, копирование, реакции, конфиг |
| 10 | Desktop уведомления (83%) | notify-rust, muted фильтр, mentions, медиа. TODO: кастомные звуки |
| 11 | Inline просмотр фото | Dual renderer (Halfblocks + iTerm2/Sixel), throttling 15 FPS, modal viewer, lazy loading, auto-download |
| 12 | Голосовые сообщения | ffplay player, pause/resume with seek, VoiceCache, AudioConfig, progress bar + waveform UI |
| 13 | Глубокий рефакторинг | 5 файлов (4582->модули), 5 traits, shared components, docs |
---
## Фаза 11: Inline просмотр фото в чате [DONE]
**UX**: Always-show inline preview (50 chars, Halfblocks) -> `v`/`м` открывает fullscreen modal (iTerm2/Sixel) -> `←`/`→` навигация между фото.
### Реализовано:
- [x] **Dual renderer архитектура**:
- `inline_image_renderer`: Halfblocks (быстро, Unicode блоки) для навигации
- `modal_image_renderer`: iTerm2/Sixel (медленно, высокое качество) для просмотра
- [x] **Performance optimizations**:
- Frame throttling: inline 15 FPS, текст 60 FPS
- Lazy loading: только видимые изображения
- LRU cache: max 100 протоколов
- Skip partial rendering (no flickering)
- [x] **UX улучшения**:
- Always-show inline preview (фикс. ширина 50 chars)
- Fullscreen modal на `v`/`м` с aspect ratio
- Loading indicator в модалке
- Navigation hotkeys: `←`/`→` между фото, `Esc`/`q` закрыть
- [x] **Типы и API**:
- `MediaInfo`, `PhotoInfo`, `PhotoDownloadState`, `ImageModalState`
- `ImagesConfig` в config.toml
- Feature flag `images` для зависимостей
- [x] **Media модуль**:
- `cache.rs`: ImageCache (LRU)
- `image_renderer.rs`: new() + new_fast()
- [x] **UI модули**:
- `modals/image_viewer.rs`: fullscreen modal
- `messages.rs`: throttled second-pass rendering
- [x] **Авто-загрузка фото** (bugfix):
- Auto-download последних 30 фото при открытии чата (`open_chat_and_load_data`)
- Download on demand по `v` (вместо "Фото не загружено")
- Retry при ошибке загрузки
- Конфиг: `auto_download_images` + `show_images` в `[images]`
---
## Фаза 12: Прослушивание голосовых сообщений [DONE]
### Этап 1: Инфраструктура аудио [DONE]
- [x] Модуль `src/audio/`
- `player.rs` — AudioPlayer на ffplay (subprocess)
- `cache.rs` — VoiceCache (LRU, configurable size, `~/.cache/tele-tui/voice/`)
- [x] AudioPlayer API: play(), play_from(ss), pause() (SIGSTOP), resume(), resume_from(ss), stop()
- [x] Race condition fix: `starting` flag + pid ownership guard в потоках
- [x] Drop impl для AudioPlayer (убивает ffplay при выходе)
### Этап 2: Интеграция с TDLib [DONE]
- [x] Типы: `VoiceInfo`, `VoiceDownloadState`, `PlaybackState`, `PlaybackStatus`
- [x] Конвертация `MessageVoiceNote` в `message_conversion.rs`
- [x] `download_voice_note()` в TdClientTrait + client_impl + fake
- [x] Методы `has_voice()`, `voice_info()`, `voice_info_mut()` на `MessageInfo`
### Этап 3: UI для воспроизведения [DONE]
- [x] Progress bar (━●─) с позицией и длительностью
- [x] Waveform визуализация (▁▂▃▄▅▆▇█) из base64-encoded TDLib данных
- [x] Иконки статуса: ▶ Playing, ⏸ Paused, ⏹ Stopped
- [x] Throttled redraw: обновление UI только при смене секунды (не 60 FPS)
### Этап 4: Хоткеи [DONE]
- [x] Space — play/pause toggle (запуск + пауза/возобновление с откатом 1s)
- [x] ←/→ — seek ±5 сек (через `resume_from()` — перезапуск ffplay с `-ss`)
- [x] Seek работает и при воспроизведении, и на паузе (на паузе двигает позицию, при resume стартует с неё)
- [x] MoveLeft/MoveRight как alias для SeekBackward/SeekForward (HashMap non-deterministic order fix)
- [x] Автоматическая остановка при навигации на другое сообщение
- [x] Остановка ffplay при выходе из приложения (Ctrl+C)
### Этап 5: Конфигурация и кэш [DONE]
- [x] `AudioConfig` в config.toml (`cache_size_mb`, `auto_download_voice`)
- [x] `DEFAULT_AUDIO_CACHE_SIZE_MB` константа (100 MB)
- [x] Ticker для progress bar в event loop (delta-based position tracking)
- [x] VoiceCache интеграция: проверка кэша перед загрузкой, кэширование после download
### Технические детали
- **Аудио:** ffplay (subprocess), resume/seek через перезапуск с `-ss` offset
- **Race conditions:** `starting` flag предотвращает false `is_stopped()` при старте ffplay; pid ownership guard в потоках предотвращает затирание pid нового процесса старым
- **Keybinding conflict:** Left/Right привязаны к MoveLeft/MoveRight и SeekBackward/SeekForward; HashMap iteration order не гарантирован → оба варианта обрабатываются как seek в режиме выбора сообщения
- **Платформы:** macOS, Linux (везде где есть ffmpeg)
- **Хоткеи:** Space (play/pause), ←/→ (seek ±5s)
---
## Фаза 14: Мультиаккаунт
**Цель**: поддержка нескольких Telegram-аккаунтов с мгновенным переключением внутри приложения.
### UI: Индикатор в footer + хоткеи
```
┌──────────────┬───────────────────────────┐
│ Saved Msgs │ Привет! │
│ Иван Петров │ Как дела? │
│ Работа чат │ │
├──────────────┴───────────────────────────┤
│ [NORMAL] Михаил ⟨1/2⟩ Work(3) │ Ctrl+A │
└──────────────────────────────────────────┘
```
- **Footer**: текущий аккаунт + номер `⟨1/2⟩` + бейджи непрочитанных с других аккаунтов
- **Быстрое переключение**: `Ctrl+1`..`Ctrl+9` — мгновенный switch без модалки
- **Модалка управления** (`Ctrl+A`): список аккаунтов, добавление/удаление, выбор активного
### Модалка переключения аккаунтов
```
┌──────────────────────────────────┐
│ Аккаунты │
│ │
│ 1. Михаил (+7 900 ...) ● │ ← активный
│ 2. Work (+7 911 ...) (3) │ ← 3 непрочитанных
│ 3. + Добавить аккаунт │
│ │
│ [j/k навигация, Enter выбор] │
│ [d — удалить аккаунт] │
└──────────────────────────────────┘
```
### Техническая реализация: все клиенты одновременно
- **Несколько TdClient**: каждый аккаунт — отдельный `TdClient` со своим `database_directory`
- Аккаунт 1: `~/.local/share/tele-tui/accounts/1/tdlib_data/`
- Аккаунт 2: `~/.local/share/tele-tui/accounts/2/tdlib_data/`
- **Все клиенты активны**: polling updates со всех аккаунтов одновременно (уведомления, непрочитанные)
- **Мгновенное переключение**: swap активного `App.td_client` — чаты и сообщения уже загружены
- **Общий конфиг**: `~/.config/tele-tui/config.toml` (один для всех аккаунтов)
- **Профили аккаунтов**: `~/.config/tele-tui/accounts.toml` — список аккаунтов (имя, путь к БД)
### Этапы
- [x] **Этап 1: Инфраструктура профилей** (DONE)
- Структура `AccountProfile` (name, display_name, db_path)
- `accounts.toml` — хранение списка аккаунтов
- Миграция `tdlib_data/``accounts/default/tdlib_data/` (обратная совместимость)
- CLI: `--account <name>` для запуска конкретного аккаунта
- [x] **Этап 2+3: Account Switcher Modal + Переключение** (DONE)
- Подход: single-client reinit (close TDLib → new TdClient → auth)
- Модалка `Ctrl+A` — глобальный оверлей с навигацией j/k
- Footer индикатор `[account_name]` если не "default"
- `AccountSwitcherState` enum (SelectAccount / AddAccount)
- `recreate_client()` метод в TdClientTrait (close → new → set_tdlib_parameters)
- `add_account()` — создание нового аккаунта из модалки
- `pending_account_switch` флаг → обработка в main loop
- [ ] **Этап 4: Расширенные возможности мультиаккаунта**
- Удаление аккаунта из модалки
- Хоткеи `Ctrl+1`..`Ctrl+9` — быстрое переключение
- Бейджи непрочитанных с других аккаунтов (требует множественных TdClient)
- Параллельный polling updates со всех аккаунтов