SHA256
Добавить Turbo-загрузку и превью для вложений
This commit is contained in:
@@ -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}`;
|
||||
|
||||
Reference in New Issue
Block a user