Files
telegram-tui/CONTEXT.md
Mikhail Kilin c18f43664e fixes
2026-01-22 15:26:15 +03:00

11 KiB
Raw Blame History

Текущий контекст проекта

Статус: Фаза 6 завершена — Полировка

Что сделано

TDLib интеграция

  • Подключена библиотека tdlib-rs v1.1 с автоматической загрузкой TDLib
  • Реализована авторизация через телефон + код + 2FA пароль
  • Сессия сохраняется автоматически в папке tdlib_data/
  • Отключены логи TDLib через FFI вызов td_execute до создания клиента
  • Updates обрабатываются в отдельном потоке через mpsc канал (неблокирующе)
  • Graceful shutdown: корректное закрытие TDLib при выходе (Ctrl+C)

Функциональность

  • Загрузка списка чатов (до 50 штук)
  • Фильтрация чатов: показываются только чаты из ChatList::Main (без архива)
  • Фильтрация удалённых аккаунтов: "Deleted Account" не отображаются в списке
  • Отображение названия чата, счётчика непрочитанных и @username
  • Иконка 📌 для закреплённых чатов
  • Иконка 🔇 для замьюченных чатов
  • Индикатор @ для чатов с непрочитанными упоминаниями
  • Онлайн-статус: зелёная точка ● для онлайн пользователей
  • Загрузка истории сообщений при открытии чата (множественные попытки)
  • Группировка сообщений по дате (разделители "Сегодня", "Вчера", дата) — по центру
  • Группировка сообщений по отправителю (заголовок с именем)
  • Выравнивание сообщений: исходящие справа (зелёные), входящие слева
  • Перенос длинных сообщений: автоматический wrap на несколько строк
  • Отображение времени и галочек: текст (HH:MM ✓✓) для исходящих, (HH:MM) текст для входящих
  • Галочки прочтения (✓ отправлено, ✓✓ прочитано) — обновляются в реальном времени
  • Отметка сообщений как прочитанных: при открытии чата счётчик непрочитанных сбрасывается
  • Отправка текстовых сообщений
  • Новые сообщения в реальном времени при открытом чате
  • Поиск по чатам (Ctrl+S): фильтрация по названию и @username
  • Кеширование имён пользователей: имена загружаются асинхронно и обновляются в UI
  • Папки Telegram: загрузка и переключение между папками (1-9)
  • Медиа-заглушки: [Фото], [Видео], [Голосовое], [Стикер], [GIF] и др.

Состояние сети

  • Индикатор в футере: показывает текущее состояние подключения
    • ⚠ Нет сети — красный, ожидание сети
    • ⏳ Прокси... — cyan, подключение к прокси
    • ⏳ Подключение... — cyan, подключение к серверам
    • ⏳ Обновление... — cyan, синхронизация данных

Оптимизации

  • 60 FPS ready: poll таймаут 16ms, рендеринг только при изменениях (needs_redraw флаг)
  • Оптимизация памяти:
    • Очистка сообщений при закрытии чата
    • Лимит кэша пользователей (500)
    • Периодическая очистка неактивных записей
  • Минимальное разрешение: предупреждение если терминал меньше 80x20

Динамический инпут

  • Автоматическое расширение: поле ввода увеличивается при длинном тексте (до 10 строк)
  • Перенос текста: длинные сообщения переносятся на новые строки

Управление

  • ↑/↓ стрелки — навигация по списку чатов
  • Enter — открыть чат / отправить сообщение
  • Esc — закрыть открытый чат / отменить поиск
  • Ctrl+S — поиск по чатам (фильтрация по названию и username)
  • Ctrl+R — обновить список чатов
  • Ctrl+C — выход (graceful shutdown)
  • ↑/↓ в открытом чате — скролл сообщений (с подгрузкой старых)
  • 1-9 — переключение папок (в списке чатов)
  • Ввод текста в поле сообщения

Структура проекта

src/
├── main.rs           # Точка входа, event loop, TDLib инициализация, graceful shutdown
├── app/
│   ├── mod.rs        # App структура и состояние (needs_redraw флаг)
│   └── state.rs      # AppScreen enum
├── ui/
│   ├── mod.rs        # Роутинг UI по экранам, проверка минимального размера
│   ├── loading.rs    # Экран загрузки
│   ├── auth.rs       # Экран авторизации
│   ├── main_screen.rs # Главный экран с папками
│   ├── chat_list.rs  # Список чатов (pin, mute, online, mentions)
│   ├── messages.rs   # Область сообщений (wrap, группировка, динамический инпут)
│   └── footer.rs     # Подвал с командами и статусом сети
├── input/
│   ├── mod.rs        # Роутинг ввода
│   ├── auth.rs       # Обработка ввода на экране авторизации
│   └── main_input.rs # Обработка ввода на главном экране
├── utils.rs          # Утилиты (disable_tdlib_logs, format_timestamp, format_date, get_day)
└── tdlib/
    ├── mod.rs        # Модуль экспорта (TdClient, UserOnlineStatus, NetworkState)
    └── client.rs     # TdClient: авторизация, чаты, сообщения, кеш, NetworkState

Ключевые решения

  1. Неблокирующий receive: TDLib updates приходят в отдельном потоке и передаются в main loop через mpsc::channel. Это позволяет UI оставаться отзывчивым.

  2. FFI для логов: Используем прямой вызов td_execute для отключения логов синхронно, до создания клиента, чтобы избежать вывода в терминал.

  3. Синхронизация чатов: Чаты загружаются асинхронно через updates. Main loop периодически синхронизирует app.chats с td_client.chats.

  4. Кеширование имён: При получении Update::User сохраняем имя (first_name + last_name) и username в HashMap. Имена подгружаются асинхронно через очередь pending_user_ids. Кэш ограничен 500 записями.

  5. Группировка сообщений: Сообщения группируются по дате (разделители по центру) и по отправителю (заголовки). Исходящие выравниваются вправо, входящие влево.

  6. Отметка прочтения: При открытии чата вызывается view_messages для всех сообщений. Новые входящие сообщения автоматически отмечаются как прочитанные. Update::ChatReadOutbox обновляет статус галочек.

  7. Graceful shutdown: При Ctrl+C устанавливается флаг остановки, закрывается TDLib клиент, ожидается завершение polling задачи с таймаутом 2 сек.

  8. Оптимизация рендеринга: Флаг needs_redraw позволяет пропускать перерисовку когда ничего не изменилось. Триггеры: TDLib updates, пользовательский ввод, изменение размера терминала.

  9. Перенос текста: Длинные сообщения автоматически разбиваются на строки с учётом ширины терминала. Для исходящих — time_mark на последней строке, для входящих — время на первой строке с отступом для остальных.

Зависимости (Cargo.toml)

ratatui = "0.29"
crossterm = "0.28"
tdlib-rs = { version = "1.1", features = ["download-tdlib"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
dotenvy = "0.15"
chrono = "0.4"

Переменные окружения (.env)

API_ID=your_api_id
API_HASH=your_api_hash

Что НЕ сделано / TODO (Фаза 7)

  • Удалить дублирование current_messages между App и TdClient
  • Использовать единый источник данных для сообщений
  • Реализовать LRU-кэш для user_names/user_statuses вместо простого лимита
  • Lazy loading для имён пользователей (загружать только видимых)
  • Профилирование памяти и устранение утечек
  • Markdown форматирование в сообщениях

Известные проблемы

  1. При первом запуске нужно пройти авторизацию
  2. Время отображается с фиксированным смещением +3 (MSK)