Files
SHiNE-server/shine-UI/js/pages/arweave-uploads-view.js

174 lines
7.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
clearArweaveAttachmentHistory,
formatArweaveHistoryTime,
getArweaveAttachmentAvailability,
openArweaveAttachmentManager,
readArweaveAttachmentHistory,
} from '../components/arweave-attachment-manager.js';
import { formatBytes } from '../services/attachment-format.js';
import { toUserMessage } from '../services/ui-error-texts.js';
import { state } from '../state.js';
export const pageMeta = { id: 'arweave-uploads-view', title: 'Загрузка файлов' };
function closeUploadsMenu(controls) {
const menu = controls?.querySelector?.('[data-menu="true"]');
if (menu) menu.hidden = true;
}
function setStatusBadge(node, status, label) {
if (!node) return;
node.className = `ar-attachment-status ar-attachment-status--${status || 'pending'}`;
node.textContent = label || 'Проверяем...';
}
function renderTile(item, index) {
const tile = document.createElement('article');
tile.className = `ar-attachment-history-tile ar-attachment-history-tile--page${item?.preview?.ar ? ' ar-attachment-history-tile--with-preview' : ''}`;
const name = document.createElement('strong');
name.className = 'ar-attachment-history-name';
name.textContent = item.name;
const status = document.createElement('span');
status.className = 'ar-attachment-status ar-attachment-status--pending';
status.dataset.statusIndex = String(index);
status.textContent = 'Проверяем...';
const meta = document.createElement('div');
meta.className = 'ar-attachment-history-meta-row';
const size = document.createElement('span');
size.textContent = formatBytes(item.size);
const time = document.createElement('span');
time.textContent = formatArweaveHistoryTime(item.uploadedAtMs);
meta.append(status, size, time);
if (item?.preview?.ar) {
const previewFlag = document.createElement('span');
previewFlag.className = 'ar-attachment-placement-flag';
previewFlag.textContent = 'С превью';
meta.append(previewFlag);
}
if (item.pendingPlacement) {
const flag = document.createElement('span');
flag.className = 'ar-attachment-placement-flag';
flag.textContent = 'Не добавлен в SHiNE';
meta.append(flag);
}
const txId = document.createElement('div');
txId.className = 'mono-cell ar-attachment-history-txid';
txId.textContent = item.ar;
tile.append(name, meta, txId);
return tile;
}
export function render({ navigate }) {
const screen = document.createElement('section');
screen.className = 'stack arweave-uploads-screen';
const controls = document.createElement('div');
controls.className = 'arweave-uploads-toolbar';
controls.innerHTML = `
<button class="secondary-btn arweave-uploads-back" type="button" data-action="back" aria-label="Назад">←</button>
<div class="arweave-uploads-title">Загрузка файлов в блокчейн</div>
<button class="primary-btn arweave-uploads-add" type="button" data-action="upload" aria-label="Добавить файл">+</button>
<button class="secondary-btn arweave-uploads-menu-btn" type="button" data-action="menu" aria-label="Меню">⋮</button>
<div class="arweave-uploads-menu" data-menu="true" hidden>
<button class="text-btn" type="button" data-action="upload-menu">Добавить файл</button>
<button class="text-btn" type="button" data-action="clear">Очистить историю</button>
<button class="text-btn" type="button" data-action="help">Справка</button>
</div>
`;
const statusLine = document.createElement('p');
statusLine.className = 'meta-muted inline-error';
const list = document.createElement('div');
list.className = 'ar-attachment-history-tiles arweave-uploads-list';
const uploadFile = async () => {
statusLine.textContent = '';
closeUploadsMenu(controls);
try {
await openArweaveAttachmentManager({
login: state.session.login,
storagePwd: state.session.storagePwdInMemory,
gateway: state.entrySettings.arweaveServer,
historyOnly: true,
});
renderHistory();
} catch (error) {
statusLine.textContent = toUserMessage(error, 'Не удалось загрузить файл.');
}
};
function renderHistory() {
const rows = readArweaveAttachmentHistory(state.session.login).slice().reverse();
list.innerHTML = '';
statusLine.textContent = '';
if (!rows.length) {
const empty = document.createElement('div');
empty.className = 'card meta-muted';
empty.textContent = 'Загруженные в этой сессии файлы появятся здесь.';
list.append(empty);
return;
}
rows.forEach((item, index) => {
list.append(renderTile(item, index));
const statusEl = list.querySelector(`[data-status-index="${index}"]`);
void getArweaveAttachmentAvailability({
gateway: state.entrySettings.arweaveServer,
attachment: item,
})
.then((result) => setStatusBadge(statusEl, result.status, result.label))
.catch(() => setStatusBadge(statusEl, 'unavailable', 'Недоступен'));
});
window.setTimeout(() => {
list.scrollTop = list.scrollHeight;
}, 0);
}
controls.querySelector('[data-action="upload"]')?.addEventListener('click', () => {
void uploadFile();
});
controls.querySelector('[data-action="upload-menu"]')?.addEventListener('click', () => {
void uploadFile();
});
controls.querySelector('[data-action="back"]')?.addEventListener('click', () => navigate('settings-view'));
controls.querySelector('[data-action="menu"]')?.addEventListener('click', (event) => {
event.stopPropagation();
const menu = controls.querySelector('[data-menu="true"]');
if (menu) menu.hidden = !menu.hidden;
});
controls.querySelector('[data-action="clear"]')?.addEventListener('click', () => {
const menu = controls.querySelector('[data-menu="true"]');
if (menu) menu.hidden = true;
const confirmed = window.confirm('Очистить журнал загруженных файлов этой сессии?');
if (!confirmed) return;
clearArweaveAttachmentHistory(state.session.login);
renderHistory();
});
controls.querySelector('[data-action="help"]')?.addEventListener('click', () => {
const menu = controls.querySelector('[data-menu="true"]');
if (menu) menu.hidden = true;
window.alert(
'Здесь вы можете заранее добавить файл в Arweave или через Turbo. По умолчанию сразу выбрана загрузка через Turbo, а маленькие файлы пока загружаются там бесплатно.\n\n'
+ 'Потом при создании сообщения можно открыть историю загрузок и выбрать уже загруженный файл по txId. '
+ 'Если файл только что загружен, gateway может несколько минут его не отдавать, поэтому статус может быть “ещё обновляется”.'
);
});
screen.addEventListener('click', (event) => {
if (controls.contains(event.target)) return;
closeUploadsMenu(controls);
});
screen.append(controls, statusLine, list);
renderHistory();
return screen;
}