Documented new feature for playing voice messages directly from TUI with full playback controls and visual feedback. Documentation Changes: - ROADMAP.md: Added Phase 12 with 7 stages - Stage 1: Audio infrastructure (audio module, AudioPlayer, VoiceCache) - Stage 2: TDLib integration (VoiceNoteInfo, download_voice_note) - Stage 3: UI for playback (progress bar, status indicators, footer) - Stage 4: Hotkeys (play/pause, stop, seek, volume control) - Stage 5: Configuration and UX (AudioConfig, ticker updates) - Stage 6: Error handling and fallback (system player) - Stage 7: Additional improvements (prefetching, animations) - CONTEXT.md: Added PLANNED section for Phase 12 - Technical stack: rodio 0.17, TDLib downloadFile - Platforms: Linux (ALSA/PulseAudio), macOS (CoreAudio), Windows (WASAPI) - Architecture: src/audio/ module with 3 submodules - LRU cache (100 MB limit) - Async loading, ticker for progress updates - Configuration options in config.toml - Fallback to system players (mpv, ffplay) - HOTKEYS.md: Added new hotkeys - `Space` - play/pause (in voice message selection mode) - `s` / `ы` - stop playback - `←` / `→` - seek -5s/+5s (during playback) - `↑` / `↓` - volume +/-10% (during playback) - Added new "Voice Playback" section - Added new "Voice Playback Mode" section - PROJECT_STRUCTURE.md: Added audio/ module documentation - player.rs - AudioPlayer with rodio - cache.rs - VoiceCache for downloaded OGG files - state.rs - PlaybackState (status, position, duration, volume) - Updated dependencies section (rodio 0.17) - Updated App state with audio fields Technical Details: - rodio 0.17 Pure Rust audio library (cross-platform) - OGG Opus support (Telegram voice message format) - Visual progress bar: ▶ ████████░░░░░░ 0:08 / 0:15 - Status indicators: ▶ (playing), ⏸ (paused), ⏹ (stopped), ⏳ (loading) - Smart caching with size limits - Async non-blocking file download - Ticker for smooth progress updates (100ms) - Graceful fallback to system players New Configuration (config.toml): - enabled: bool - enable/disable audio playback - default_volume: f32 - volume (0.0 - 1.0) - seek_step_seconds: i32 - seek step in seconds (default 5) - autoplay: bool - autoplay on selection - cache_size_mb: usize - cache size limit in MB - show_waveform: bool - show waveform visualization - system_player_fallback: bool - use system player fallback - system_player: String - system player command (mpv, ffplay) Status: PLANNED (documentation complete, implementation pending) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
428 lines
24 KiB
Markdown
428 lines
24 KiB
Markdown
# Roadmap
|
||
|
||
## Фаза 1: Базовая инфраструктура [DONE]
|
||
|
||
- [x] Настройка проекта (Cargo.toml)
|
||
- [x] TUI фреймворк (ratatui + crossterm)
|
||
- [x] Базовый layout (папки, список чатов, область сообщений)
|
||
- [x] Vim-style навигация (hjkl, стрелки)
|
||
- [x] Русская раскладка (ролд)
|
||
|
||
## Фаза 2: TDLib интеграция [DONE]
|
||
|
||
- [x] Подключение tdlib-rs
|
||
- [x] Авторизация (телефон + код + 2FA)
|
||
- [x] Сохранение сессии
|
||
- [x] Загрузка списка чатов
|
||
- [x] Загрузка истории сообщений
|
||
- [x] Отключение логов TDLib
|
||
|
||
## Фаза 3: Улучшение UX [DONE]
|
||
|
||
- [x] Отправка сообщений
|
||
- [x] Фильтрация чатов (только Main, без архива)
|
||
- [x] Поиск по чатам (Ctrl+S)
|
||
- [x] Скролл истории сообщений
|
||
- [x] Загрузка имён пользователей (вместо User_ID)
|
||
- [x] Отметка сообщений как прочитанные
|
||
- [x] Реальное время: новые сообщения
|
||
|
||
## Фаза 4: Папки и фильтрация [DONE]
|
||
|
||
- [x] Загрузка папок из Telegram
|
||
- [x] Переключение между папками (1-9)
|
||
- [x] Фильтрация чатов по папке
|
||
|
||
## Фаза 5: Расширенный функционал [DONE]
|
||
|
||
- [x] Отображение онлайн-статуса (зелёная точка ●)
|
||
- [x] Статус доставки/прочтения (✓, ✓✓)
|
||
- [x] Поддержка медиа-заглушек (фото, видео, голосовые, стикеры и др.)
|
||
- [x] Mentions (@) — индикатор непрочитанных упоминаний
|
||
- [x] Muted чаты (иконка 🔇)
|
||
|
||
## Фаза 6: Полировка [DONE]
|
||
|
||
- [x] Оптимизация использования памяти (базовая)
|
||
- Очистка сообщений при закрытии чата
|
||
- Лимит кэша пользователей (500)
|
||
- Периодическая очистка неактивных записей
|
||
- [x] Оптимизация 60 FPS
|
||
- Poll таймаут 16ms
|
||
- Флаг `needs_redraw` — рендеринг только при изменениях
|
||
- Обработка Event::Resize для перерисовки при изменении размера
|
||
- [x] Минимальное разрешение (80x20)
|
||
- Предупреждение если терминал слишком мал
|
||
- [x] Обработка ошибок сети
|
||
- NetworkState enum (WaitingForNetwork, Connecting, etc.)
|
||
- Индикатор в футере с цветовой индикацией
|
||
- [x] Graceful shutdown
|
||
- AtomicBool флаг для остановки polling
|
||
- Корректное закрытие TDLib клиента
|
||
- Таймаут ожидания завершения задач
|
||
- [x] Динамический инпут
|
||
- Автоматическое расширение до 10 строк
|
||
- Wrap для длинного текста
|
||
- [x] Перенос длинных сообщений
|
||
- Автоматический wrap на несколько строк
|
||
- Правильное выравнивание для исходящих/входящих
|
||
|
||
## Фаза 7: Глубокий рефакторинг памяти [DONE]
|
||
|
||
- [x] Удалить дублирование current_messages между App и TdClient
|
||
- [x] Использовать единый источник данных для сообщений
|
||
- [x] Реализовать LRU-кэш для user_names/user_statuses вместо простого лимита
|
||
- [x] Lazy loading для имён пользователей (батчевая загрузка последних 5 за цикл)
|
||
- [x] Лимиты памяти:
|
||
- MAX_MESSAGES_IN_CHAT = 500
|
||
- MAX_CHATS = 200
|
||
- MAX_CHAT_USER_IDS = 500
|
||
- MAX_USER_CACHE_SIZE = 500 (LRU)
|
||
|
||
## Фаза 8: Дополнительные фичи [DONE]
|
||
|
||
- [x] Markdown форматирование в сообщениях
|
||
- Bold, Italic, Underline, Strikethrough
|
||
- Code (inline, Pre, PreCode)
|
||
- Spoiler (скрытый текст)
|
||
- URLs, упоминания (@)
|
||
- [x] Редактирование сообщений
|
||
- ↑ при пустом инпуте → выбор сообщения
|
||
- Enter для начала редактирования
|
||
- Подсветка выбранного сообщения (▶)
|
||
- Esc для отмены
|
||
- [x] Удаление сообщений
|
||
- d / в / Delete в режиме выбора
|
||
- Модалка подтверждения (y/n)
|
||
- Удаление для всех если возможно
|
||
- [x] Индикатор редактирования (✎)
|
||
- Отображается рядом с временем для отредактированных сообщений
|
||
- [x] Блочный курсор в поле ввода
|
||
- Vim-style курсор █
|
||
- Перемещение ←/→, Home/End
|
||
- Редактирование в любой позиции
|
||
- [x] Reply на сообщения
|
||
- `r` / `к` в режиме выбора → режим ответа
|
||
- Превью сообщения в поле ввода
|
||
- Esc для отмены
|
||
- [x] Forward сообщений
|
||
- `f` / `а` в режиме выбора → режим пересылки
|
||
- Превью сообщения в поле ввода
|
||
- Выбор чата стрелками, Enter для пересылки
|
||
- Esc для отмены
|
||
- Отображение "↪ Переслано от" для пересланных сообщений
|
||
|
||
## Фаза 9: Расширенные возможности [DONE]
|
||
|
||
- [x] Typing indicator ("печатает...")
|
||
- Показывать когда собеседник печатает
|
||
- Отправлять свой статус печати при наборе текста
|
||
- [x] Закреплённые сообщения (Pinned)
|
||
- Отображать pinned message вверху открытого чата
|
||
- Клик/хоткей для перехода к закреплённому сообщению
|
||
- [x] Поиск по сообщениям в чате
|
||
- `Ctrl+F` — поиск текста внутри открытого чата
|
||
- Навигация по результатам (n/N или стрелки)
|
||
- Подсветка найденных совпадений
|
||
- [x] Черновики
|
||
- Сохранять набранный текст при переключении между чатами
|
||
- Индикатор черновика в списке чатов
|
||
- Восстановление текста при возврате в чат
|
||
- [x] Профиль пользователя/чата
|
||
- `Ctrl+i` — открыть информацию о чате/собеседнике
|
||
- Для личных чатов: имя, username, телефон, био
|
||
- Для групп: название, описание, количество участников
|
||
- [x] Копирование сообщений
|
||
- `y` / `н` в режиме выбора — скопировать текст в системный буфер обмена
|
||
- Использовать clipboard crate для кроссплатформенности
|
||
- [x] Реакции
|
||
- Отображение реакций под сообщениями
|
||
- `e` в режиме выбора — добавить реакцию (emoji picker)
|
||
- Список доступных реакций чата
|
||
- [x] Конфигурационный файл
|
||
- `~/.config/tele-tui/config.toml`
|
||
- Настройки: цветовая схема, часовой пояс, хоткеи
|
||
- Загрузка конфига при старте
|
||
|
||
## Фаза 10: Desktop уведомления [DONE - 83%]
|
||
|
||
### Стадия 1: Базовая реализация [DONE]
|
||
- [x] NotificationManager модуль
|
||
- notify-rust интеграция (версия 4.11)
|
||
- Feature flag "notifications" в Cargo.toml
|
||
- Базовая структура с настройками
|
||
- [x] Конфигурация уведомлений
|
||
- NotificationsConfig в config.toml
|
||
- enabled: bool - вкл/выкл уведомлений
|
||
- only_mentions: bool - только упоминания
|
||
- show_preview: bool - показывать превью текста
|
||
- [x] Интеграция с TdClient
|
||
- Поле notification_manager в TdClient
|
||
- Метод configure_notifications()
|
||
- Обработка в handle_new_message_update()
|
||
- [x] Базовая отправка уведомлений
|
||
- Уведомления для сообщений не из текущего чата
|
||
- Форматирование title (имя чата) и body (текст/медиа-заглушка)
|
||
- Sender name из MessageInfo
|
||
|
||
### Стадия 2: Улучшения [IN PROGRESS]
|
||
- [x] Синхронизация muted чатов
|
||
- Загрузка списка muted чатов из Telegram
|
||
- Вызов sync_muted_chats() при инициализации и обновлении (Ctrl+R)
|
||
- Muted чаты автоматически фильтруются из уведомлений
|
||
- [x] Фильтрация по упоминаниям
|
||
- Метод MessageInfo::has_mention() проверяет TextEntityType::Mention и MentionName
|
||
- NotificationManager применяет фильтр only_mentions из конфига
|
||
- Работает для @username и inline mentions
|
||
- [x] Поддержка типов медиа
|
||
- Метод beautify_media_labels() заменяет текстовые заглушки на emoji
|
||
- Поддержка: 📷 Фото, 🎥 Видео, 🎞️ GIF, 🎤 Голосовое, 🎨 Стикер
|
||
- Также: 📎 Файл, 🎵 Аудио, 📹 Видеосообщение, 📍 Локация, 👤 Контакт, 📊 Опрос
|
||
- [ ] Кастомизация звуков
|
||
- Настройка звуков уведомлений в config.toml
|
||
- Разные звуки для разных типов сообщений
|
||
|
||
### Стадия 3: Полировка [DONE]
|
||
- [x] Обработка ошибок
|
||
- Graceful fallback если уведомления недоступны (возвращает Ok без паники)
|
||
- Логирование ошибок через tracing::warn!
|
||
- Детальное логирование причин пропуска уведомлений (debug level)
|
||
- [x] Дополнительные настройки
|
||
- timeout_ms - продолжительность показа (0 = системное значение)
|
||
- urgency - уровень важности: "low", "normal", "critical" (только Linux)
|
||
- Красивые эмодзи для типов медиа
|
||
- [ ] Опциональные улучшения (не критично)
|
||
- Кросс-платформенное тестирование (требует ручного тестирования)
|
||
- icon - кастомная иконка приложения
|
||
- Actions в уведомлениях (кнопки "Ответить", "Прочитано")
|
||
|
||
## Фаза 11: Показ изображений в чате [PLANNED]
|
||
|
||
### Этап 1: Инфраструктура [TODO]
|
||
- [ ] Модуль src/media/
|
||
- image_cache.rs - LRU кэш для загруженных изображений
|
||
- image_loader.rs - Асинхронная загрузка через TDLib
|
||
- image_renderer.rs - Рендеринг в ratatui
|
||
- [ ] Зависимости
|
||
- ratatui-image 1.0 - поддержка изображений в TUI
|
||
- Определение протокола терминала (Sixel/Kitty/iTerm2/Halfblocks)
|
||
- [ ] ImageCache с лимитами
|
||
- LRU кэш с максимальным размером в МБ
|
||
- Автоматическая очистка старых изображений
|
||
- MAX_IMAGE_CACHE_SIZE = 100 MB (по умолчанию)
|
||
|
||
### Этап 2: Интеграция с TDLib [TODO]
|
||
- [ ] Обработка MessageContentPhoto
|
||
- Добавить PhotoInfo в MessageInfo
|
||
- Извлечение file_id, width, height из Photo
|
||
- Выбор оптимального размера изображения (до 800px)
|
||
- [ ] Загрузка файлов
|
||
- Метод TdClient::download_photo(file_id)
|
||
- Асинхронная загрузка через downloadFile API
|
||
- Обработка состояний загрузки (pending/downloading/ready)
|
||
- [ ] Кэширование
|
||
- Сохранение путей к загруженным файлам
|
||
- Повторное использование уже загруженных изображений
|
||
|
||
### Этап 3: Рендеринг в UI [TODO]
|
||
- [ ] Модификация render_messages()
|
||
- Определение возможностей терминала при старте
|
||
- Рендеринг изображений через ratatui-image
|
||
- Автоматическое масштабирование под размер области
|
||
- Сохранение aspect ratio
|
||
- [ ] Превью в списке сообщений
|
||
- Миниатюры размером 20x10 символов
|
||
- Lazy loading (загрузка только видимых)
|
||
- Placeholder пока изображение грузится
|
||
- [ ] Индикатор загрузки
|
||
- Текстовая заглушка "[Загрузка фото...]"
|
||
- Progress bar для больших файлов
|
||
- Процент загрузки
|
||
|
||
### Этап 4: Полноэкранный просмотр [TODO]
|
||
- [ ] Новый режим: ViewImage
|
||
- `v` / `м` в режиме выбора - открыть изображение
|
||
- Показ на весь экран терминала
|
||
- `Esc` для закрытия
|
||
- [ ] Информация об изображении
|
||
- Размер файла
|
||
- Разрешение (width x height)
|
||
- Формат (JPEG/PNG/GIF)
|
||
- [ ] Навигация
|
||
- `←` / `→` - предыдущее/следующее изображение в чате
|
||
- Автоматическая загрузка соседних изображений
|
||
|
||
### Этап 5: Конфигурация и UX [TODO]
|
||
- [ ] MediaConfig в config.toml
|
||
- show_images: bool - включить/отключить показ изображений
|
||
- image_cache_mb: usize - размер кэша в МБ
|
||
- preview_quality: "low" | "medium" | "high"
|
||
- render_protocol: "auto" | "sixel" | "kitty" | "iterm2" | "halfblocks"
|
||
- [ ] Поддержка различных терминалов
|
||
- Auto-detection протокола при старте
|
||
- Fallback на Unicode halfblocks для любого терминала
|
||
- Опция отключения изображений если терминал не поддерживает
|
||
- [ ] Оптимизация производительности
|
||
- Асинхронная загрузка (не блокирует UI)
|
||
- Приоритизация видимых изображений
|
||
- Fast resize для превью
|
||
- Кэширование отмасштабированных версий
|
||
|
||
### Этап 6: Обработка ошибок [TODO]
|
||
- [ ] Graceful fallback
|
||
- Текстовая заглушка "[Фото]" если загрузка не удалась
|
||
- Повторная попытка по запросу пользователя
|
||
- Логирование проблем через tracing
|
||
- [ ] Ограничения
|
||
- Таймаут загрузки (30 сек)
|
||
- Максимальный размер файла для автозагрузки (10 MB)
|
||
- Предупреждение для больших файлов
|
||
|
||
### Технические детали
|
||
- **Поддерживаемые протоколы:**
|
||
- Sixel (xterm, WezTerm, mintty)
|
||
- Kitty Graphics Protocol (Kitty terminal)
|
||
- iTerm2 Inline Images (iTerm2 на macOS)
|
||
- Unicode Halfblocks (fallback для всех)
|
||
- **Поддерживаемые форматы:**
|
||
- JPEG, PNG, GIF, WebP, BMP
|
||
- **Новые хоткеи:**
|
||
- `v` / `м` - открыть изображение в полном размере (режим выбора)
|
||
- `←` / `→` - навигация между изображениями (в режиме просмотра)
|
||
- `Esc` - закрыть полноэкранный просмотр
|
||
|
||
## Фаза 12: Прослушивание голосовых сообщений [PLANNED]
|
||
|
||
### Этап 1: Инфраструктура аудио [TODO]
|
||
- [ ] Модуль src/audio/
|
||
- player.rs - AudioPlayer на rodio
|
||
- cache.rs - VoiceCache для загруженных файлов
|
||
- state.rs - PlaybackState (статус, позиция, громкость)
|
||
- [ ] Зависимости
|
||
- rodio 0.17 - Pure Rust аудио библиотека
|
||
- Feature flag "audio" в Cargo.toml
|
||
- [ ] AudioPlayer API
|
||
- play() - воспроизведение файла
|
||
- pause() / resume() - пауза/возобновление
|
||
- stop() - остановка
|
||
- seek() - перемотка
|
||
- set_volume() - регулировка громкости
|
||
- get_position() - текущая позиция
|
||
- [ ] VoiceCache
|
||
- Кэш загруженных OGG файлов в ~/.cache/tele-tui/voice/
|
||
- LRU политика очистки
|
||
- MAX_VOICE_CACHE_SIZE = 100 MB
|
||
|
||
### Этап 2: Интеграция с TDLib [TODO]
|
||
- [ ] Обработка MessageContentVoiceNote
|
||
- Добавить VoiceNoteInfo в MessageInfo
|
||
- Извлечение file_id, duration, mime_type, waveform
|
||
- Метка формата (OGG Opus обычно)
|
||
- [ ] Загрузка файлов
|
||
- Метод TdClient::download_voice_note(file_id)
|
||
- Асинхронная загрузка через downloadFile API
|
||
- Обработка состояний (pending/downloading/ready)
|
||
- [ ] Кэширование
|
||
- Сохранение путей к загруженным файлам
|
||
- Не перезагружать уже скачанные голосовые
|
||
- Проверка существования файла перед воспроизведением
|
||
|
||
### Этап 3: UI для воспроизведения [TODO]
|
||
- [ ] Индикатор в сообщении
|
||
- Иконка 🎤 и длительность голосового
|
||
- Progress bar во время воспроизведения
|
||
- Статус: ▶ (playing), ⏸ (paused), ⏹ (stopped), ⏳ (loading)
|
||
- Текущее время / общая длительность (0:08 / 0:15)
|
||
- [ ] Модификация render_messages()
|
||
- render_voice_note() для голосовых сообщений
|
||
- render_progress_bar() для индикатора воспроизведения
|
||
- Hint "[Space] Воспроизвести" если не играет
|
||
- [ ] Footer с управлением
|
||
- Отображение доступных команд при воспроизведении
|
||
- "[Space] Play/Pause [s] Stop [←/→] Seek [↑/↓] Volume"
|
||
- [ ] Waveform визуализация (опционально)
|
||
- Конвертация waveform данных из Telegram в ASCII bars
|
||
- Использование символов ▁▂▃▄▅▆▇█ для визуализации
|
||
|
||
### Этап 4: Хоткеи для управления [TODO]
|
||
- [ ] Новые команды
|
||
- PlayVoice - Space в режиме выбора голосового
|
||
- PauseVoice - Space во время воспроизведения
|
||
- StopVoice - s / ы
|
||
- SeekBackward - ← (перемотка назад на 5 сек)
|
||
- SeekForward - → (перемотка вперед на 5 сек)
|
||
- VolumeUp - ↑ (увеличить на 10%)
|
||
- VolumeDown - ↓ (уменьшить на 10%)
|
||
- [ ] Контекстная обработка
|
||
- Space работает как play/pause в зависимости от состояния
|
||
- ← / → для seek только во время воспроизведения
|
||
- ↑ / ↓ для громкости только во время воспроизведения
|
||
- [ ] Поддержка русской раскладки
|
||
- s / ы - stop
|
||
- Остальные клавиши универсальны (Space, стрелки)
|
||
|
||
### Этап 5: Конфигурация и UX [TODO]
|
||
- [ ] AudioConfig в config.toml
|
||
- enabled: bool - включить/отключить аудио
|
||
- default_volume: f32 - громкость по умолчанию (0.0 - 1.0)
|
||
- seek_step_seconds: i32 - шаг перемотки в секундах
|
||
- autoplay: bool - автовоспроизведение при выборе
|
||
- cache_size_mb: usize - размер кэша голосовых
|
||
- show_waveform: bool - показывать waveform визуализацию
|
||
- system_player_fallback: bool - использовать системный плеер
|
||
- system_player: String - команда системного плеера (mpv, ffplay)
|
||
- [ ] Асинхронная загрузка
|
||
- Не блокировать UI во время загрузки файла
|
||
- Индикатор загрузки с процентами
|
||
- Возможность отмены загрузки
|
||
- [ ] Обновление UI
|
||
- Ticker для обновления progress bar (каждые 100ms)
|
||
- Плавное обновление позиции воспроизведения
|
||
- Автоматическая остановка при достижении конца
|
||
|
||
### Этап 6: Обработка ошибок [TODO]
|
||
- [ ] Graceful fallback на системный плеер
|
||
- Если rodio не работает - использовать mpv/ffplay
|
||
- Логирование ошибок через tracing
|
||
- Предупреждение пользователю если аудио недоступно
|
||
- [ ] Обработка ошибок загрузки
|
||
- Таймаут загрузки (30 сек)
|
||
- Повторная попытка по запросу
|
||
- Сообщение об ошибке в UI
|
||
- [ ] Ограничения
|
||
- Максимальный размер файла для кэша
|
||
- Автоматическая очистка старых файлов
|
||
- Предупреждение для очень длинных голосовых (>5 мин)
|
||
|
||
### Этап 7: Дополнительные улучшения [TODO]
|
||
- [ ] Управление воспроизведением
|
||
- Автоматическая остановка при закрытии чата
|
||
- Сохранение позиции при паузе
|
||
- Автопереход к следующему голосовому (опционально)
|
||
- [ ] Оптимизация
|
||
- Lazy loading (загрузка только при воспроизведении)
|
||
- Префетчинг следующего голосового (опционально)
|
||
- Минимальная задержка при нажатии Play
|
||
- [ ] Визуальные улучшения
|
||
- Анимация progress bar
|
||
- Цветовая индикация статуса (зеленый - playing, желтый - paused)
|
||
- Иконки в зависимости от статуса
|
||
|
||
### Технические детали
|
||
- **Аудио библиотека:**
|
||
- rodio 0.17 (Pure Rust, кроссплатформенная)
|
||
- Поддержка OGG Opus (формат голосовых в Telegram)
|
||
- Контроль воспроизведения через Sink API
|
||
- **Платформы:**
|
||
- Linux (ALSA, PulseAudio)
|
||
- macOS (CoreAudio)
|
||
- Windows (WASAPI)
|
||
- **Fallback:**
|
||
- mpv --no-video (универсальный плеер)
|
||
- ffplay -nodisp (из ffmpeg)
|
||
- **Новые хоткеи:**
|
||
- `Space` - воспроизвести/пауза (в режиме выбора голосового)
|
||
- `s` / `ы` - остановить воспроизведение
|
||
- `←` / `→` - перемотка -5с / +5с (во время воспроизведения)
|
||
- `↑` / `↓` - громкость +/- 10% (во время воспроизведения)
|