Commit Graph

43 Commits

Author SHA1 Message Date
Mikhail Kilin
260b81443e style: replace DarkGray with Rgb(160,160,160) for better terminal compatibility
DarkGray renders differently across terminals; a specific RGB value gives
consistent appearance. Also always show the account indicator in the footer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 00:57:06 +03:00
Mikhail Kilin
a095fe277b fix: always reserve space for selection marker to prevent text shift
Some checks failed
ci/woodpecker/pr/check Pipeline failed
Render "  " (2 spaces) for unselected messages instead of nothing,
so text stays aligned when navigating with the ▶ selection indicator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 15:49:08 +03:00
Mikhail Kilin
d4e1ed1376 fix: resolve all 23 clippy warnings
Some checks failed
ci/woodpecker/pr/check Pipeline failed
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-22 17:28:50 +03:00
Mikhail Kilin
264f183510 style: auto-format entire codebase with cargo fmt (stable rustfmt.toml)
Some checks failed
ci/woodpecker/pr/check Pipeline failed
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-22 17:09:51 +03:00
Mikhail Kilin
78fe09bf11 feat: implement photo albums (media groups) and persist account selection
Group photos with shared media_album_id into single album bubbles with
grid layout (up to 3x cols). Album navigation treats grouped photos as
one unit (j/k skip entire album). Persist selected account to
accounts.toml so it survives app restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:18:04 +03:00
Mikhail Kilin
8bd08318bb fixes
Some checks failed
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-14 17:57:37 +03:00
Mikhail Kilin
6639dc876c fixes 2026-02-13 19:52:53 +03:00
Mikhail Kilin
8a467b6418 feat: complete Phase 12 — voice playback ticker, cache, config, and UI
Add playback position ticker in event loop with 1s UI refresh rate,
integrate VoiceCache for downloaded voice files, add [audio] config
section (cache_size_mb, auto_download_voice), and render progress bar
with waveform visualization in message bubbles.

Fix race conditions in AudioPlayer: add `starting` flag to prevent
false `is_stopped()` during ffplay startup, guard pid cleanup so old
threads don't overwrite newer process pids. Implement `resume_from()`
with ffplay `-ss` for real audio seek on unpause (-1s rewind).

Kill ffplay on app exit via `stop_playback()` in shutdown + Drop impl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 16:37:02 +03:00
Mikhail Kilin
2a5fd6aa35 perf: optimize Phase 11 image rendering with dual-protocol architecture
Redesigned UX and performance for inline photo viewing:

UX changes:
- Always-show inline preview (fixed 50 chars width)
- Fullscreen modal on 'v' key with ←/→ navigation between photos
- Loading indicator " Загрузка..." in modal for first view
- ImageModalState type for modal state management

Performance optimizations:
- Dual renderer architecture:
  * inline_image_renderer: Halfblocks protocol (fast, Unicode blocks)
  * modal_image_renderer: iTerm2/Sixel protocol (high quality)
- Frame throttling: inline images 15 FPS (66ms), text remains 60 FPS
- Lazy loading: only visible images loaded (was: all images)
- LRU cache: max 100 protocols with eviction
- Skip partial rendering to prevent image shrinking/flickering

Technical changes:
- App: added inline_image_renderer, modal_image_renderer, last_image_render_time
- ImageRenderer: new() for modal (auto-detect), new_fast() for inline (Halfblocks)
- messages.rs: throttled second-pass rendering, visible-only loading
- modals/image_viewer.rs: NEW fullscreen modal with loading state
- ImagesConfig: added inline_image_max_width, auto_download_images

Result: 10x faster navigation, smooth 60 FPS text, quality modal viewing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 01:36:36 +03:00
Mikhail Kilin
b0f1f9fdc2 feat: implement Phase 11 — inline photo viewing with ratatui-image
Add feature-gated (`images`) inline photo support:
- New types: MediaInfo, PhotoInfo, PhotoDownloadState, ImagesConfig
- Media module: ImageCache (LRU filesystem cache), ImageRenderer (terminal protocol detection)
- Photo metadata extraction from TDLib MessagePhoto with download_file() API
- ViewImage command (v/м) to toggle photo expand/collapse in message selection
- Two-pass UI rendering: placeholder lines in message bubbles + StatefulImage overlay
- Collapse all expanded photos on Esc (exit selection mode)

