Документация и UI: уточнить формат вложений

This commit is contained in:
AidarKC
2026-07-30 11:14:19 +04:00
parent e9e6628b21
commit f961947e1e
6 changed files with 108 additions and 12 deletions
+2
View File
@@ -41,6 +41,8 @@ TEXT-тип хранит сообщения и редактирования.
Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_EDIT_POST` и `TEXT_EDIT_REPLY` клиент может хранить вложения как технические строки в начале обычного `text`. Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_EDIT_POST` и `TEXT_EDIT_REPLY` клиент может хранить вложения как технические строки в начале обычного `text`.
Подробная спецификация: [15_TEXT_Attachments.md](./15_TEXT_Attachments.md).
Бинарный формат `TextBody` не меняется: вложения являются частью UTF-8 текста. Бинарный формат `TextBody` не меняется: вложения являются частью UTF-8 текста.
Один блок вложения: Один блок вложения:
+84
View File
@@ -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
<SHiNE:attach;v=1;name=report.pdf;size=845221;sha256=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef;ar=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>
```
Несколько вложений идут подряд в самом начале текста:
```text
<SHiNE:attach;v=1;name=photo.jpg;size=248193;sha256=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;ar=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB>
<SHiNE:attach;v=1;name=report.pdf;size=845221;sha256=cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc;ar=DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD>
Текст сообщения
```
После последнего 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 ограничивает максимальный размер такой проверки.
+6
View File
@@ -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 ## 2026-07-30 10:31:26 +0400
- Базовый коммит-ориентир: `c7684d6`. - Базовый коммит-ориентир: `c7684d6`.
- Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_EDIT_POST` и `TEXT_EDIT_REPLY` зафиксирован клиентский формат вложений `SHiNE:attach v=1`. - Для `TEXT_POST`, `TEXT_REPLY`, `TEXT_EDIT_POST` и `TEXT_EDIT_REPLY` зафиксирован клиентский формат вложений `SHiNE:attach v=1`.
+5 -3
View File
@@ -17,11 +17,13 @@
Социальные связи (`msg_type=3`). Социальные связи (`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`). Параметры пользователя (`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`. Типы каналов и формат `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)
Журнал изменений документации. Журнал изменений документации.
## Смежная документация ## Смежная документация
+2 -1
View File
@@ -668,10 +668,11 @@ function renderNodeCard(node, heading, handlers, localNumber) {
body.className = `channel-message-body${isDeletedMessage ? ' channel-message-body--deleted' : ''}`; body.className = `channel-message-body${isDeletedMessage ? ' channel-message-body--deleted' : ''}`;
body.textContent = isDeletedMessage ? 'Сообщение удалено' : parsedText.text; body.textContent = isDeletedMessage ? 'Сообщение удалено' : parsedText.text;
card.append(authorTile, body); card.append(authorTile);
if (!isDeletedMessage && parsedText.attachments.length > 0) { if (!isDeletedMessage && parsedText.attachments.length > 0) {
card.append(createAttachmentListElement(parsedText.attachments, { gateway: state.entrySettings.arweaveServer })); card.append(createAttachmentListElement(parsedText.attachments, { gateway: state.entrySettings.arweaveServer }));
} }
card.append(body);
const target = buildTargetFromNode(node); const target = buildTargetFromNode(node);
const refKey = messageRefKey(target); const refKey = messageRefKey(target);
+2 -1
View File
@@ -1002,10 +1002,11 @@ function renderPostCard(post, {
body.className = `channel-message-body${isDeletedMessage ? ' channel-message-body--deleted' : ''}`; body.className = `channel-message-body${isDeletedMessage ? ' channel-message-body--deleted' : ''}`;
body.textContent = isDeletedMessage ? 'Сообщение удалено' : parsedBody.text; body.textContent = isDeletedMessage ? 'Сообщение удалено' : parsedBody.text;
card.append(authorTile, body); card.append(authorTile);
if (!isDeletedMessage && parsedBody.attachments.length > 0) { if (!isDeletedMessage && parsedBody.attachments.length > 0) {
card.append(createAttachmentListElement(parsedBody.attachments, { gateway: state.entrySettings.arweaveServer })); card.append(createAttachmentListElement(parsedBody.attachments, { gateway: state.entrySettings.arweaveServer }));
} }
card.append(body);
const refKey = messageRefKey(post.messageRef); const refKey = messageRefKey(post.messageRef);
if (refKey) { if (refKey) {