Files
telegram-tui/ROADMAP.md
Mikhail Kilin dea3559da7
Some checks failed
ci/woodpecker/pr/check Pipeline failed
docs: remove out-of-scope items from Phase 14 Etap 4 roadmap
Remove account deletion from modal and parallel polling — these won't
be implemented in the current scope.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 00:57:18 +03:00

11 KiB
Raw Blame History

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) -> / навигация между фото.

Реализовано:

  • Dual renderer архитектура:
    • inline_image_renderer: Halfblocks (быстро, Unicode блоки) для навигации
    • modal_image_renderer: iTerm2/Sixel (медленно, высокое качество) для просмотра
  • Performance optimizations:
    • Frame throttling: inline 15 FPS, текст 60 FPS
    • Lazy loading: только видимые изображения
    • LRU cache: max 100 протоколов
    • Skip partial rendering (no flickering)
  • UX улучшения:
    • Always-show inline preview (фикс. ширина 50 chars)
    • Fullscreen modal на v/м с aspect ratio
    • Loading indicator в модалке
    • Navigation hotkeys: / между фото, Esc/q закрыть
  • Типы и API:
    • MediaInfo, PhotoInfo, PhotoDownloadState, ImageModalState
    • ImagesConfig в config.toml
    • Feature flag images для зависимостей
  • Media модуль:
    • cache.rs: ImageCache (LRU)
    • image_renderer.rs: new() + new_fast()
  • UI модули:
    • modals/image_viewer.rs: fullscreen modal
    • messages.rs: throttled second-pass rendering
  • Авто-загрузка фото (bugfix):
    • Auto-download последних 30 фото при открытии чата (open_chat_and_load_data)
    • Download on demand по v (вместо "Фото не загружено")
    • Retry при ошибке загрузки
    • Конфиг: auto_download_images + show_images в [images]

Фаза 12: Прослушивание голосовых сообщений [DONE]

Этап 1: Инфраструктура аудио [DONE]

  • Модуль src/audio/
    • player.rs — AudioPlayer на ffplay (subprocess)
    • cache.rs — VoiceCache (LRU, configurable size, ~/.cache/tele-tui/voice/)
  • AudioPlayer API: play(), play_from(ss), pause() (SIGSTOP), resume(), resume_from(ss), stop()
  • Race condition fix: starting flag + pid ownership guard в потоках
  • Drop impl для AudioPlayer (убивает ffplay при выходе)

Этап 2: Интеграция с TDLib [DONE]

  • Типы: VoiceInfo, VoiceDownloadState, PlaybackState, PlaybackStatus
  • Конвертация MessageVoiceNote в message_conversion.rs
  • download_voice_note() в TdClientTrait + client_impl + fake
  • Методы has_voice(), voice_info(), voice_info_mut() на MessageInfo

Этап 3: UI для воспроизведения [DONE]

  • Progress bar (━●─) с позицией и длительностью
  • Waveform визуализация (▁▂▃▄▅▆▇█) из base64-encoded TDLib данных
  • Иконки статуса: ▶ Playing, ⏸ Paused, ⏹ Stopped
  • Throttled redraw: обновление UI только при смене секунды (не 60 FPS)

Этап 4: Хоткеи [DONE]

  • Space — play/pause toggle (запуск + пауза/возобновление с откатом 1s)
  • ←/→ — seek ±5 сек (через resume_from() — перезапуск ffplay с -ss)
  • Seek работает и при воспроизведении, и на паузе (на паузе двигает позицию, при resume стартует с неё)
  • MoveLeft/MoveRight как alias для SeekBackward/SeekForward (HashMap non-deterministic order fix)
  • Автоматическая остановка при навигации на другое сообщение
  • Остановка ffplay при выходе из приложения (Ctrl+C)

Этап 5: Конфигурация и кэш [DONE]

  • AudioConfig в config.toml (cache_size_mb, auto_download_voice)
  • DEFAULT_AUDIO_CACHE_SIZE_MB константа (100 MB)
  • Ticker для progress bar в event loop (delta-based position tracking)
  • 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-аккаунтов с мгновенным переключением внутри приложения.

┌──────────────┬───────────────────────────┐
│ 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 — список аккаунтов (имя, путь к БД)

Этапы

  • Этап 1: Инфраструктура профилей (DONE)

    • Структура AccountProfile (name, display_name, db_path)
    • accounts.toml — хранение списка аккаунтов
    • Миграция tdlib_data/accounts/default/tdlib_data/ (обратная совместимость)
    • CLI: --account <name> для запуска конкретного аккаунта
  • Этап 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)