diff --git a/docs/Blockchain/11_TEXT_Blocks.md b/docs/Blockchain/11_TEXT_Blocks.md index 17d86fe8..564451cd 100644 --- a/docs/Blockchain/11_TEXT_Blocks.md +++ b/docs/Blockchain/11_TEXT_Blocks.md @@ -41,6 +41,8 @@ TEXT-тип хранит сообщения и редактирования. Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_EDIT_POST` и `TEXT_EDIT_REPLY` клиент может хранить вложения как технические строки в начале обычного `text`. +Подробная спецификация: [15_TEXT_Attachments.md](./15_TEXT_Attachments.md). + Бинарный формат `TextBody` не меняется: вложения являются частью UTF-8 текста. Один блок вложения: diff --git a/docs/Blockchain/15_TEXT_Attachments.md b/docs/Blockchain/15_TEXT_Attachments.md new file mode 100644 index 00000000..526e6d82 --- /dev/null +++ b/docs/Blockchain/15_TEXT_Attachments.md @@ -0,0 +1,84 @@ +# Вложения в TEXT-сообщениях (`SHiNE:attach v=1`) + +Документ фиксирует текущий формат вложений в текстовых блоках SHiNE. + +## Область применения + +Формат применяется к UTF-8 полю `text` в TEXT-блоках: + +- `TEXT_POST` +- `TEXT_REPLY` +- `TEXT_EDIT_POST` +- `TEXT_EDIT_REPLY` + +Бинарный формат `TextBody` не меняется. Вложения являются техническим префиксом внутри обычного текста. + +## Общий вид + +Один attach-блок: + +```text + +``` + +Несколько вложений идут подряд в самом начале текста: + +```text + + +Текст сообщения +``` + +После последнего attach-блока идёт обычный пользовательский текст. Пользовательский текст может быть пустым, если есть хотя бы одно валидное вложение. + +## Поля + +Обязательные поля: + +- `v=1` - версия формата attach-блока; +- `name` - имя файла, закодированное через `encodeURIComponent`; +- `size` - размер файла в байтах; +- `sha256` - SHA-256 исходного файла в hex, 64 символа; +- `ar` - короткий Arweave Transaction ID, 43 символа, без gateway URL. + +## Хранение файла + +Файл хранится вне блокчейна в Arweave. В блокчейне хранится только метаинформация, достаточная для отображения и проверки: + +- имя файла; +- размер; +- SHA-256; +- Arweave `txId`. + +## Создание вложения в UI + +UI поддерживает три сценария: + +- загрузить новый файл в Arweave выбранным Arweave-кошельком; +- ввести существующий `txId`, скачать файл через Arweave gateway и локально посчитать `size/sha256`; +- выбрать файл из журнала файлов, загруженных в текущей браузерной сессии. + +Журнал хранится только в `sessionStorage` текущего браузера и не является частью блокчейна. + +## Отображение + +Новый клиент при чтении сообщения: + +1. читает валидные attach-блоки только из начала текста; +2. скрывает технические attach-строки; +3. отображает вложения над пользовательским текстом; +4. каждое вложение показывает как карточку/ссылку на Arweave gateway; +5. если attach-блок битый, игнорирует только этот блок и продолжает отображать сообщение. + +Старые клиенты без поддержки формата могут показывать attach-блоки как обычный текст. + +## Редактирование + +При редактировании сообщения UI сохраняет существующие attach-блоки и меняет только пользовательский текст. Удаление сообщения по-прежнему выполняется через edit-блок с пустым текстом, как описано в `11_TEXT_Blocks.md`. + +## Ограничения v1 + +- `ar` допускает только короткий Arweave `txId`, полный URL не используется; +- превью типа image/video/audio не входит в формат v1; +- MIME type, width, height, duration и thumbnail не записываются в блокчейн; +- проверка существующего `txId` скачивает файл локально через gateway, поэтому UI ограничивает максимальный размер такой проверки. diff --git a/docs/Blockchain/CHANGELOG.md b/docs/Blockchain/CHANGELOG.md index f68a0e20..cdd13b60 100644 --- a/docs/Blockchain/CHANGELOG.md +++ b/docs/Blockchain/CHANGELOG.md @@ -1,5 +1,11 @@ # История изменений документации блокчейна +## 2026-07-30 11:12:47 +0400 +- Базовый коммит-ориентир: `e9e6628`. +- Добавлен отдельный документ `docs/Blockchain/15_TEXT_Attachments.md` с полной спецификацией `SHiNE:attach v=1`. +- В `docs/Blockchain/README.md` добавлена ссылка на документ вложений. +- В UI порядок отображения сообщения с вложениями закреплён как: вложения сверху, пользовательский текст снизу. + ## 2026-07-30 10:31:26 +0400 - Базовый коммит-ориентир: `c7684d6`. - Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_EDIT_POST` и `TEXT_EDIT_REPLY` зафиксирован клиентский формат вложений `SHiNE:attach v=1`. diff --git a/docs/Blockchain/README.md b/docs/Blockchain/README.md index 302df73f..3e4ef7de 100644 --- a/docs/Blockchain/README.md +++ b/docs/Blockchain/README.md @@ -3,25 +3,27 @@ Этот каталог описывает только текущий рабочий формат протокола для MVP. ## Основные документы -1. [01_Common_Block_Format.md](./01_Common_Block_Format.md) +1. [01_Common_Block_Format.md](./01_Common_Block_Format.md) Единый бинарный формат блока (Frame v0), подпись, базовые проверки. -2. [02_Blockchain_Kinds_and_Lines.md](./02_Blockchain_Kinds_and_Lines.md) +2. [02_Blockchain_Kinds_and_Lines.md](./02_Blockchain_Kinds_and_Lines.md) Виды цепочек и правила line-полей. -3. [10_TECH_Blocks.md](./10_TECH_Blocks.md) +3. [10_TECH_Blocks.md](./10_TECH_Blocks.md) Системные блоки (`msg_type=0`). -4. [11_TEXT_Blocks.md](./11_TEXT_Blocks.md) +4. [11_TEXT_Blocks.md](./11_TEXT_Blocks.md) Текстовые блоки (`msg_type=1`). -5. [12_REACTION_Blocks.md](./12_REACTION_Blocks.md) +5. [12_REACTION_Blocks.md](./12_REACTION_Blocks.md) Реакции (`msg_type=2`). -6. [13_CONNECTION_Blocks.md](./13_CONNECTION_Blocks.md) +6. [13_CONNECTION_Blocks.md](./13_CONNECTION_Blocks.md) Социальные связи (`msg_type=3`). -7. [14_USER_PARAM_Blocks.md](./14_USER_PARAM_Blocks.md) +7. [14_USER_PARAM_Blocks.md](./14_USER_PARAM_Blocks.md) Параметры пользователя (`msg_type=4`). -8. [01_Channel_Types_and_CreateChannel.md](./01_Channel_Types_and_CreateChannel.md) +8. [15_TEXT_Attachments.md](./15_TEXT_Attachments.md) + Вложения в TEXT-сообщениях через `SHiNE:attach v=1`. +9. [01_Channel_Types_and_CreateChannel.md](./01_Channel_Types_and_CreateChannel.md) Типы каналов и формат `CreateChannelBody`. -9. [02_Channel_Commands.md](./02_Channel_Commands.md) +10. [02_Channel_Commands.md](./02_Channel_Commands.md) Команды в текстовых сообщениях каналов. -10. [CHANGELOG.md](./CHANGELOG.md) +11. [CHANGELOG.md](./CHANGELOG.md) Журнал изменений документации. ## Смежная документация diff --git a/shine-UI/js/pages/channel-thread-view.js b/shine-UI/js/pages/channel-thread-view.js index 8ffa4a82..f6f0885b 100644 --- a/shine-UI/js/pages/channel-thread-view.js +++ b/shine-UI/js/pages/channel-thread-view.js @@ -668,10 +668,11 @@ function renderNodeCard(node, heading, handlers, localNumber) { body.className = `channel-message-body${isDeletedMessage ? ' channel-message-body--deleted' : ''}`; body.textContent = isDeletedMessage ? 'Сообщение удалено' : parsedText.text; - card.append(authorTile, body); + card.append(authorTile); if (!isDeletedMessage && parsedText.attachments.length > 0) { card.append(createAttachmentListElement(parsedText.attachments, { gateway: state.entrySettings.arweaveServer })); } + card.append(body); const target = buildTargetFromNode(node); const refKey = messageRefKey(target); diff --git a/shine-UI/js/pages/channel-view.js b/shine-UI/js/pages/channel-view.js index 78107dee..47e93c0a 100644 --- a/shine-UI/js/pages/channel-view.js +++ b/shine-UI/js/pages/channel-view.js @@ -1002,10 +1002,11 @@ function renderPostCard(post, { body.className = `channel-message-body${isDeletedMessage ? ' channel-message-body--deleted' : ''}`; body.textContent = isDeletedMessage ? 'Сообщение удалено' : parsedBody.text; - card.append(authorTile, body); + card.append(authorTile); if (!isDeletedMessage && parsedBody.attachments.length > 0) { card.append(createAttachmentListElement(parsedBody.attachments, { gateway: state.entrySettings.arweaveServer })); } + card.append(body); const refKey = messageRefKey(post.messageRef); if (refKey) {