193 lines
15 KiB
Markdown
193 lines
15 KiB
Markdown
# Текущий контекст проекта
|
||
|
||
## Статус: Фаза 9 — Расширенные возможности
|
||
|
||
### Что сделано
|
||
|
||
#### 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) текст` для входящих
|
||
- **Галочки прочтения** (✓ отправлено, ✓✓ прочитано) — обновляются в реальном времени
|
||
- **Отметка сообщений как прочитанных**: при открытии чата счётчик непрочитанных сбрасывается
|
||
- **Отправка текстовых сообщений**
|
||
- **Редактирование сообщений**: ↑ при пустом инпуте → выбор → Enter → редактирование
|
||
- **Удаление сообщений**: в режиме выбора нажать `d` / `в` / `Delete` → модалка подтверждения
|
||
- **Reply на сообщения**: в режиме выбора нажать `r` / `к` → режим ответа с превью
|
||
- **Forward сообщений**: в режиме выбора нажать `f` / `а` → выбор чата для пересылки
|
||
- **Отображение пересланных сообщений**: индикатор "↪ Переслано от" с именем отправителя
|
||
- **Индикатор редактирования**: ✎ рядом с временем для отредактированных сообщений
|
||
- **Новые сообщения в реальном времени** при открытом чате
|
||
- **Поиск по чатам** (Ctrl+S): фильтрация по названию и @username
|
||
- **Typing indicator** ("печатает..."): отображение статуса набора текста собеседником и отправка своего статуса
|
||
- **Закреплённые сообщения**: отображение pinned message вверху чата с переходом к нему
|
||
- **Поиск по сообщениям в чате** (Ctrl+F): поиск текста внутри открытого чата с навигацией по результатам
|
||
- **Черновики**: автосохранение набранного текста при переключении между чатами
|
||
- **Профиль пользователя/чата** (`i`): просмотр информации о собеседнике или группе
|
||
- **Копирование сообщений** (`y`/`н`): копирование текста сообщения в системный буфер обмена
|
||
- **Реакции на сообщения**:
|
||
- Отображение реакций под сообщениями
|
||
- Логика отображения: 1 человек = только emoji, 2+ = emoji + счётчик
|
||
- Свои реакции в рамках [👍], чужие без рамок 👍
|
||
- Emoji picker с сеткой доступных реакций (8 в ряду)
|
||
- Добавление/удаление реакций (toggle)
|
||
- Обновление реакций в реальном времени через Update::MessageInteractionInfo
|
||
- **Кеширование имён пользователей**: имена загружаются асинхронно и обновляются в UI
|
||
- **Папки Telegram**: загрузка и переключение между папками (1-9)
|
||
- **Медиа-заглушки**: [Фото], [Видео], [Голосовое], [Стикер], [GIF] и др.
|
||
- **Markdown форматирование в сообщениях**:
|
||
- **Жирный** (bold)
|
||
- *Курсив* (italic)
|
||
- __Подчёркнутый__ (underline)
|
||
- ~~Зачёркнутый~~ (strikethrough)
|
||
- `Код` (inline code, Pre, PreCode) — cyan на тёмном фоне
|
||
- Спойлеры — скрытый текст (серый на сером)
|
||
- Ссылки (URL, TextUrl, Email, Phone) — синий с подчёркиванием
|
||
- @Упоминания — синий с подчёркиванием
|
||
|
||
#### Состояние сети
|
||
- **Индикатор в футере**: показывает текущее состояние подключения
|
||
- `⚠ Нет сети` — красный, ожидание сети
|
||
- `⏳ Прокси...` — cyan, подключение к прокси
|
||
- `⏳ Подключение...` — cyan, подключение к серверам
|
||
- `⏳ Обновление...` — cyan, синхронизация данных
|
||
|
||
#### Оптимизации
|
||
- **60 FPS ready**: poll таймаут 16ms, рендеринг только при изменениях (`needs_redraw` флаг)
|
||
- **Оптимизация памяти**:
|
||
- Очистка сообщений при закрытии чата
|
||
- Лимит кэша пользователей (500)
|
||
- Периодическая очистка неактивных записей
|
||
- **Минимальное разрешение**: предупреждение если терминал меньше 80x20
|
||
|
||
#### Динамический инпут
|
||
- **Автоматическое расширение**: поле ввода увеличивается при длинном тексте (до 10 строк)
|
||
- **Перенос текста**: длинные сообщения переносятся на новые строки
|
||
- **Блочный курсор**: vim-style курсор █ с возможностью перемещения по тексту
|
||
|
||
#### Управление
|
||
- `↑/↓` стрелки — навигация по списку чатов
|
||
- `Enter` — открыть чат / отправить сообщение
|
||
- `Esc` — закрыть открытый чат / отменить поиск
|
||
- `Ctrl+S` — поиск по чатам (фильтрация по названию и username)
|
||
- `Ctrl+R` — обновить список чатов
|
||
- `Ctrl+C` — выход (graceful shutdown)
|
||
- `↑/↓` в открытом чате — скролл сообщений (с подгрузкой старых)
|
||
- `↑` при пустом инпуте — выбор сообщения для редактирования
|
||
- `Enter` в режиме выбора — начать редактирование
|
||
- `r` / `к` в режиме выбора — ответить на сообщение (reply)
|
||
- `f` / `а` в режиме выбора — переслать сообщение (forward)
|
||
- `d` / `в` / `Delete` в режиме выбора — удалить сообщение (с подтверждением)
|
||
- `y` / `н` / `Enter` — подтвердить удаление в модалке
|
||
- `n` / `т` / `Esc` — отменить удаление в модалке
|
||
- `Esc` — отменить выбор/редактирование/reply
|
||
- `1-9` — переключение папок (в списке чатов)
|
||
- `Ctrl+F` — поиск по сообщениям в открытом чате
|
||
- `n` / `N` — навигация по результатам поиска (следующий/предыдущий)
|
||
- `i` — открыть профиль пользователя/чата
|
||
- `y` / `н` в режиме выбора — скопировать сообщение в буфер обмена
|
||
- `e` / `у` в режиме выбора — добавить реакцию (открывает emoji picker)
|
||
- `←` / `→` / `↑` / `↓` в emoji picker — навигация по сетке реакций
|
||
- `Enter` в emoji picker — добавить/удалить реакцию
|
||
- `Esc` в emoji picker — закрыть picker
|
||
- **Редактирование текста в инпуте:**
|
||
- `←` / `→` — перемещение курсора
|
||
- `Home` — курсор в начало
|
||
- `End` — курсор в конец
|
||
- `Backspace` — удалить символ слева
|
||
- `Delete` — удалить символ справа
|
||
|
||
### Структура проекта
|
||
|
||
```
|
||
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)
|
||
|
||
```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 (Фаза 9)
|
||
|
||
- [ ] Конфигурационный файл (~/.config/tele-tui/config.toml)
|
||
|
||
## Известные проблемы
|
||
|
||
1. При первом запуске нужно пройти авторизацию
|
||
2. Время отображается с фиксированным смещением +3 (MSK)
|