docs: trim CONTEXT.md and ROADMAP.md (3006→246 lines, -92%)
Completed phases condensed to summary tables, detailed history removed (available in git log). Detailed plans kept only for upcoming phases 11 (images) and 12 (voice messages). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2343
CONTEXT.md
2343
CONTEXT.md
File diff suppressed because it is too large
Load Diff
581
ROADMAP.md
581
ROADMAP.md
@@ -1,200 +1,22 @@
|
||||
# Roadmap
|
||||
|
||||
## Фаза 1: Базовая инфраструктура [DONE]
|
||||
## Завершённые фазы
|
||||
|
||||
- [x] Настройка проекта (Cargo.toml)
|
||||
- [x] TUI фреймворк (ratatui + crossterm)
|
||||
- [x] Базовый layout (папки, список чатов, область сообщений)
|
||||
- [x] Vim-style навигация (hjkl, стрелки)
|
||||
- [x] Русская раскладка (ролд)
|
||||
| Фаза | Описание | Ключевые результаты |
|
||||
|------|----------|---------------------|
|
||||
| 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: кастомные звуки |
|
||||
| 13 | Глубокий рефакторинг | 5 файлов (4582→модули), 5 traits, shared components, docs |
|
||||
|
||||
## Фаза 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]
|
||||
|
||||
@@ -279,17 +101,11 @@
|
||||
- Предупреждение для больших файлов
|
||||
|
||||
### Технические детали
|
||||
- **Поддерживаемые протоколы:**
|
||||
- Sixel (xterm, WezTerm, mintty)
|
||||
- Kitty Graphics Protocol (Kitty terminal)
|
||||
- iTerm2 Inline Images (iTerm2 на macOS)
|
||||
- Unicode Halfblocks (fallback для всех)
|
||||
- **Поддерживаемые форматы:**
|
||||
- JPEG, PNG, GIF, WebP, BMP
|
||||
- **Новые хоткеи:**
|
||||
- `v` / `м` - открыть изображение в полном размере (режим выбора)
|
||||
- `←` / `→` - навигация между изображениями (в режиме просмотра)
|
||||
- `Esc` - закрыть полноэкранный просмотр
|
||||
- **Поддерживаемые протоколы:** Sixel, Kitty Graphics, iTerm2 Inline Images, Unicode Halfblocks (fallback)
|
||||
- **Поддерживаемые форматы:** JPEG, PNG, GIF, WebP, BMP
|
||||
- **Новые хоткеи:** `v`/`м` - полноэкранный просмотр, `←`/`→` - навигация, `Esc` - закрыть
|
||||
|
||||
---
|
||||
|
||||
## Фаза 12: Прослушивание голосовых сообщений [PLANNED]
|
||||
|
||||
@@ -302,30 +118,20 @@
|
||||
- rodio 0.17 - Pure Rust аудио библиотека
|
||||
- Feature flag "audio" в Cargo.toml
|
||||
- [ ] AudioPlayer API
|
||||
- play() - воспроизведение файла
|
||||
- pause() / resume() - пауза/возобновление
|
||||
- stop() - остановка
|
||||
- seek() - перемотка
|
||||
- set_volume() - регулировка громкости
|
||||
- get_position() - текущая позиция
|
||||
- play(), pause()/resume(), stop(), seek(), set_volume(), get_position()
|
||||
- [ ] VoiceCache
|
||||
- Кэш загруженных OGG файлов в ~/.cache/tele-tui/voice/
|
||||
- LRU политика очистки
|
||||
- MAX_VOICE_CACHE_SIZE = 100 MB
|
||||
- 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]
|
||||
- [ ] Индикатор в сообщении
|
||||
@@ -333,342 +139,37 @@
|
||||
- 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 только во время воспроизведения
|
||||
- ↑ / ↓ для громкости только во время воспроизведения
|
||||
- Space - play/pause, s/ы - stop
|
||||
- ←/→ - seek ±5 сек, ↑/↓ - volume ±10%
|
||||
- [ ] Контекстная обработка (управление только во время воспроизведения)
|
||||
- [ ] Поддержка русской раскладки
|
||||
- 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)
|
||||
- Плавное обновление позиции воспроизведения
|
||||
- Автоматическая остановка при достижении конца
|
||||
- enabled, default_volume, seek_step_seconds, autoplay, cache_size_mb, show_waveform
|
||||
- system_player_fallback, system_player (mpv, ffplay)
|
||||
- [ ] Асинхронная загрузка (не блокирует UI)
|
||||
- [ ] Ticker для обновления progress bar (каждые 100ms)
|
||||
|
||||
### Этап 6: Обработка ошибок [TODO]
|
||||
- [ ] Graceful fallback на системный плеер
|
||||
- Если rodio не работает - использовать mpv/ffplay
|
||||
- Логирование ошибок через tracing
|
||||
- Предупреждение пользователю если аудио недоступно
|
||||
- [ ] Обработка ошибок загрузки
|
||||
- Таймаут загрузки (30 сек)
|
||||
- Повторная попытка по запросу
|
||||
- Сообщение об ошибке в UI
|
||||
- [ ] Ограничения
|
||||
- Максимальный размер файла для кэша
|
||||
- Автоматическая очистка старых файлов
|
||||
- Предупреждение для очень длинных голосовых (>5 мин)
|
||||
- [ ] Graceful fallback на системный плеер (mpv/ffplay)
|
||||
- [ ] Таймаут загрузки (30 сек), повторная попытка
|
||||
- [ ] Ограничения: максимальный размер файла, автоочистка кэша
|
||||
|
||||
### Этап 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% (во время воспроизведения)
|
||||
|
||||
## Фаза 13: Глубокий рефакторинг архитектуры [DONE]
|
||||
|
||||
**Мотивация:** Код вырос до критических размеров - некоторые файлы содержат >1000 строк, что затрудняет поддержку и навигацию. Необходимо разбить монолитные файлы на логические модули.
|
||||
|
||||
**Проблемы:**
|
||||
- `src/input/main_input.rs` - 1199 строк (самый большой файл!)
|
||||
- `src/app/mod.rs` - 1015 строк, 116 функций (God Object)
|
||||
- `src/ui/messages.rs` - 893 строки
|
||||
- `src/tdlib/messages.rs` - 833 строки
|
||||
- `src/config/mod.rs` - 642 строки
|
||||
|
||||
### Этап 1: Разбить input/main_input.rs (1199 → <200 строк) [DONE ✅]
|
||||
|
||||
**Текущая проблема:**
|
||||
- Весь input handling в одном файле
|
||||
- Функции по 300-400 строк
|
||||
- Невозможно быстро найти нужный handler
|
||||
|
||||
**План:**
|
||||
- [x] Создать `src/input/handlers/` директорию
|
||||
- [x] Создать `handlers/chat.rs` - обработка ввода в открытом чате
|
||||
- Переместить `handle_open_chat_keyboard_input()`
|
||||
- Обработка скролла, выбора сообщений
|
||||
- **452 строки** (7 функций)
|
||||
- [x] Создать `handlers/chat_list.rs` - обработка в списке чатов
|
||||
- Переместить `handle_chat_list_keyboard_input()`
|
||||
- Навигация по чатам, папки
|
||||
- **142 строки** (3 функции)
|
||||
- [x] Создать `handlers/compose.rs` - режимы edit/reply/forward
|
||||
- Обработка ввода в режимах редактирования
|
||||
- Input field управление (курсор, backspace, delete)
|
||||
- **80 строк** (2 функции)
|
||||
- [x] Создать `handlers/modal.rs` - модалки
|
||||
- Delete confirmation
|
||||
- Emoji picker
|
||||
- Profile modal
|
||||
- **316 строк** (5 функций)
|
||||
- [x] Создать `handlers/search.rs` - поиск
|
||||
- Search mode в чате
|
||||
- Search mode в списке чатов
|
||||
- **140 строк** (3 функций)
|
||||
- [x] Обновить `main_input.rs` - только роутинг
|
||||
- Определение текущего режима
|
||||
- Делегация в нужный handler
|
||||
- **164 строки** (2 функции)
|
||||
|
||||
**Результат:** 1199 строк → **164 строки** (удалено 1035 строк, -86%)
|
||||
- Создано 5 новых модулей обработки ввода
|
||||
- Чистый router pattern в main_input.rs
|
||||
- Каждый handler отвечает за свою область
|
||||
- **Дополнительно:** Исправлен конфликт Ctrl+I → Ctrl+U для профиля
|
||||
|
||||
### Этап 2: Уменьшить app/mod.rs (116 функций → traits) [DONE ✅]
|
||||
|
||||
**Текущая проблема:**
|
||||
- God Object с 116 функциями
|
||||
- Сложно найти нужный метод
|
||||
- Нарушение Single Responsibility Principle
|
||||
|
||||
**План:**
|
||||
- [x] Создать `app/methods/` директорию
|
||||
- [x] Создать trait `NavigationMethods`
|
||||
- `next_chat()`, `previous_chat()`, `select_current_chat()`, `close_chat()`
|
||||
- `next_filtered_chat()`, `previous_filtered_chat()`, `select_filtered_chat()`
|
||||
- **7 методов**
|
||||
- [x] Создать trait `MessageMethods`
|
||||
- `start_message_selection()`, `select_previous/next_message()`
|
||||
- `get_selected_message()`, `start_editing_selected()`, `cancel_editing()`
|
||||
- `is_editing()`, `is_selecting_message()`
|
||||
- **8 методов**
|
||||
- [x] Создать trait `ComposeMethods`
|
||||
- `start_reply_to_selected()`, `cancel_reply()`, `is_replying()`, `get_replying_to_message()`
|
||||
- `start_forward_selected()`, `cancel_forward()`, `is_forwarding()`, `get_forwarding_message()`
|
||||
- `get_current_draft()`, `load_draft()`
|
||||
- **10 методов**
|
||||
- [x] Создать trait `SearchMethods`
|
||||
- Chat search: `start_search()`, `cancel_search()`, `get_filtered_chats()`
|
||||
- Message search: `enter/exit_message_search_mode()`, `set/get_search_results()`
|
||||
- Navigation: `select_previous/next_search_result()`, query управление
|
||||
- **15 методов**
|
||||
- [x] Создать trait `ModalMethods`
|
||||
- Delete confirmation: `is_confirm_delete_shown()`
|
||||
- Pinned: `is/enter/exit_pinned_mode()`, `select_previous/next_pinned()`, getters
|
||||
- Profile: `is/enter/exit_profile_mode()`, navigation, leave_group confirmation
|
||||
- Reactions: `is/enter/exit_reaction_picker_mode()`, `select_previous/next_reaction()`
|
||||
- **27 методов**
|
||||
- [x] Оставить в `app/mod.rs` только:
|
||||
- Struct definition
|
||||
- Constructors (new, with_client)
|
||||
- Utilities (get_command, get_selected_chat_id, get_selected_chat)
|
||||
- Getters/setters для всех полей
|
||||
- **~48 методов**
|
||||
|
||||
**Структура:**
|
||||
```rust
|
||||
// app/mod.rs - только core
|
||||
mod methods;
|
||||
pub use methods::*;
|
||||
|
||||
impl<T: TdClientTrait> App<T> {
|
||||
pub fn new() -> Self { ... }
|
||||
pub fn get_command(...) -> Option<Command> { ... }
|
||||
pub fn get_selected_chat_id(&self) -> Option<i64> { ... }
|
||||
// ... getters/setters ...
|
||||
}
|
||||
|
||||
// app/methods/navigation.rs
|
||||
pub trait NavigationMethods<T: TdClientTrait> {
|
||||
fn next_chat(&mut self);
|
||||
fn previous_chat(&mut self);
|
||||
}
|
||||
impl<T: TdClientTrait> NavigationMethods<T> for App<T> { ... }
|
||||
```
|
||||
|
||||
**Результат:** 1015 строк → **371 строка** (удалено 644 строки, -63%)
|
||||
- 116 функций → 5 trait impl блоков (67 методов в traits + 48 в core)
|
||||
- Каждый trait отвечает за свою область функциональности
|
||||
- Соблюдён Single Responsibility Principle ✅
|
||||
|
||||
### Этап 3: Разбить ui/messages.rs (893 → 365 строк) [DONE ✅]
|
||||
|
||||
**Текущая проблема:**
|
||||
- Весь UI рендеринг сообщений в одном файле
|
||||
- Модалки смешаны с основным рендерингом
|
||||
- Compose bar (input field) в том же файле
|
||||
|
||||
**План:**
|
||||
- [x] Создать `ui/modals/` директорию
|
||||
- [x] Создать `modals/mod.rs` - экспорты модальных окон
|
||||
- [x] Создать `modals/delete_confirm.rs`
|
||||
- Wrapper для компонента подтверждения удаления
|
||||
- **~8 строк**
|
||||
- [x] Создать `modals/reaction_picker.rs`
|
||||
- Wrapper для компонента выбора реакций
|
||||
- **~13 строк**
|
||||
- [x] Создать `modals/search.rs`
|
||||
- Поиск по сообщениям в чате
|
||||
- Input с курсором, результаты, навигация
|
||||
- **193 строки**
|
||||
- [x] Создать `modals/pinned.rs`
|
||||
- Просмотр закреплённых сообщений
|
||||
- Header, список сообщений, навигация
|
||||
- **163 строки**
|
||||
- [x] Создать `ui/compose_bar.rs`
|
||||
- Поле ввода с поддержкой 5 режимов
|
||||
- Режимы: normal, edit, reply, forward, select
|
||||
- Динамический preview для каждого режима
|
||||
- **168 строк**
|
||||
- [x] Обновить `messages.rs`:
|
||||
- Оставлен только core rendering
|
||||
- Chat header, pinned bar, message list
|
||||
- Utility функции (wrap_text_with_offsets, WrappedLine)
|
||||
- Интеграция через compose_bar::render() и modals::render_*()
|
||||
- **365 строк**
|
||||
|
||||
**Результат:** 893 строки → **365 строк** (удалено 528 строк, -59%)
|
||||
- Создано 6 новых модулей UI
|
||||
- Чистое разделение ответственности
|
||||
- Модальные окна полностью изолированы
|
||||
- Compose bar - отдельный переиспользуемый компонент
|
||||
|
||||
### Этап 4: Разбить tdlib/messages.rs (833 → 3 файла) [DONE ✅]
|
||||
|
||||
**Текущая проблема:**
|
||||
- Смешивается конвертация из TDLib и операции
|
||||
- Большой файл сложно читать
|
||||
|
||||
**План:**
|
||||
- [x] Создать `tdlib/messages/` директорию
|
||||
- [x] Создать `messages/convert.rs`
|
||||
- convert_message(), fetch_missing_reply_info(), fetch_and_update_reply()
|
||||
- **134 строки**
|
||||
- [x] Создать `messages/operations.rs`
|
||||
- 11 TDLib API операций (send, edit, delete, forward, search, etc.)
|
||||
- **616 строк**
|
||||
- [x] Обновить `tdlib/messages.rs` → `tdlib/messages/mod.rs`
|
||||
- Struct MessageManager, new(), push_message()
|
||||
- **99 строк**
|
||||
|
||||
**Результат:** 836 строк → 3 файла (99 + 134 + 616)
|
||||
|
||||
### Этап 5: Разбить config/mod.rs (642 → 3 файла) [DONE ✅]
|
||||
|
||||
**Текущая проблема:**
|
||||
- Много default_* функций (по 1-3 строки каждая)
|
||||
- Validation logic смешана с определениями
|
||||
- Сложно найти нужную секцию конфига
|
||||
|
||||
**План:**
|
||||
- [x] Создать `config/validation.rs`
|
||||
- validate(), parse_color()
|
||||
- **86 строк**
|
||||
- [x] Создать `config/loader.rs`
|
||||
- load(), save(), paths, credentials
|
||||
- **192 строки**
|
||||
- [x] Оставить в `config/mod.rs`:
|
||||
- Structs, defaults, Default impls, tests
|
||||
- **350 строк**
|
||||
|
||||
**Результат:** 642 строки → 3 файла (350 + 86 + 192)
|
||||
|
||||
### Этап 6: Code Duplication Cleanup [DONE ✅]
|
||||
|
||||
**План:**
|
||||
- [x] Очистка неиспользуемых импортов в 7 файлах
|
||||
- [x] Извлечение `format_user_status()` в `ui/chat_list.rs` (удалено ~80 строк дублей)
|
||||
- [x] Создание `ui/components/message_list.rs` — общие render_message_item, calculate_scroll_offset, render_help_bar (удалено ~120 строк дублей)
|
||||
- [x] Извлечение `scroll_to_message()` в `input/handlers/mod.rs` (удалено ~20 строк дублей)
|
||||
- **Итого:** удалено ~220 строк дублированного кода, 0 compiler warnings
|
||||
|
||||
### Этап 7: Documentation Update [DONE ✅]
|
||||
|
||||
**План:**
|
||||
- [x] Обновить CONTEXT.md с новой структурой
|
||||
- [x] Полностью переписать PROJECT_STRUCTURE.md (архитектура, дерево файлов, traits, state machine)
|
||||
- [x] Добавить module-level документацию (`//!`) к 16 файлам
|
||||
- [x] Создать architecture diagram (ASCII) в PROJECT_STRUCTURE.md
|
||||
|
||||
### Метрики успеха
|
||||
|
||||
**До рефакторинга:**
|
||||
```
|
||||
input/main_input.rs: 1199 строк
|
||||
app/mod.rs: 1015 строк (116 функций)
|
||||
ui/messages.rs: 893 строки
|
||||
tdlib/messages.rs: 833 строки
|
||||
config/mod.rs: 642 строки
|
||||
ИТОГО: 4582 строки в 5 файлах
|
||||
```
|
||||
|
||||
**После рефакторинга:**
|
||||
```
|
||||
input/handlers/*.rs: ~6 файлов по <400 строк
|
||||
app/methods/*.rs: ~6 traits с impl блоками
|
||||
ui/modals/*.rs: ~4 файла по <150 строк
|
||||
tdlib/messages/*.rs: 2 файла по <500 строк
|
||||
config/*.rs: 4 файла по <200 строк
|
||||
ИТОГО: те же строки, но в ~20+ файлах
|
||||
```
|
||||
|
||||
**Преимущества:**
|
||||
- ✅ Легче найти нужный код
|
||||
- ✅ Легче тестировать модули
|
||||
- ✅ Меньше конфликтов при работе в команде
|
||||
- ✅ Лучше читаемость и поддерживаемость
|
||||
- ✅ Соблюдение Single Responsibility Principle
|
||||
- **Аудио библиотека:** rodio 0.17 (Pure Rust, кроссплатформенная, OGG Opus)
|
||||
- **Платформы:** Linux (ALSA/PulseAudio), macOS (CoreAudio), Windows (WASAPI)
|
||||
- **Fallback:** mpv --no-video, ffplay -nodisp
|
||||
- **Новые хоткеи:** Space - play/pause, s/ы - stop, ←/→ - seek, ↑/↓ - volume
|
||||
|
||||
Reference in New Issue
Block a user