182 lines
9.7 KiB
Markdown
182 lines
9.7 KiB
Markdown
# Анонс для исполнителя (кратко)
|
||
|
||
Ниже описан текущий статус ветки по функциям:
|
||
- PWA + FCM уведомления
|
||
- личные сообщения (вторая слева вкладка, "Личные сообщения")
|
||
- связи / близкие друзья (центральная вкладка)
|
||
- server-push события (в том числе закрытие сессии)
|
||
|
||
## Что нужно проверить и довести до рабочего состояния
|
||
1. **PWA/FCM**: регистрация service worker, получение FCM token, отправка token на сервер, получение foreground/background уведомлений.
|
||
2. **Личные сообщения**: отправка первого сообщения любому пользователю, входящие по WS, ACK, fallback в FCM, дедупликация на клиенте.
|
||
3. **Связи / близкие друзья**: поиск пользователя, добавление в близкие, обновление графа связей сразу после добавления.
|
||
4. **SessionRevoked**: если сессию закрыли с другого устройства, клиент должен корректно завершить локальную сессию и показать понятное состояние.
|
||
|
||
## Главная цель handoff
|
||
Сделать так, чтобы все описанные сценарии стабильно работали end-to-end без ручных "подпинок".
|
||
|
||
---
|
||
|
||
# Подробное ТЗ и технические детали
|
||
|
||
## 1) Архитектура протокола и общие принципы
|
||
|
||
### 1.1 Формат обмена
|
||
Используется JSON-over-WebSocket.
|
||
- Для запрос-ответ: `op + requestId + payload`
|
||
- Для server-push событий: те же поля, но `event=true`, `requestId` используется как eventId.
|
||
|
||
### 1.2 ID сообщений/событий
|
||
ID генерируются в формате:
|
||
- `prefix-yyyyMMdd-HHmmss-SSS-random10`
|
||
|
||
Реализация: `NetIdGenerator`.
|
||
|
||
### 1.3 Роли каналов доставки
|
||
- **WS** — приоритетная доставка в активные сессии.
|
||
- **FCM** — fallback, если ACK по WS не получен или WS-сессия отсутствует.
|
||
|
||
---
|
||
|
||
## 2) PWA + FCM
|
||
|
||
## 2.1 Что уже добавлено
|
||
### Клиент
|
||
- `shine-UI/manifest.webmanifest`
|
||
- `shine-UI/firebase-messaging-sw.js`
|
||
- `shine-UI/js/services/pwa-push-service.js`
|
||
- `shine-UI/index.html` содержит placeholders:
|
||
- `window.__SHINE_FIREBASE_CONFIG__`
|
||
- `window.__SHINE_FIREBASE_VAPID_KEY__`
|
||
|
||
### Сервер
|
||
- API `UpsertPushToken`
|
||
- Таблица `user_push_tokens`
|
||
- Серверный FCM sender (legacy HTTP): `FcmPushSender`
|
||
- Конфиг: `fcm.server.key` в `application.properties`
|
||
|
||
## 2.2 Как должно работать (целевое поведение)
|
||
1. Клиент после авторизации регистрирует SW.
|
||
2. Просит permission на notifications.
|
||
3. Получает FCM token.
|
||
4. Если token новый/изменился — отправляет `UpsertPushToken`.
|
||
5. Сервер сохраняет token за конкретной сессией.
|
||
|
||
## 2.3 Что проверить/доделать
|
||
- Синхронизация Firebase config между `index.html` и `firebase-messaging-sw.js`.
|
||
- Работа iOS Safari (PWA через Home Screen).
|
||
- Поведение при смене token.
|
||
- Надёжность `FcmPushSender` (таймауты, логирование ошибок ответа).
|
||
|
||
---
|
||
|
||
## 3) Вторая слева вкладка: Личные сообщения / Чаты
|
||
|
||
## 3.1 Продуктовая логика (как должно быть)
|
||
1. Открытие списка диалогов на вкладке "Личные сообщения".
|
||
2. Кнопка `+` открывает поиск пользователя по префиксу логина (`SearchUsers`).
|
||
3. **Первое сообщение можно отправить любому пользователю**, даже если он не контакт.
|
||
4. Если пользователь не в контактах — в чате показывается действие "Добавить в контакты".
|
||
5. Входящее сообщение может прийти:
|
||
- напрямую по WS (`IncomingDirectMessage`)
|
||
- через FCM (fallback)
|
||
6. На клиенте дедупликация должна быть по `messageId`.
|
||
|
||
## 3.2 Что уже сделано технически
|
||
### Сервер
|
||
- `SendDirectMessage`
|
||
- `AckIncomingMessage`
|
||
- `direct_messages` таблица + DAO
|
||
- доставка по активным WS-сессиям + ожидание ACK + fallback в FCM
|
||
|
||
### Клиент
|
||
- `authService.sendDirectMessage(...)`
|
||
- `authService.ackIncomingMessage(...)`
|
||
- WS client поддерживает server events (`onEvent`)
|
||
- В `app.js` обработка `IncomingDirectMessage`
|
||
- В `state.js` добавлены `incomingDedup`, `addIncomingMessage`
|
||
|
||
## 3.3 Что глючит/что проверить
|
||
- Стабильность отображения новых чатов, если сообщение пришло от неизвестного пользователя.
|
||
- Согласованность списка диалогов и фактических сообщений.
|
||
- Поведение при быстрых дубликатах WS + FCM.
|
||
- Поведение при сетевых обрывах/повторном коннекте.
|
||
|
||
---
|
||
|
||
## 4) Центральная вкладка: Связи / Близкие друзья
|
||
|
||
## 4.1 Целевое поведение
|
||
1. Экран "Связи" загружает граф друзей (`GetUserConnectionsGraph`).
|
||
2. Кнопка "Добавить близкого друга" открывает модалку:
|
||
- поле логина/префикса
|
||
- кнопка "Поиск"
|
||
- кнопка "Назад"
|
||
3. Поиск идёт через `SearchUsers`.
|
||
4. По клику на найденного — подтверждение "Добавить? Да/Нет".
|
||
5. При "Да" вызывается `AddCloseFriend`, после успеха:
|
||
- закрыть модалку
|
||
- вернуться на экран связей
|
||
- обновить граф.
|
||
|
||
## 4.2 Что уже сделано
|
||
- UI-flow модалки реализован на `network-view.js`.
|
||
- API `AddCloseFriend` добавлен на сервере.
|
||
- `ConnectionsStateDAO.upsertRelation(...)` добавлен для upsert связи FRIEND.
|
||
|
||
## 4.3 Что проверить/доделать
|
||
- Валидация edge-cases (добавление самого себя, несуществующий логин).
|
||
- Корректность отрисовки графа после добавления.
|
||
- Согласованность данных с будущей "настоящей" записью в blockchain (сейчас MVP upsert в `connections_state`).
|
||
|
||
---
|
||
|
||
## 5) SessionRevoked и мультисессии
|
||
|
||
## 5.1 Целевое поведение
|
||
Если с другой сессии закрыли текущую сессию:
|
||
1. сервер шлёт событие `SessionRevoked`
|
||
2. клиент чистит локальную авторизацию
|
||
3. клиент возвращается в состояние неавторизованного входа.
|
||
|
||
## 5.2 Что проверить
|
||
- Что событие приходит до закрытия socket.
|
||
- Что UX не "зависает" на промежуточном экране.
|
||
|
||
---
|
||
|
||
## 6) API-операции (быстрый список)
|
||
|
||
### Уже используемые/добавленные в ветке
|
||
- `SearchUsers`
|
||
- `ListContacts`
|
||
- `GetUserConnectionsGraph`
|
||
- `AddCloseFriend`
|
||
- `UpsertPushToken`
|
||
- `SendDirectMessage`
|
||
- `AckIncomingMessage`
|
||
- `CloseActiveSession` (с server event `SessionRevoked`)
|
||
|
||
---
|
||
|
||
## 7) Минимальный чек-лист тестирования для нового исполнителя
|
||
|
||
1. Авторизация пользователя A и B в разных браузерах/устройствах.
|
||
2. A отправляет первое сообщение B (без контактов) — должно уйти.
|
||
3. B получает по WS, отправляется ACK, fallback FCM не должен дублировать.
|
||
4. Выключить WS у B и проверить fallback FCM.
|
||
5. Вкладка "Связи": добавить близкого друга через поиск, проверить обновление графа.
|
||
6. Закрыть сессию B с другого устройства и проверить `SessionRevoked` UX.
|
||
7. Перезапуск клиента: проверка повторной регистрации push-токена только при изменении.
|
||
|
||
---
|
||
|
||
## 8) Важное ограничение текущей реализации
|
||
|
||
Некоторые части реализованы как MVP и требуют стабилизации:
|
||
- местами UI/состояние могут рассинхронизироваться;
|
||
- fallback WS->FCM может требовать донастройки таймингов и ретраев;
|
||
- `AddCloseFriend` сейчас пишет прямое состояние связи (upsert), а не полный blockchain-поток создания блоков.
|
||
|
||
Это ожидаемо для handoff: задача следующего исполнителя — довести до production-стабильности.
|