Dependencies: ratatui-image 8.1, image 0.25 (optional, behind `images` feature flag)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 21:25:17 +03:00
Mikhail Kilin
ffd52d2384 refactor: complete Phase 13 deep architecture refactoring (etaps 3-7)
Split monolithic files into modular architecture:
- ui/messages.rs (893→365 lines): extract modals/, compose_bar.rs
- tdlib/messages.rs (836→3 files): split into messages/mod, convert, operations
- config/mod.rs (642→3 files): extract validation.rs, loader.rs
- Code duplication cleanup: shared components, ~220 lines removed
- Documentation: PROJECT_STRUCTURE.md rewrite, 16 files got //! docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:28:11 +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
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
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
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
Mikhail Kilin
ed5a4f9c72 refactor: complete UI components - implement message_bubble.rs
Some checks failed
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
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
2b04b785c0 refactor: cleanup unused code and warnings
Some checks failed
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
644e36597d fixes 2026-01-31 03:48:50 +03:00
Mikhail Kilin
43960332d9 refactor: restructure MessageInfo with logical field grouping (P2.6)
Сгруппированы 16 плоских полей MessageInfo в 4 логические структуры
для улучшения организации кода и maintainability.

Новые структуры:
- MessageMetadata: id, sender_name, date, edit_date
- MessageContent: text, entities
- MessageState: is_outgoing, is_read, can_be_edited, can_be_deleted_*
- MessageInteractions: reply_to, forward_from, reactions

Изменения:
- Добавлены 4 новые структуры в tdlib/types.rs
- Обновлена MessageInfo для использования новых структур
- Добавлен конструктор MessageInfo::new() для удобного создания
- Добавлены getter методы (id(), text(), sender_name() и др.) для удобного доступа
- Обновлены все места создания MessageInfo (convert_message)
- Обновлены все места использования (~200+ обращений):
  * ui/messages.rs: рендеринг сообщений
  * app/mod.rs: логика приложения
  * input/main_input.rs: обработка ввода и копирование
  * tdlib/client.rs: обработка updates
  * Все тестовые файлы (14 файлов)

Преимущества:
- Логическая группировка данных
- Проще понимать структуру сообщения
- Легче добавлять новые поля в будущем
- Улучшенная читаемость кода

Статус: Priority 2 теперь 80% (4/5 задач)
-  Error enum
-  Config validation
-  Newtype для ID
-  MessageInfo реструктуризация
-  MessageBuilder pattern

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 01:45:54 +03:00
Mikhail Kilin
bba5cbd22d fixes 2026-01-30 23:55:01 +03:00
Mikhail Kilin
433233d766 commit 2026-01-30 17:26:21 +03:00
Mikhail Kilin
4deb0fbe00 commit 2026-01-30 15:07:13 +03:00
Mikhail Kilin
126c7482af fixes
Some checks failed
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-01-29 01:22:57 +03:00
Mikhail Kilin
68a2b7a982 fixes 2026-01-28 11:39:21 +03:00
Mikhail Kilin
051c4a0265 fixes
Some checks failed
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-01-28 01:29:03 +03:00
Mikhail Kilin
f291191577 fixes 2026-01-27 23:29:00 +03:00
Mikhail Kilin
356d2d3064 add account profile 2026-01-27 13:41:29 +03:00
Mikhail Kilin
ac684da820 add draft messages 2026-01-27 12:31:31 +03:00
Mikhail Kilin
dc76e01f3c add find messages 2026-01-27 12:09:05 +03:00
Mikhail Kilin
81dc5b9007 add pinned messages 2026-01-27 04:38:29 +03:00
Mikhail Kilin
4d5625f950 add typings in/out
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 03:59:49 +03:00
Mikhail Kilin
e4dabbe3ac fixes 2026-01-25 01:47:38 +03:00
Mikhail Kilin
fa749d24c5 fixes 2026-01-24 18:53:35 +03:00
Mikhail Kilin
22c4e17377 fixes 2026-01-24 02:22:47 +03:00
Mikhail Kilin
c18f43664e fixes 2026-01-22 15:26:15 +03:00
Mikhail Kilin
1ef341d907 commit 2026-01-21 21:20:18 +03:00
Mikhail Kilin
0a9ae8b448 fixes 2026-01-21 02:49:28 +03:00
Mikhail Kilin
32ab1df1fa fixes 2026-01-21 02:27:08 +03:00
Mikhail Kilin
9912ac11bd fixes 2026-01-20 14:54:30 +03:00
Mikhail Kilin
b6d9291864 fixes 2026-01-20 01:00:12 +03:00
Mikhail Kilin
d701464fde init 2026-01-18 11:49:41 +03:00