SHiNE-server/TASKS/01-07.04.26-каналы-api/01-ТЗ-каналы.md
AidarKC 0c7d8fac02 07-04-2026
Сделал вкладку параметры пользователя РАБОТАЮЩЕЙ

Добавил
- Локальный запуск
- техническое задание 1 (доработать ui что бы RFYFKS работали)
2026-04-07 14:43:08 +03:00

8.6 KiB
Raw Blame History

Задача 01: Доработка вкладки «Каналы» (UI + API)

Кратко и по делу

Нужно довести вторую вкладку «Каналы» до полностью рабочего состояния на реальных данных сервера.

Что должно работать:

  • список каналов;
  • вход в канал и чтение сообщений;
  • вход в тред сообщения (история/ветка);
  • ответ на сообщение;
  • лайк/снятие лайка;
  • подписка на пользователя;
  • подписка на канал;
  • видимое имя канала в формате имя_пользователя/имя_канала.

Запись любых новых сущностей делается через AddBlock с подписью на клиенте. Чтение делается через 3 API:

  • ListSubscriptionsFeed
  • GetChannelMessages
  • GetMessageThread

Техническая особенность (оставляем как есть):

  • на экране каналов индикатор непрочитанного = общее число сообщений канала.

Подробное ТЗ

1. Цель

Сделать рабочий каналовый сценарий «от списка до треда», где чтение строится на RPC API, а запись действий пользователя — только через AddBlock.

2. Что уже есть в проекте

2.1 UI (частично)

  • Есть страницы:
    • channels-list
    • channel-view
    • add-channel-view
  • Есть запросы чтения в клиенте:
    • authService.listSubscriptionsFeed(...)
    • authService.getChannelMessages(...)
    • authService.getMessageThread(...)
  • Есть fallback на mock-данные при ошибках сервера.

2.2 API/сервер (уже реализованы)

  • ListSubscriptionsFeed
  • GetChannelMessages
  • GetMessageThread
  • AddBlock

2.3 Тесты

  • Есть интеграционный тест API каналов: IT_06_ChannelsApi.
  • Есть тесты генерации блоков каналов/связей: IT_03_AddBlock_NoAuth.
  • Формат AddBlock и его сборка/подпись описаны в AddBlockSender.

3. Проблемы текущей реализации (что надо закрыть)

  • Кнопки «подписаться на человека/канал» в списке каналов сейчас UI-only (модалка без реальной записи через AddBlock).
  • add-channel-view пока не создает канал на сервере через AddBlock (CreateChannelBody), только делает navigate.
  • channel-view добавляет пост локально (в память), а не отправляет блок TEXT_POST через AddBlock.
  • Нет полноценного экрана треда сообщения с реальными GetMessageThread и действиями ответить/лайк/убрать лайк через блоки.
  • Нет гарантированного отображения канала в требуемом формате ownerLogin/channelName.

4. Функциональные требования

4.1 Список каналов

На вкладке «Каналы» отображать 3 группы:

  • Мои каналы
  • Каналы пользователей, на кого я подписан
  • Каналы, на которые я подписан

Источник данных: ListSubscriptionsFeed.

Каждый канал показывать в формате:

  • ownerLogin/channelName

4.2 Открытие канала

При входе в канал:

  • загрузить сообщения через GetChannelMessages;
  • показать список сообщений в хронологическом порядке (по текущему параметру sort);
  • оставить техническую особенность непрочитанных как есть.

4.3 Открытие треда сообщения

При клике на сообщение:

  • загрузить тред через GetMessageThread;
  • показать ancestors, focus, descendants;
  • из треда должны быть доступны действия:
    • «Ответить»
    • «Лайк»
    • «Убрать лайк»

Запись действий — только AddBlock.

4.4 Создание канала

В add-channel-view кнопка «Создать» должна:

  • отправлять AddBlock с телом CreateChannelBody;
  • после успеха возвращать к списку каналов и обновлять его.

4.5 Подписки

  • Подписка на пользователя: AddBlock с ConnectionBody подтип CONNECTION_FOLLOW, target = HEADER пользователя.
  • Подписка на канал: AddBlock с ConnectionBody подтип CONNECTION_FOLLOW, target = root блока канала (CreateChannelBody или HEADER для канала 0).

5. API (форматы)

5.1 ListSubscriptionsFeed (чтение)

Request:

{
  "op": "ListSubscriptionsFeed",
  "requestId": "...",
  "payload": {
    "login": "A1",
    "limit": 200
  }
}

Response (смысловые поля):

  • ownedChannels[]
  • followedUsersChannels[]
  • followedChannels[]

5.2 GetChannelMessages (чтение)

Request:

{
  "op": "GetChannelMessages",
  "requestId": "...",
  "payload": {
    "channel": {
      "ownerBlockchainName": "A1-001",
      "channelRootBlockNumber": 0,
      "channelRootBlockHash": ""
    },
    "limit": 200,
    "sort": "asc"
  }
}

Response (смысловые поля):

  • channel
  • messages[]

5.3 GetMessageThread (чтение)

Request:

{
  "op": "GetMessageThread",
  "requestId": "...",
  "payload": {
    "message": {
      "blockchainName": "A1-001",
      "blockNumber": 15,
      "blockHash": "..."
    },
    "depthUp": 20,
    "depthDown": 2,
    "limitChildrenPerNode": 50
  }
}

Response (смысловые поля):

  • ancestors[]
  • focus
  • descendants[]

5.4 AddBlock (запись)

Любое изменение (создать канал, пост, reply, реакция, подписка) записывается через:

{
  "op": "AddBlock",
  "requestId": "...",
  "payload": {
    "blockchainName": "A1-001",
    "blockNumber": 6,
    "prevBlockHash": "<64-hex>",
    "blockBytesB64": "<base64 full block>"
  }
}

Важно:

  • blockBytesB64 формируется на клиенте.
  • Подпись блока формируется на клиенте приватным blockchain key пользователя.
  • Перед добавлением блока клиент берет актуальный курсор цепочки с сервера.

6. Типы блоков для каналов и связей (через AddBlock)

  • Создание канала: CreateChannelBody
  • Пост/ответ: TextBody (TEXT_POST, TEXT_REPLY)
  • Реакции: ReactionBody (лайк/снятие лайка)
  • Подписки: ConnectionBody (CONNECTION_FOLLOW)

7. Критерии приемки

  • Список каналов отображается с реальными данными API.
  • Формат названия канала в UI: ownerLogin/channelName.
  • Создание канала реально пишет блок и канал появляется после обновления.
  • Отправка поста/ответа/реакций реально пишет блок и видна после перечитки API.
  • Подписка на пользователя/канал реально пишет блок и отражается в выдаче.
  • Переход в тред сообщения показывает реальные ancestors/focus/descendants.
  • Непрочитанные в списке каналов = общее число сообщений (временное правило).

8. Локальный запуск (уже сделано)

Команда:

./gradlew startLocal

Что делает:

  • чистит логи;
  • билдит сервер;
  • запускает локальный WS сервер;
  • запускает локальный HTTP сервер клиента;
  • открывает браузер по URL с параметром localWsPort.