feat(social): add friends, private chats, inbox and music sharing
ci / module boundaries / boundaries (push) Successful in 7s
ci / api / api (push) Successful in 1m9s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m8s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m23s
ci / db / db (push) Successful in 2m29s
ci / ts / ts (packages + web) (push) Successful in 2m55s
ci / module boundaries / boundaries (push) Successful in 7s
ci / api / api (push) Successful in 1m9s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m8s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m23s
ci / db / db (push) Successful in 2m29s
ci / ts / ts (packages + web) (push) Successful in 2m55s
This commit is contained in:
1 parent
f1528de948
commit
0a05bfe2cd
43 files changed
+2828
-389
No files matched your search
@@ -0,0 +1,58 @@
|
||||
# Друзья, сообщения и уведомления
|
||||
|
||||
Социальные функции работают между пользователями одного сервера. В web и desktop
|
||||
открывается раздел «Друзья и общение», на Android — вкладка «Друзья».
|
||||
|
||||
## Поведение
|
||||
|
||||
- Поиск по логину и отображаемому имени начинается с двух символов, возвращает до 30 человек.
|
||||
Пароли, роли, настройки и другие приватные поля в результат не попадают.
|
||||
- Заявка требует явного принятия получателем. Встречная заявка не принимает дружбу автоматически.
|
||||
Можно отменить свою заявку, отклонить входящую или удалить друга.
|
||||
- Личные сообщения и отправка музыки доступны только текущим друзьям. Блокировка прекращает
|
||||
дружбу и закрывает общение в обоих направлениях. Разблокировка дружбу не восстанавливает.
|
||||
- История сохраняется после удаления друга, но доступна снова только после новой взаимной дружбы.
|
||||
В первой странице чата — последние 50 сообщений; ранние подгружаются отдельно.
|
||||
- В сообщении до 4000 символов. Музыкальное вложение — ID трека либо действующая ссылка
|
||||
общего доступа к плейлисту. Отзыв ссылки делает вложенный плейлист недоступным.
|
||||
- «Поделиться» открывает выбор: скопировать ссылку, вызвать системную отправку (когда она
|
||||
поддерживается клиентом) или отправить конкретному другу одним нажатием. Отправка другу
|
||||
создаёт сообщение с музыкальным вложением. Повтор после сетевого сбоя использует тот же UUID.
|
||||
|
||||
## Спокойные уведомления
|
||||
|
||||
Четыре типа: входящая заявка, принятие заявки, личное сообщение, музыка.
|
||||
Центр событий и счётчики сохраняются на сервере, отметки прочтения общие для устройств.
|
||||
Нет звуков, автоматических всплывающих окон и запроса разрешений ОС.
|
||||
|
||||
Список уведомлений возвращает до 100 событий, сначала непрочитанные. По мере подтверждения
|
||||
новых становятся доступны более старые непрочитанные события. Открытый видимый чат подтверждает
|
||||
сообщения только до последнего полученного номера; более поздние сообщения не теряются.
|
||||
В скрытой вкладке и в фоне Android автоматического подтверждения нет.
|
||||
|
||||
Сейчас это уведомления **внутри работающего приложения**, с обновлением центра каждые 15 секунд
|
||||
и открытого чата каждые 8 секунд. Web использует стандартную приостановку фонового polling
|
||||
React Query; Android останавливает polling при уходе приложения в фон. Уведомления ОС при
|
||||
закрытом клиенте (Web Push/FCM/нативный desktop) в эту реализацию не входят.
|
||||
|
||||
## Реализация и проверки
|
||||
|
||||
Контракт: `api/openapi.yaml`, операции `getSocial`, `searchPeople`, `socialAction`,
|
||||
`getDirectMessages`, `sendDirectMessage`. Модуль API: `internal/social`.
|
||||
Миграция `00019_social.sql` создаёт дружбу, блокировки, сообщения и уведомления.
|
||||
Миграции применяются штатным запуском API.
|
||||
|
||||
Мутации пары сериализованы транзакционной advisory-блокировкой PostgreSQL. Отправка сообщения
|
||||
и создание уведомления атомарны. UUID сообщения глобально уникален; повтор с другим содержимым
|
||||
возвращает конфликт. Чужое уведомление нельзя отметить прочитанным. Поиск скрывает заблокированные
|
||||
аккаунты и личные блокировки, включая обратное направление.
|
||||
|
||||
Ограничения: до 50 исходящих ожидающих заявок, до 10 новых заявок за минуту,
|
||||
до 30 сообщений одному человеку за минуту; тело социального POST ограничено 32 KiB.
|
||||
Тексты выводятся обычным текстом, вложения формируют только внутренние маршруты каталога.
|
||||
|
||||
Проверки: `go test ./internal/social`,
|
||||
`TEST_DATABASE_URL=… go test -tags integration ./internal/social`,
|
||||
`pnpm --filter @pipu/web test src/App.test.tsx -t 'social|playlist sharing'`,
|
||||
`pnpm --filter @pipu/web test:e2e e2e/social.spec.ts e2e/playlists.spec.ts`.
|
||||
Интеграционный сценарий включён в `ci-db`.
|
||||
Reference in new issue
Block a user