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>
This commit is contained in:
Mikhail Kilin
2026-02-02 05:42:19 +03:00
parent ed5a4f9c72
commit 8e48d076de
38 changed files with 1053 additions and 161 deletions

View File

@@ -7,28 +7,29 @@
//! - Forward mode
use crate::app::App;
use crate::tdlib::TdClientTrait;
use crossterm::event::KeyEvent;
/// Обрабатывает ввод в режиме закреплённых сообщений
pub async fn handle_pinned_input(app: &mut App, key: KeyEvent) {
pub async fn handle_pinned_input<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent) {
// TODO: Implement pinned messages input handling
let _ = (app, key);
}
/// Обрабатывает ввод в режиме выбора реакции
pub async fn handle_reaction_picker_input(app: &mut App, key: KeyEvent) {
pub async fn handle_reaction_picker_input<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent) {
// TODO: Implement reaction picker input handling
let _ = (app, key);
}
/// Обрабатывает ввод в режиме подтверждения удаления
pub async fn handle_delete_confirmation_input(app: &mut App, key: KeyEvent) {
pub async fn handle_delete_confirmation_input<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent) {
// TODO: Implement delete confirmation input handling
let _ = (app, key);
}
/// Обрабатывает ввод в режиме пересылки
pub async fn handle_forward_input(app: &mut App, key: KeyEvent) {
pub async fn handle_forward_input<T: TdClientTrait>(app: &mut App<T>, key: KeyEvent) {
// TODO: Implement forward mode input handling
let _ = (app, key);
}