Добавить Turbo-загрузку и превью для вложений

This commit is contained in:
AidarKC
2026-08-04 19:09:54 +04:00
parent 391b18a5ac
commit 75b75fd223
13 changed files with 1445 additions and 690 deletions
+32 -4
View File
@@ -32,15 +32,31 @@ function normalizeName(name) {
return clean || 'file';
}
function normalizePreview(input = {}) {
const previewTxId = String(input.previewAr || input.ar || input.txId || '').trim();
const previewSha256Hex = String(input.previewSha256 || input.sha256 || input.sha256Hex || '').trim().toLowerCase();
if (!previewTxId || !previewSha256Hex) return null;
if (!validateArweaveTxId(previewTxId)) return null;
if (!validateSha256Hex(previewSha256Hex)) return null;
return {
ar: previewTxId,
sha256: previewSha256Hex,
};
}
export function normalizeAttachment(input = {}) {
const txId = String(input.ar || input.txId || '').trim();
const sha256Hex = String(input.sha256 || input.sha256Hex || '').trim().toLowerCase();
const size = Number(input.size || input.sizeBytes || 0);
const name = normalizeName(input.name || input.fileName || 'file');
const preview = normalizePreview(input.preview || {
previewAr: input.previewAr,
previewSha256: input.previewSha256,
});
if (!validateArweaveTxId(txId)) throw new Error('Некорректный Transaction ID Arweave.');
if (!validateSha256Hex(sha256Hex)) throw new Error('Некорректный SHA-256 файла.');
if (!Number.isInteger(size) || size <= 0) throw new Error('Некорректный размер файла.');
return {
const out = {
v: 1,
name,
size,
@@ -48,12 +64,20 @@ export function normalizeAttachment(input = {}) {
ar: txId,
uploadedAtMs: Number(input.uploadedAtMs || 0) || Date.now(),
};
if (preview) {
out.v = 2;
out.preview = preview;
}
return out;
}
export function buildAttachmentBlock(attachment) {
const item = normalizeAttachment(attachment);
const encodedName = encodeURIComponent(item.name);
return `<SHiNE:attach;v=1;name=${encodedName};size=${item.size};sha256=${item.sha256};ar=${item.ar}>`;
const previewFields = item.preview
? `;previewAr=${item.preview.ar};previewSha256=${item.preview.sha256}`
: '';
return `<SHiNE:attach;v=${item.preview ? 2 : 1};name=${encodedName};size=${item.size};sha256=${item.sha256};ar=${item.ar}${previewFields}>`;
}
export function composeMessageWithAttachments(text, attachments = []) {
@@ -91,6 +115,8 @@ export function parseMessageAttachments(rawText) {
size: fields.size,
sha256: fields.sha256,
ar: fields.ar,
previewAr: fields.previewAr,
previewSha256: fields.previewSha256,
}));
} catch {
// Битый attach-блок скрываем из UI, но не ломаем отображение текста.
@@ -236,7 +262,7 @@ function createFileCard({ item, url, messageTimestampMs, slide }) {
return card;
}
function createMediaSlide({ item, url, kind, messageTimestampMs, slide }) {
function createMediaSlide({ item, url, kind, messageTimestampMs, slide, previewUrl = '' }) {
const frame = document.createElement('div');
frame.className = `message-attachment-media-frame message-attachment-media-frame--${kind}`;
frame.role = 'button';
@@ -264,6 +290,7 @@ function createMediaSlide({ item, url, kind, messageTimestampMs, slide }) {
const video = document.createElement('video');
video.className = 'message-attachment-media';
video.src = url;
if (previewUrl) video.poster = previewUrl;
video.preload = 'metadata';
video.muted = true;
video.playsInline = true;
@@ -320,11 +347,12 @@ export function createAttachmentCarouselElement(attachments = [], { gateway = ''
const item = items[index];
const kind = getAttachmentKind(item);
const url = buildArweaveDataUrl({ gateway, txId: item.ar });
const previewUrl = item.preview?.ar ? buildArweaveDataUrl({ gateway, txId: item.preview.ar }) : '';
slide.dataset.unavailable = '0';
slide.replaceChildren();
slide.append(kind === 'file'
? createFileCard({ item, url, messageTimestampMs, slide })
: createMediaSlide({ item, url, kind, messageTimestampMs, slide }));
: createMediaSlide({ item, url, kind, messageTimestampMs, slide, previewUrl }));
prev.hidden = items.length <= 1 || index <= 0;
next.hidden = items.length <= 1 || index >= items.length - 1;
counter.textContent = `${index + 1} из ${items.length}`;