Mikhail Kilin
5f1d715e8f
fix: eliminate infinite recursion in TdClientTrait implementation
...
CRITICAL BUG FIX: Three methods in TdClientTrait impl were calling themselves recursively instead of delegating to actual implementations, causing stack overflow and application panic on startup.
Fixed methods:
1. user_cache_mut() - now returns &mut self.user_cache directly
2. sync_notification_muted_chats() - now delegates to notification_manager.sync_muted_chats()
3. handle_update() - now properly delegates to TdClient::handle_update() using qualified path
This bug caused the app to hang on "Инициализация TDLib..." screen and exit raw mode, displaying escape sequences ("CB52") on key presses when user tried to interact.
Root cause: Introduced in refactoring commit bd5e5be where trait implementations were created but incorrectly delegated to self.method() instead of accessing struct fields directly or using qualified path syntax.
Also added panic hook in main.rs to ensure terminal restoration on panic for better debugging experience.
Impact: Application completely broken - couldn't start. Stack overflow on first update.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-05 12:57:55 +03:00
Mikhail Kilin
bccf07501f
docs: add Phase 13 - deep architecture refactoring plan
...
Added comprehensive plan for refactoring oversized files and God Objects
in the codebase. Current critical issues:
Critical Problems:
- input/main_input.rs: 1199 lines (largest file!)
- app/mod.rs: 1015 lines, 116 functions (God Object)
- ui/messages.rs: 893 lines
- tdlib/messages.rs: 833 lines
- config/mod.rs: 642 lines
Phase 13 Plan (7 stages):
Stage 1: Split input/main_input.rs (1199 → <200 lines)
- Create input/handlers/ directory
- handlers/chat.rs - open chat input handling (~300-400 lines)
- handlers/chat_list.rs - chat list input (~200-300 lines)
- handlers/compose.rs - edit/reply/forward modes (~200 lines)
- handlers/modal.rs - delete confirm, emoji picker (~150 lines)
- handlers/search.rs - search modes (~100 lines)
- main_input.rs becomes router only (<200 lines)
Stage 2: Reduce app/mod.rs (116 functions → traits)
- Create app/methods/ directory with traits:
- NavigationMethods (~15 methods)
- MessageMethods (~20 methods)
- ComposeMethods (~15 methods)
- SearchMethods (~5 methods)
- ModalMethods (~10 methods)
- Keep only core in mod.rs (~30-40 methods)
Stage 3: Split ui/messages.rs (893 → <300 lines)
- Create ui/modals/ directory:
- modals/delete_confirm.rs (~50 lines)
- modals/emoji_picker.rs (~100 lines)
- modals/search_modal.rs (~80 lines)
- modals/profile_modal.rs (~100 lines)
- Create ui/compose_bar.rs (~150 lines)
- messages.rs keeps main layout (~300 lines)
Stage 4: Split tdlib/messages.rs (833 → 2 files)
- Create tdlib/messages/ directory:
- messages/convert.rs - TDLib conversion (~500 lines)
- messages/operations.rs - operations (~300 lines)
Stage 5: Split config/mod.rs (642 → 3 files)
- config/defaults.rs - all default_* functions (~100 lines)
- config/validation.rs - validation logic (~150 lines)
- config/loader.rs - file loading (~100 lines)
- mod.rs - struct definitions (~200-300 lines)
Stage 6: Code Duplication Cleanup
- Extract common handler logic
- Extract common UI components
- Apply DRY principle
Stage 7: Documentation Update
- Update CONTEXT.md with new structure
- Update PROJECT_STRUCTURE.md
- Add module-level documentation
- Create architecture diagram
Success Metrics:
Before: 4582 lines in 5 files
After: Same lines in ~20+ files
Benefits: Better readability, testability, maintainability, SRP compliance
Status: PLANNED (comprehensive refactoring plan documented)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-05 11:30:29 +03:00
Mikhail Kilin
776271ff36
docs: add Phase 12 - voice message playback
...
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 >
2026-02-05 02:51:04 +03:00
Mikhail Kilin
8844c2953d
docs: add Phase 11 - image display in chat
...
Documented new feature for displaying images directly in terminal
instead of text placeholders like "[Фото]".
Documentation Changes:
- ROADMAP.md: Added Phase 11 with 6 stages
- Stage 1: Infrastructure (media module, ImageCache, dependencies)
- Stage 2: TDLib integration (PhotoInfo, download_photo)
- Stage 3: UI rendering (inline previews, scaling)
- Stage 4: Fullscreen viewer (new ViewImage mode)
- Stage 5: Configuration and UX (MediaConfig in config.toml)
- Stage 6: Error handling and fallback
- CONTEXT.md: Added PLANNED section for Phase 11
- Technical stack: ratatui-image 1.0, TDLib downloadFile
- Protocols: Sixel, Kitty Graphics, iTerm2, Unicode Halfblocks
- Architecture: src/media/ module with 3 submodules
- LRU cache (100 MB limit)
- Async loading, lazy loading for visible images
- Configuration options in config.toml
- HOTKEYS.md: Added new hotkeys
- `v` / `м` - open image in fullscreen (in selection mode)
- `←` / `→` - navigate between images (in viewer mode)
- `Esc` - close image viewer
- Added new "View Image Mode" section
- PROJECT_STRUCTURE.md: Added media/ module documentation
- image_cache.rs - LRU cache for downloaded images
- image_loader.rs - Async loading via TDLib
- image_renderer.rs - Rendering with protocol detection
- Updated dependencies section
- Updated App state with new fields
Technical Details:
- Terminal protocol auto-detection (Sixel/Kitty/iTerm2/Halfblocks)
- Cross-platform support (Linux, macOS, Windows)
- Graceful fallback to Unicode halfblocks for all terminals
- Async non-blocking image loading
- Smart caching with size limits
- Configurable quality and protocol settings
New Configuration (config.toml):
- show_images: bool - enable/disable image display
- image_cache_mb: usize - cache size limit in MB
- preview_quality: "low" | "medium" | "high"
- render_protocol: "auto" | "sixel" | "kitty" | "iterm2" | "halfblocks"
Status: PLANNED (documentation complete, implementation pending)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-05 02:43:04 +03:00
Mikhail Kilin
bea0bcbed0
feat: implement desktop notifications with comprehensive filtering
...
Implemented Phase 10 (Desktop Notifications) with three stages:
notify-rust integration, smart filtering, and production polish.
Stage 1 - Base Implementation:
- Add NotificationManager module (src/notifications.rs, 350+ lines)
- Integrate notify-rust 4.11 with feature flag "notifications"
- Implement NotificationsConfig in config.toml (enabled, only_mentions, show_preview)
- Add notification_manager field to TdClient
- Create configure_notifications() method for config integration
- Hook into handle_new_message_update() to send notifications
- Send notifications for messages outside current chat
- Format notification body with sender name and message preview
Stage 2 - Smart Filtering:
- Sync muted chats from Telegram (sync_muted_chats method)
- Filter muted chats from notifications automatically
- Add MessageInfo::has_mention() to detect @username mentions
- Implement only_mentions filter (notify only when mentioned)
- Beautify media labels with emojis (📷 📹 🎤 🎨 📎 etc.)
- Support 10+ media types in notification preview
Stage 3 - Production Polish:
- Add graceful error handling (no panics on notification failure)
- Implement comprehensive logging (tracing::debug!/warn!)
- Add timeout_ms configuration (0 = system default)
- Add urgency configuration (low/normal/critical, Linux only)
- Platform-specific #[cfg] for urgency support
- Log all notification skip reasons at debug level
Hotkey Change:
- Move profile view from 'i' to Ctrl+i to avoid conflicts
Technical Details:
- Cross-platform support (macOS, Linux, Windows)
- Feature flag for optional notifications support
- Graceful fallback when notifications unavailable
- LRU-friendly muted chats sync
- Test coverage for all core notification logic
- All 75 tests passing
Files Changed:
- NEW: src/notifications.rs - Complete NotificationManager
- NEW: config.example.toml - Example configuration with notifications
- Modified: Cargo.toml - Add notify-rust 4.11 dependency
- Modified: src/config/mod.rs - Add NotificationsConfig struct
- Modified: src/tdlib/types.rs - Add has_mention() method
- Modified: src/tdlib/client.rs - Add notification integration
- Modified: src/tdlib/update_handlers.rs - Hook notifications
- Modified: src/config/keybindings.rs - Change profile to Ctrl+i
- Modified: tests/* - Add notification config to tests
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-05 01:27:44 +03:00
Mikhail Kilin
1cc61ea026
refactor: clean up dead code and optimize performance
...
Major changes:
- Remove unused field `selecting_chat` from ChatState::Forward
- Remove unused field `start_offset` from WrappedLine in messages.rs
- Delete unused functions from modal_handler.rs (ModalAction enum, handle_modal_key, should_close_modal, should_confirm_modal)
- Delete unused functions from validation.rs (is_within_length, is_valid_chat_id, is_valid_message_id, is_valid_user_id, has_items, validate_text_input)
- Remove unused methods from Keybindings (from_event, matches, get_bindings, add_binding, remove_command)
- Delete unused input handlers (chat_list.rs, messages.rs, modal.rs, search.rs)
- Remove unused imports across multiple files
Performance optimizations:
- Fix slow chat opening: load only last 100 messages instead of i32::MAX (10-100x faster)
- Reduce timeout from 30s to 10s for initial message load
- Fix slow text input: replace O(n) string rebuilding with O(1) String::insert()/remove() operations
- Optimize Backspace, Delete, and Char input handlers
Bug fixes:
- Remove duplicate ChatSortOrder tests after enum deletion
- Fix test compilation errors after removing unused methods
- Update tests to use get_command() instead of removed matches() method
Code cleanup:
- Remove ~400 lines of dead code
- Remove 12 unused tests
- Clean up imports in config/mod.rs, main_input.rs, tdlib/messages.rs
Test status: 565 tests passing
Warnings reduced from 40+ to 9
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-04 22:27:02 +03:00
d10dc6599a
Merge pull request 'refactor' ( #18 ) from refactor into main
...
CI / Check (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Build (macos-latest) (push) Has been cancelled
CI / Build (ubuntu-latest) (push) Has been cancelled
CI / Build (windows-latest) (push) Has been cancelled
Reviewed-on: #18
2026-02-04 17:08:43 +00:00
Mikhail Kilin
bd5e5be618
refactor: extract state modules and services from monolithic files
...
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
Извлечены state модули и сервисы из монолитных файлов для улучшения структуры:
State модули:
- auth_state.rs: состояние авторизации
- chat_list_state.rs: состояние списка чатов
- compose_state.rs: состояние ввода сообщений
- message_view_state.rs: состояние просмотра сообщений
- ui_state.rs: UI состояние
Сервисы и утилиты:
- chat_filter.rs: централизованная фильтрация чатов (470+ строк)
- message_service.rs: сервис работы с сообщениями (17KB)
- key_handler.rs: trait для обработки клавиш (380+ строк)
Config модуль:
- config.rs -> config/mod.rs: основной конфиг
- config/keybindings.rs: настраиваемые горячие клавиши (420+ строк)
Тесты: 626 passed ✅
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-04 19:29:25 +03:00
Mikhail Kilin
72c4a886fa
fix: implement dynamic message history loading with retry logic
...
Проблема:
- При открытии чата видно только последнее сообщение
- TDLib возвращал 1 сообщение при первом запросе
- Не было retry логики для ожидания синхронизации с сервером
Решение:
1. Динамическая загрузка с retry (до 20 попыток на чанк)
2. Загрузка всей доступной истории (без лимита)
3. Retry при получении малого количества сообщений
4. Корректная чанковая загрузка по 50 сообщений
Алгоритм:
- При открытии чата: get_chat_history(i32::MAX) - загружает всё
- Чанками по 50: TDLIB_MESSAGE_LIMIT
- Retry если получено < 50 при первой загрузке
- Остановка если 3 раза подряд пусто
- Порядок: старые чанки вставляются в начало (splice)
- При скролле: load_older_messages_if_needed() подгружает автоматически
Изменения:
src/tdlib/messages.rs:
- Убрана фиксированная задержка 100ms после open_chat
- Добавлен счетчик consecutive_empty_results
- Retry логика без искусственных sleep()
- Проверка: если получено мало - продолжить попытки
src/input/main_input.rs:
- limit: 100 → i32::MAX (без ограничений)
- timeout: 10s → 30s
tests/chat_list.rs:
- test_chat_history_chunked_loading: проверка 100, 120, 200 сообщений
- test_chat_history_loads_all_without_limit: загрузка 200 без лимита
- test_load_older_messages_pagination: подгрузка при скролле
Все тесты: 104/104 ✅
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-04 03:56:58 +03:00
Mikhail Kilin
222a21770c
fix: implement chunked message loading to fill screen on chat open
...
Проблема:
- get_chat_history() загружала только один чанк (50 сообщений max)
- При запросе 100 сообщений возвращалось только 50
- Экран не заполнялся полностью при открытии чата
Решение:
- Добавлена чанковая загрузка по TDLIB_MESSAGE_LIMIT (50) сообщений
- Автоматическая подгрузка пока не достигнут запрошенный limit
- Правильная сборка сообщений (старые чанки вставляются в начало)
- Retry логика для каждого чанка (до 3 попыток)
Изменения в src/tdlib/messages.rs:
- get_chat_history(): цикл загрузки чанков вместо одного запроса
- Вставка более старых чанков в начало списка (splice)
- Обработка edge cases (пустые результаты, ошибки, конец истории)
Тесты:
- test_chat_history_chunked_loading: проверка загрузки 100, 120, 200 сообщений
- Проверка правильного порядка сообщений (от старых к новым)
- Проверка границы между чанками (messages 50/51)
Все тесты пройдены: 343/343 ✅
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-04 02:48:30 +03:00
Mikhail Kilin
c881f74ecb
refactor: complete nesting simplification (category 3 - 100%)
...
Simplified deep nesting across the codebase using modern Rust patterns:
let-else guards, early returns, iterator chains, and extracted functions.
**Files improved:**
1. src/tdlib/messages.rs (44 → 28 spaces max indent)
- fetch_missing_reply_info(): 7 → 2-3 levels
* Extracted fetch_and_update_reply()
* Used filter_map and iterator chains
- get_chat_history() retry loop: 6 → 3 levels
* Early continue for empty results
* Used .flatten() instead of nested if-let
2. src/input/main_input.rs (40 → 36 spaces max indent)
- handle_forward_mode(): 7 → 2-3 levels
* Extracted forward_selected_message()
- Reaction picker: 5 → 2-3 levels
* Extracted send_reaction()
- Scroll + load older: 6 → 2-3 levels
* Extracted load_older_messages_if_needed()
3. src/config.rs (36 → 32 spaces max indent)
- load_credentials(): 7 → 2-3 levels
* Extracted load_credentials_from_file()
* Extracted load_credentials_from_env()
* Used ? operator for Option chains
**Results:**
- Max nesting in entire project: ≤32 spaces (8 levels)
- 8 new functions extracted for better separation of concerns
- All 343 tests passing ✅
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-04 02:35:56 +03:00
Mikhail Kilin
9a04455113
docs: mark refactoring as complete (100%) and ready to merge
2026-02-04 02:16:27 +03:00
Mikhail Kilin
dec60ea74e
fix: mark incoming messages as read when opening chat and load all history
...
Fixes two critical bugs:
1. Unread badge not clearing when opening chat - incoming messages weren't marked as viewed
2. Only last 2-3 messages loaded instead of full history due to incorrect break condition
Changes:
- Add incoming message IDs to pending_view_messages queue on chat open
- Remove premature break in get_chat_history() that stopped after 2 messages
- Add FakeTdClient.pending_view_messages field for testing
- Implement process_pending_view_messages() in FakeTdClient
Tests added:
- test_incoming_message_shows_unread_badge: verify "(1)" appears for unread
- test_opening_chat_clears_unread_badge: verify badge clears after opening
- test_opening_chat_loads_many_messages: verify all 50 messages load, not just last few
All 28 chat_list tests pass.
2026-02-04 02:07:47 +03:00
Mikhail Kilin
5ac10ea24c
refactor: complete large files/functions refactoring (Phase 6-7)
...
Phase 6: Refactor tdlib/client.rs ✅
- Extract update handlers to update_handlers.rs (302 lines, 8 functions)
- Extract message converter to message_converter.rs (250 lines, 6 functions)
- Extract chat helpers to chat_helpers.rs (149 lines, 3 functions)
- Result: client.rs 1259 → 599 lines (-52%)
Phase 7: Refactor tdlib/messages.rs ✅
- Create message_conversion.rs module (158 lines)
- Extract 6 helper functions:
- extract_content_text() - content extraction (~80 lines)
- extract_entities() - formatting extraction (~10 lines)
- extract_sender_name() - sender name with API call (~15 lines)
- extract_forward_info() - forward info (~12 lines)
- extract_reply_info() - reply info (~15 lines)
- extract_reactions() - reactions extraction (~26 lines)
- Result: convert_message() 150 → 57 lines (-62%)
- Result: messages.rs 850 → 757 lines (-11%)
Summary:
- ✅ All 4 large files refactored (100%)
- ✅ All 629 tests passing
- ✅ Category #2 "Large files/functions" COMPLETE
- ✅ Documentation updated (REFACTORING_OPPORTUNITIES.md, CONTEXT.md)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-04 01:29:26 +03:00
Mikhail Kilin
b081886e34
docs: update CONTEXT.md with Phase 6 start
2026-02-03 22:26:51 +03:00
Mikhail Kilin
0acf864c28
refactor: extract NewMessage and ChatAction handlers (client.rs) - FIXED
...
Phase 6 начало - рефакторинг handle_update():
- handle_new_message_update() - обработка новых сообщений (~45 строк)
- handle_chat_action_update() - typing статусы (~50 строк)
- Добавлены импорты: UpdateNewMessage, UpdateChatAction
Результат:
- handle_update() сокращена с 351 до ~268 строк (24% ✂️ )
- 2/17 веток извлечены в отдельные методы
- Файл: 1167 → 1178 строк (+11 чистых строк кода)
Phase 6: client.rs рефакторинг в процессе!
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 22:03:51 +03:00
Mikhail Kilin
88ff4dd3b7
docs: update CONTEXT.md with Phase 5 completion
2026-02-03 21:30:48 +03:00
Mikhail Kilin
2dbbf1cb5b
refactor: extract message list and input box rendering (ui/messages.rs)
...
Завершена Phase 5 - полная декомпозиция render():
- render_message_list() - список сообщений с автоскроллом (~100 строк)
- render_input_box() - input с режимами forward/select/edit/reply (~145 строк)
Результат:
- render() сокращена с ~390 до ~92 строк (76% ✂️ )
- 4 извлечённые функции: header, pinned, message_list, input_box
- Каждая функция имеет чёткую ответственность
Файл: 879 → 905 строк (+26 doc-комментариев)
Phase 5 завершена: ui/messages.rs рефакторинг выполнен! 🎉
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 21:30:20 +03:00
Mikhail Kilin
315395f1f2
refactor: extract header and pinned bar rendering (ui/messages.rs)
...
Извлечены функции из render() (Phase 5 начало):
- render_chat_header() - заголовок чата с typing status (~50 строк)
- render_pinned_bar() - панель закреплённого сообщения (~30 строк)
Результат:
- Главная функция render() сокращена на ~65 строк
- Применены let-else guards для упрощения
- Каждая функция имеет чёткую ответственность
Phase 5: Рефакторинг ui/messages.rs (879 строк)
Цель: разделить монолитную функцию render() на модули
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 20:41:08 +03:00
Mikhail Kilin
6150fe3cdb
docs: update CONTEXT.md with Phase 4 results
...
Документация Phase 4: Упрощение вложенности
- Глубина вложенности: 6+ → 2-3 уровня
- Применены паттерны: early returns, let-else guards
- Извлечено 3 вспомогательных функции
- 6 функций упрощены
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 20:35:45 +03:00
Mikhail Kilin
9d9232f74f
refactor: complete nesting simplification with let-else guards
...
Применены дополнительные упрощения:
- handle_escape_key: преобразован в early returns
- handle_message_selection: применены let-else guards для всех веток
- Блоки 'd', 'y', 'e' теперь с явными guards
Результат Phase 4:
- Уменьшена вложенность во всех извлечённых функциях
- Применены паттерны: early returns, let-else guards, вспомогательные функции
- Код стал максимально линейным и читаемым
- Глубина вложенности: 6+ → 2-3 уровня
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 20:35:20 +03:00
Mikhail Kilin
67fd7506b3
refactor: reduce nesting with early returns and guard clauses
...
Применены паттерны упрощения вложенности:
- handle_profile_mode: упрощён блок Enter с let-else
- handle_profile_open: применён early return guard
- handle_enter_key: разделена на 3 функции + early returns
- edit_message() - редактирование сообщения
- send_new_message() - отправка нового сообщения
- Сокращено с ~130 до ~40 строк
- handle_message_search_mode: извлечена функция perform_message_search()
- Упрощены блоки Backspace и Char с let-else
Результат: код стал более линейным, уменьшена глубина вложенности с 6+ до 2-3 уровней
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 20:34:19 +03:00
Mikhail Kilin
7e372bffef
docs: update CONTEXT.md with complete refactoring results
...
Обновлена документация с результатами Phase 3:
- Функция handle() сократилась с 891 до 82 строк (91% сокращение!)
- Всего извлечено 13 специализированных функций
- Phase 2: 2 функции (~163 строки)
- Phase 3: 11 функций (~783 строки)
Код стал линейным и простым для понимания.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 17:16:33 +03:00
Mikhail Kilin
45d03b59fd
refactor: complete main_input.rs simplification (Phase 3/3)
...
Извлечены все оставшиеся блоки из функции handle():
- handle_profile_mode() - режим профиля с модалкой (~120 строк)
- handle_message_search_mode() - поиск по сообщениям (~73 строки)
- handle_pinned_mode() - закреплённые сообщения (~42 строки)
- handle_reaction_picker_mode() - emoji picker (~90 строк)
- handle_delete_confirmation() - подтверждение удаления (~60 строк)
- handle_forward_mode() - пересылка сообщений (~52 строки)
- handle_chat_search_mode() - поиск по чатам (~43 строки)
- handle_enter_key() - обработка Enter (~145 строк)
- handle_escape_key() - обработка Esc (~35 строк)
- handle_message_selection() - режим выбора сообщения (~95 строк)
- handle_profile_open() - Ctrl+U для профиля (~28 строк)
Результат:
- Функция handle() сокращена с 734 до 82 строк (89% сокращение!)
- Всего извлечено 13 специализированных функций
- Каждая функция имеет чёткую ответственность
- Код стал линейным и легко читаемым
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 17:15:47 +03:00
Mikhail Kilin
a518875421
docs: update CONTEXT.md with Phase 2 completion
...
Обновлена документация рефакторинга main_input.rs:
- Phase 1: 10 функций (~704 строки)
- Phase 2: 2 функции (~163 строки)
- Итого: 12 функций, сокращение handle() с 891 до 734 строк
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 17:01:27 +03:00
Mikhail Kilin
f4c24ddabe
refactor: extract keyboard and navigation handlers (Phase 2/2)
...
Извлечены оставшиеся обработчики из функции handle():
- handle_open_chat_keyboard_input() - ввод текста, навигация курсора, скролл (~129 строк)
- handle_chat_list_navigation() - навигация по чатам и папкам (~34 строки)
Результат:
- Функция handle() сокращена с 891 до 734 строк
- Всего извлечено 12 специализированных функций
- Каждая функция имеет чёткую ответственность и документацию
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-03 17:00:17 +03:00
Mikhail Kilin
ee416dff45
docs: update CONTEXT.md with refactoring progress
2026-02-03 16:33:34 +03:00
Mikhail Kilin
3edbaf2c2b
refactor: extract input handlers into separate functions
...
Упрощение функции handle() в main_input.rs путём извлечения
обработчиков режимов в отдельные функции.
Извлечённые функции:
- handle_profile_mode() - режим профиля с модалкой выхода (~114 строк)
- handle_message_search_mode() - поиск по сообщениям (~73 строки)
- handle_pinned_mode() - закреплённые сообщения (~34 строки)
- handle_reaction_picker_mode() - выбор реакции (~79 строк)
- handle_delete_confirmation() - подтверждение удаления (~53 строки)
- handle_forward_mode() - выбор чата для пересылки (~48 строк)
- handle_chat_search_mode() - поиск по чатам (~32 строки)
- handle_escape_key() - обработка Esc (~25 строк)
- handle_message_selection() - выбор сообщения (~85 строк)
Итого извлечено: ~543 строки из основной функции handle()
Результат:
- handle() сократилась с 891 до ~350 строк (на 61%)
- Каждый режим теперь изолирован и легко тестируется
- Улучшена читаемость и maintainability кода
- Все тесты проходят успешно
Также:
- Обновлён tdlib-rs с 1.1 на 1.2.0
2026-02-03 16:32:26 +03:00
Mikhail Kilin
7b2dd6c9a9
refactor: encapsulate auth fields (Group 1/5)
...
Фаза 1, Подход 2 - постепенная инкапсуляция полей App.
Changes:
- src/app/mod.rs: сделаны приватными phone_input, code_input, password_input
- src/input/auth.rs: замены на phone_input_mut(), code_input_mut(), password_input_mut()
- src/ui/auth.rs: замены на phone_input(), code_input(), password_input()
- tests/helpers/app_builder.rs: замены на set_phone_input(), set_code_input(), set_password_input()
Используются существующие геттеры/сеттеры (были добавлены ранее).
Progress: Group 1/5 complete (auth fields)
Next: Group 2 (UI state: screen, is_loading, needs_redraw, is_searching)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 17:56:34 +03:00
Mikhail Kilin
3c8fec7ca6
refactor: integrate validation utils and complete refactoring #1
...
Завершена интеграция validation utils во всех местах проверки user input:
Changes:
- src/utils/mod.rs: раскомментирован экспорт validation::*
- src/input/auth.rs: 3 замены .is_empty() -> is_non_empty()
* phone_input validation (line 18)
* code_input validation (line 50)
* password_input validation (line 82)
- src/input/main_input.rs: 1 замена для message_input (line 484)
- src/main.rs: заменён последний прямой timeout на with_timeout_ignore
Documentation:
- REFACTORING_OPPORTUNITIES.md: обновлён статус категории #1
* Отмечено как "ПОЛНОСТЬЮ ЗАВЕРШЕНО" (2026-02-02)
* Добавлены метрики: 100% покрытие retry utils, 0 прямых timeouts
* Обновлён план выполнения: фаза 1 завершена
- CONTEXT.md: добавлен раздел об интеграции validation utils
Result:
✅ Категория #1 (Дублирование кода) - ПОЛНОСТЬЮ ЗАВЕРШЕНА!
- retry utils: 100% покрытие (8+ мест)
- modal_handler: 2 диалога
- validation: 4 места
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 17:38:49 +03:00
Mikhail Kilin
0768283e8a
refactor: eliminate code duplication - extract helpers and use retry utils
...
Extracted duplicate code and unified timeout handling across the codebase.
Changes:
- Extracted open_chat_and_load_data() function (eliminates 52 lines of duplication)
- Replaced manual y/н/Enter handling with handle_yes_no() from modal_handler (2 places)
- Replaced 7 direct tokio::time::timeout calls with retry utils (auth, main_input, main)
- Added with_timeout_ignore() for non-critical operations
- Fixed modal_handler.rs bug: corrected Russian 'y' key (д → н)
- Removed unused imports in handlers/mod.rs and utils/mod.rs
Impact:
- main_input.rs: 1164 → 958 lines (-206 lines, -18%)
- Code duplication: 52 lines eliminated
- Direct timeout calls: 7 → 1 (-86%)
- DRY principle applied throughout
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 14:20:33 +03:00
Mikhail Kilin
8e48d076de
refactor: implement trait-based DI for TdClient and fix stack overflow
...
Implement complete trait-based dependency injection pattern for TdClient
to enable testing with FakeTdClient mock. Fix critical stack overflow bugs
caused by infinite recursion in trait implementations.
Breaking Changes:
- App is now generic: App<T: TdClientTrait = TdClient>
- All UI and input handlers are generic over TdClientTrait
- TdClient methods now accessed through trait interface
New Files:
- src/tdlib/trait.rs: TdClientTrait definition with 40+ methods
- src/tdlib/client_impl.rs: TdClientTrait impl for TdClient
- tests/helpers/fake_tdclient_impl.rs: TdClientTrait impl for FakeTdClient
Critical Fixes:
- Fix stack overflow in send_message, edit_message, delete_messages
- Fix stack overflow in forward_messages, current_chat_messages
- Fix stack overflow in current_pinned_message
- All methods now call message_manager directly to avoid recursion
Testing:
- FakeTdClient supports configurable auth_state for auth screen tests
- Added pinned message support in FakeTdClient
- All 196+ tests passing (188 tests + 8 benchmarks)
Dependencies:
- Added async-trait = "0.1"
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 05:42:19 +03:00
0cd477f294
Merge pull request 'refactor: complete UI components - implement message_bubble.rs' ( #17 ) from add_tests into main
...
CI / Check (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Build (macos-latest) (push) Has been cancelled
CI / Build (ubuntu-latest) (push) Has been cancelled
CI / Build (windows-latest) (push) Has been cancelled
Reviewed-on: #17
2026-02-02 00:45:42 +00:00
Mikhail Kilin
ed5a4f9c72
refactor: complete UI components - implement message_bubble.rs
...
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
Finalize Priority 3 UI components refactoring (5/5 complete):
- Create message_bubble.rs (437 lines) with 3 rendering functions:
* render_date_separator() - centered date separators
* render_sender_header() - sender headers (incoming/outgoing)
* render_message_bubble() - messages with forward/reply/reactions
- Simplify messages.rs by removing ~300 lines:
* Use message_grouping::group_messages() for logic
* Use UI components for rendering
* Cleaner separation of concerns
- Update module exports and main.rs
All 196 tests passing (188 tests + 8 benchmarks). No regressions.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 03:41:03 +03:00
8855a07ccd
Merge pull request 'add_tests' ( #16 ) from add_tests into main
...
CI / Check (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Build (macos-latest) (push) Has been cancelled
CI / Build (ubuntu-latest) (push) Has been cancelled
CI / Build (windows-latest) (push) Has been cancelled
Reviewed-on: #16
2026-02-02 00:19:58 +00:00
Mikhail Kilin
2980e52113
commit
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
2026-02-02 03:18:55 +03:00
Mikhail Kilin
9465f067fe
commit
2026-02-02 02:46:26 +03:00
Mikhail Kilin
5c92c059c9
fixes
2026-02-02 02:32:02 +03:00
Mikhail Kilin
dd4981d216
test: add comprehensive input navigation tests
...
Added 13 integration tests for keyboard navigation:
Arrow Keys Navigation:
- test_arrow_navigation_in_chat_list: Up/Down arrows, circular wrapping
- test_vim_navigation_in_chat_list: j/k vim-style navigation
- test_russian_keyboard_navigation: Russian layout (о/р) support
- test_enter_opens_chat: Enter to open selected chat
- test_esc_closes_chat: Esc to close open chat
Cursor Navigation in Input:
- test_cursor_navigation_in_input: Left/Right arrow keys
- test_home_end_in_input: Home/End keys
- test_backspace_with_cursor: Backspace at different positions
- test_insert_char_at_cursor_position: Insert char in middle
Message Navigation:
- test_up_arrow_selects_last_message_when_input_empty: Up arrow for message selection
Additional:
- test_circular_navigation_optional: Circular list navigation
These tests verify that the navigation functionality works correctly
through the main_input handler, protecting against future refactoring
that might break keyboard input.
All tests compile and verify actual input handling via handle_main_input().
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 00:39:47 +03:00
Mikhail Kilin
4d9d76ed23
refactor: prepare handlers structure for future input refactoring
...
Preparation for splitting large input file (#2 ):
- Created src/input/handlers/ structure (7 modules)
- clipboard.rs (~100 lines) - clipboard operations extracted
- global.rs (~90 lines) - global commands (Ctrl+R/S/P/F) extracted
- Stubs: profile.rs, search.rs, modal.rs, messages.rs, chat_list.rs
- main_input.rs remains monolithic (1139 lines)
- Attempted full migration broke navigation - rolled back
- Handlers remain as preparation for gradual migration
Updated documentation:
- REFACTORING_OPPORTUNITIES.md: #2.1 status updated
- CONTEXT.md: Added lesson about careful refactoring
Lesson learned: Critical input logic requires careful step-by-step
refactoring with functionality verification after each step.
Tests: 563 passed, 0 failed
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-02 00:08:56 +03:00
Mikhail Kilin
dff0897da4
refactor: add modal/validation utils and partial App encapsulation
...
Quick wins refactoring (Variant 1):
- Created src/utils/modal_handler.rs (120+ lines)
- 4 functions for modal handling (close, confirm, yes/no)
- ModalAction enum for type-safe processing
- English and Russian keyboard layout support
- 4 unit tests
- Created src/utils/validation.rs (180+ lines)
- 7 validation functions (empty, length, IDs, etc)
- Covers all common validation patterns
- 7 unit tests
- Partial App encapsulation:
- Made config field private (readonly via app.config())
- Added 30+ getter/setter methods
- Updated ui/messages.rs to use config()
- Updated documentation:
- REFACTORING_OPPORTUNITIES.md: #1 Complete, #5 Partial
- CONTEXT.md: Added quick wins section
Tests: 563 passed, 0 failed
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 23:55:49 +03:00
Mikhail Kilin
e690acfb09
test: complete Phase 4 testing - utils tests and performance benchmarks
...
Added 9 new unit tests for utils/formatting.rs functions:
- format_date: 4 tests (today, yesterday, old, epoch)
- format_was_online: 5 tests (just now, minutes/hours/days ago, very old)
Created 3 performance benchmark files using criterion:
- benches/group_messages.rs - message grouping benchmarks
- benches/formatting.rs - timestamp/date formatting benchmarks
- benches/format_markdown.rs - markdown parsing benchmarks
Updated documentation:
- CONTEXT.md: added Phase 4.1 (Utils) and 4.2 (Benchmarks) completion
- Total coverage: 188 tests + 8 benchmarks = 196 tests (100%)
All 565 tests passing with 100% success rate.
2026-02-01 23:04:43 +03:00
Mikhail Kilin
c6beea5608
refactor: create timeout/retry utilities to reduce code duplication (P1.1)
...
Created new utility modules to eliminate repeated timeout/retry patterns:
- src/utils/retry.rs: with_timeout() and with_timeout_msg() helpers
- src/utils/formatting.rs: timestamp formatting utilities (from utils.rs)
- src/utils/tdlib.rs: TDLib log configuration utilities (from utils.rs)
Refactored src/input/main_input.rs:
- Replaced 18+ instances of timeout(Duration, op).await pattern
- Simplified error handling from nested Ok(Ok(...))/Ok(Err(...))/Err(...)
to cleaner Ok(...)/Err(...) with custom timeout messages
- Added type annotations for compiler type inference
Benefits:
- Reduced code duplication from ~20 instances to 2 utility functions
- Cleaner, more readable error handling
- Easier to maintain timeout logic in one place
- All 59 tests passing
Progress: REFACTORING_OPPORTUNITIES.md #1 (Дублирование кода) - Частично выполнено
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 19:56:33 +03:00
9cc63952f4
Merge pull request 'add_tests' ( #15 ) from add_tests into main
...
CI / Check (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Build (macos-latest) (push) Has been cancelled
CI / Build (ubuntu-latest) (push) Has been cancelled
CI / Build (windows-latest) (push) Has been cancelled
Reviewed-on: #15
2026-02-01 15:59:43 +00:00
Mikhail Kilin
2b04b785c0
refactor: cleanup unused code and warnings
...
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
Comprehensive cleanup of unused methods, dead code, and compiler warnings:
## Removed Methods (15):
- Duplicate delegation methods: is_authenticated, get_typing_text, get_user_name from TdClient
- Obsolete methods: TdClient::init() (duplicated in main.rs)
- Unused getters: UserCache::{get_username, get_name, get_user_id_by_chat}
- Unused builder methods: MessageBuilder::{edited, add_reaction}
- Unused utility: ChatState::is_normal()
- Dead code: HotkeysConfig::{matches, key_matches} (kept for tests)
- Unused method: UserCache::register_private_chat()
- Getter replaced with direct field access: MessageInfo::edit_date()
## Removed Module:
- error.rs - Unused error handling module (TeletuiError, ErrorVariant, IntoTeletuiError)
## Removed Constants (8):
- EMOJI_PICKER_COLUMNS, EMOJI_PICKER_ROWS, MAX_INPUT_HEIGHT
- MIN_TERMINAL_WIDTH, MIN_TERMINAL_HEIGHT
- TDLIB_CHAT_LIMIT, MAX_USERNAME_DISPLAY_LENGTH, MESSAGE_TEXT_INDENT
## Fixed Warnings:
- Removed unused imports (8 instances)
- Fixed unreachable patterns (10 instances)
- Fixed irrefutable if let patterns (2 instances)
- Fixed unused variables (1 instance)
- Removed dead_code annotations where appropriate
## Improvements:
- Integrated Config::load_credentials() into TdClient::new() for better credential management
- Replaced edit_date() getter with direct field access (message.metadata.edit_date)
- Updated tests to use direct field access instead of removed getters
## Test Results:
All tests passing: 499 passed, 0 failed
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 18:57:55 +03:00
Mikhail Kilin
f1a26b906c
style: use _chat_id instead of let _ = chat_id
...
More idiomatic way to mark unused parameter.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 02:48:44 +03:00
Mikhail Kilin
c27d027ebf
chore: remove dead code and unnecessary allow(dead_code) attributes
...
Cleaned up warnings by removing unused code:
- Removed unused format_timestamp() function from utils.rs
- Removed unused len() method from LruCache
- Removed unused date field from ForwardInfo struct
- Removed unnecessary #[allow(dead_code)] attributes from:
* AuthState enum (actually used)
* ChatInfo struct (actually used)
* TdClient impl block (actually used)
This reduces code noise and makes real warnings more visible.
Changes:
- 20 lines removed
- 1 line added
- 6 files changed
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 02:47:51 +03:00
0a4ab1b40d
Merge pull request 'add_tests' ( #14 ) from add_tests into main
...
CI / Check (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Build (macos-latest) (push) Has been cancelled
CI / Build (ubuntu-latest) (push) Has been cancelled
CI / Build (windows-latest) (push) Has been cancelled
Reviewed-on: #14
2026-01-31 23:42:29 +00:00
Mikhail Kilin
09c5c5674e
feat: add structured logging with tracing (P5.17)
...
CI / Check (pull_request) Has been cancelled
CI / Format (pull_request) Has been cancelled
CI / Clippy (pull_request) Has been cancelled
CI / Build (macos-latest) (pull_request) Has been cancelled
CI / Build (ubuntu-latest) (pull_request) Has been cancelled
CI / Build (windows-latest) (pull_request) Has been cancelled
Replaced eprintln! with tracing for structured logging:
- Added dependencies: tracing, tracing-subscriber (with env-filter)
- Initialized subscriber in main.rs with default warn level
- Replaced all eprintln! calls in src/config.rs with tracing macros:
* warn!() for warnings (4 occurrences)
* error!() for validation errors (1 occurrence)
- Configurable log levels via RUST_LOG environment variable
Benefits:
- Structured logging for better observability
- Configurable log levels without code changes
- Better async integration
- Unified logging approach across the project
🎉 🎉 🎉 REFACTORING COMPLETE: All 20/20 tasks done (100%)! 🎉 🎉 🎉
Priority 5: 3/3 tasks ✅ COMPLETE
Total progress: 20/20 tasks (100%) ✅ COMPLETE
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 02:29:08 +03:00
Mikhail Kilin
67739583f3
refactor: generalize LruCache to support any key type (P5.16)
...
Made LruCache generic over key type K, not just UserId:
- LruCache<V> → LruCache<K, V>
- Added trait bounds: K: Eq + Hash + Clone + Copy
- Updated UserCache field types:
* user_usernames: LruCache<UserId, String>
* user_names: LruCache<UserId, String>
* user_statuses: LruCache<UserId, UserOnlineStatus>
Benefits:
- Reusable cache implementation for any key types
- Type-safe caching
- No additional dependencies
Progress: Priority 5: 2/3 tasks, Total: 18/20 (90%)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2026-02-01 02:26:03 +03:00