Files
telegram-tui/ROADMAP.md
Mikhail Kilin 6d08300daa feat: implement audio seeking with arrow keys via ffplay restart
Seek now works by restarting ffplay with -ss offset instead of the
broken player.seek() stub. MoveLeft/MoveRight added as aliases for
SeekBackward/SeekForward to fix HashMap non-deterministic iteration
order causing Left arrow to resolve to MoveLeft instead of SeekBackward.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 18:51:45 +03:00

96 lines
6.6 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 |
| 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
---
## Фаза 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)