# 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% (во время воспроизведения) ## Фаза 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 App { pub fn new() -> Self { ... } pub fn get_command(...) -> Option { ... } pub fn get_selected_chat_id(&self) -> Option { ... } // ... getters/setters ... } // app/methods/navigation.rs pub trait NavigationMethods { fn next_chat(&mut self); fn previous_chat(&mut self); } impl NavigationMethods for App { ... } ``` **Результат:** 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