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:
Mikhail Kilin
2026-02-06 16:57:27 +03:00
parent ffd52d2384
commit 6845ee69bf
2 changed files with 90 additions and 2834 deletions

2343
CONTEXT.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,200 +1,22 @@
# Roadmap # Roadmap
## Фаза 1: Базовая инфраструктура [DONE] ## Завершённые фазы
- [x] Настройка проекта (Cargo.toml) | Фаза | Описание | Ключевые результаты |
- [x] TUI фреймворк (ratatui + crossterm) |------|----------|---------------------|
- [x] Базовый layout (папки, список чатов, область сообщений) | 1 | Базовая инфраструктура | ratatui + crossterm, vim-навигация, русская раскладка |
- [x] Vim-style навигация (hjkl, стрелки) | 2 | TDLib интеграция | tdlib-rs, авторизация, загрузка чатов и сообщений |
- [x] Русская раскладка (ролд) | 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] ## Фаза 11: Показ изображений в чате [PLANNED]
@@ -279,17 +101,11 @@
- Предупреждение для больших файлов - Предупреждение для больших файлов
### Технические детали ### Технические детали
- **Поддерживаемые протоколы:** - **Поддерживаемые протоколы:** Sixel, Kitty Graphics, iTerm2 Inline Images, Unicode Halfblocks (fallback)
- Sixel (xterm, WezTerm, mintty) - **Поддерживаемые форматы:** JPEG, PNG, GIF, WebP, BMP
- Kitty Graphics Protocol (Kitty terminal) - **Новые хоткеи:** `v`/`м` - полноэкранный просмотр, `←`/`→` - навигация, `Esc` - закрыть
- iTerm2 Inline Images (iTerm2 на macOS)
- Unicode Halfblocks (fallback для всех) ---
- **Поддерживаемые форматы:**
- JPEG, PNG, GIF, WebP, BMP
- **Новые хоткеи:**
- `v` / `м` - открыть изображение в полном размере (режим выбора)
- `←` / `→` - навигация между изображениями (в режиме просмотра)
- `Esc` - закрыть полноэкранный просмотр
## Фаза 12: Прослушивание голосовых сообщений [PLANNED] ## Фаза 12: Прослушивание голосовых сообщений [PLANNED]
@@ -302,30 +118,20 @@
- rodio 0.17 - Pure Rust аудио библиотека - rodio 0.17 - Pure Rust аудио библиотека
- Feature flag "audio" в Cargo.toml - Feature flag "audio" в Cargo.toml
- [ ] AudioPlayer API - [ ] AudioPlayer API
- play() - воспроизведение файла - play(), pause()/resume(), stop(), seek(), set_volume(), get_position()
- pause() / resume() - пауза/возобновление
- stop() - остановка
- seek() - перемотка
- set_volume() - регулировка громкости
- get_position() - текущая позиция
- [ ] VoiceCache - [ ] VoiceCache
- Кэш загруженных OGG файлов в ~/.cache/tele-tui/voice/ - Кэш загруженных OGG файлов в ~/.cache/tele-tui/voice/
- LRU политика очистки - LRU политика очистки, MAX_VOICE_CACHE_SIZE = 100 MB
- MAX_VOICE_CACHE_SIZE = 100 MB
### Этап 2: Интеграция с TDLib [TODO] ### Этап 2: Интеграция с TDLib [TODO]
- [ ] Обработка MessageContentVoiceNote - [ ] Обработка MessageContentVoiceNote
- Добавить VoiceNoteInfo в MessageInfo - Добавить VoiceNoteInfo в MessageInfo
- Извлечение file_id, duration, mime_type, waveform - Извлечение file_id, duration, mime_type, waveform
- Метка формата (OGG Opus обычно)
- [ ] Загрузка файлов - [ ] Загрузка файлов
- Метод TdClient::download_voice_note(file_id) - Метод TdClient::download_voice_note(file_id)
- Асинхронная загрузка через downloadFile API - Асинхронная загрузка через downloadFile API
- Обработка состояний (pending/downloading/ready) - Обработка состояний (pending/downloading/ready)
- [ ] Кэширование - [ ] Кэширование путей к загруженным файлам
- Сохранение путей к загруженным файлам
- Не перезагружать уже скачанные голосовые
- Проверка существования файла перед воспроизведением
### Этап 3: UI для воспроизведения [TODO] ### Этап 3: UI для воспроизведения [TODO]
- [ ] Индикатор в сообщении - [ ] Индикатор в сообщении
@@ -333,342 +139,37 @@
- Progress bar во время воспроизведения - Progress bar во время воспроизведения
- Статус: ▶ (playing), ⏸ (paused), ⏹ (stopped), ⏳ (loading) - Статус: ▶ (playing), ⏸ (paused), ⏹ (stopped), ⏳ (loading)
- Текущее время / общая длительность (0:08 / 0:15) - Текущее время / общая длительность (0:08 / 0:15)
- [ ] Модификация render_messages()
- render_voice_note() для голосовых сообщений
- render_progress_bar() для индикатора воспроизведения
- Hint "[Space] Воспроизвести" если не играет
- [ ] Footer с управлением - [ ] Footer с управлением
- Отображение доступных команд при воспроизведении
- "[Space] Play/Pause [s] Stop [←/→] Seek [↑/↓] Volume" - "[Space] Play/Pause [s] Stop [←/→] Seek [↑/↓] Volume"
- [ ] Waveform визуализация (опционально) - [ ] Waveform визуализация (опционально)
- Конвертация waveform данных из Telegram в ASCII bars - Символы ▁▂▃▄▅▆▇█ для визуализации
- Использование символов ▁▂▃▄▅▆▇█ для визуализации
### Этап 4: Хоткеи для управления [TODO] ### Этап 4: Хоткеи для управления [TODO]
- [ ] Новые команды - [ ] Новые команды
- PlayVoice - Space в режиме выбора голосового - Space - play/pause, s/ы - stop
- PauseVoice - Space во время воспроизведения - ←/→ - seek ±5 сек, ↑/↓ - volume ±10%
- StopVoice - s / ы - [ ] Контекстная обработка (управление только во время воспроизведения)
- SeekBackward - ← (перемотка назад на 5 сек)
- SeekForward - → (перемотка вперед на 5 сек)
- VolumeUp - ↑ (увеличить на 10%)
- VolumeDown - ↓ (уменьшить на 10%)
- [ ] Контекстная обработка
- Space работает как play/pause в зависимости от состояния
- ← / → для seek только во время воспроизведения
- ↑ / ↓ для громкости только во время воспроизведения
- [ ] Поддержка русской раскладки - [ ] Поддержка русской раскладки
- s / ы - stop
- Остальные клавиши универсальны (Space, стрелки)
### Этап 5: Конфигурация и UX [TODO] ### Этап 5: Конфигурация и UX [TODO]
- [ ] AudioConfig в config.toml - [ ] AudioConfig в config.toml
- enabled: bool - включить/отключить аудио - enabled, default_volume, seek_step_seconds, autoplay, cache_size_mb, show_waveform
- default_volume: f32 - громкость по умолчанию (0.0 - 1.0) - system_player_fallback, system_player (mpv, ffplay)
- seek_step_seconds: i32 - шаг перемотки в секундах - [ ] Асинхронная загрузка (не блокирует UI)
- autoplay: bool - автовоспроизведение при выборе - [ ] Ticker для обновления progress bar (каждые 100ms)
- 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] ### Этап 6: Обработка ошибок [TODO]
- [ ] Graceful fallback на системный плеер - [ ] Graceful fallback на системный плеер (mpv/ffplay)
- Если rodio не работает - использовать mpv/ffplay - [ ] Таймаут загрузки (30 сек), повторная попытка
- Логирование ошибок через tracing - [ ] Ограничения: максимальный размер файла, автоочистка кэша
- Предупреждение пользователю если аудио недоступно
- [ ] Обработка ошибок загрузки
- Таймаут загрузки (30 сек)
- Повторная попытка по запросу
- Сообщение об ошибке в UI
- [ ] Ограничения
- Максимальный размер файла для кэша
- Автоматическая очистка старых файлов
- Предупреждение для очень длинных голосовых (>5 мин)
### Этап 7: Дополнительные улучшения [TODO] ### Этап 7: Дополнительные улучшения [TODO]
- [ ] Управление воспроизведением - [ ] Автоматическая остановка при закрытии чата
- Автоматическая остановка при закрытии чата - [ ] Сохранение позиции при паузе
- Сохранение позиции при паузе - [ ] Префетчинг следующего голосового (опционально)
- Автопереход к следующему голосовому (опционально)
- [ ] Оптимизация
- Lazy loading (загрузка только при воспроизведении)
- Префетчинг следующего голосового (опционально)
- Минимальная задержка при нажатии Play
- [ ] Визуальные улучшения
- Анимация progress bar
- Цветовая индикация статуса (зеленый - playing, желтый - paused)
- Иконки в зависимости от статуса
### Технические детали ### Технические детали
- **Аудио библиотека:** - **Аудио библиотека:** rodio 0.17 (Pure Rust, кроссплатформенная, OGG Opus)
- rodio 0.17 (Pure Rust, кроссплатформенная) - **Платформы:** Linux (ALSA/PulseAudio), macOS (CoreAudio), Windows (WASAPI)
- Поддержка OGG Opus (формат голосовых в Telegram) - **Fallback:** mpv --no-video, ffplay -nodisp
- Контроль воспроизведения через Sink API - **Новые хоткеи:** Space - play/pause, s/ы - stop, ←/→ - seek, ↑/↓ - volume
- **Платформы:**
- 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