SHiNE-server/TASKS/CHAT_PWA_HANDOFF.md

9.7 KiB
Raw Blame History

Анонс для исполнителя (кратко)

Ниже описан текущий статус ветки по функциям:

  • 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-стабильности.