SHA256
149 lines
6.3 KiB
JavaScript
149 lines
6.3 KiB
JavaScript
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 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';
|
|
|
|
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(size, time, status);
|
|
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="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';
|
|
|
|
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', async () => {
|
|
statusLine.textContent = '';
|
|
try {
|
|
await openArweaveAttachmentManager({
|
|
login: state.session.login,
|
|
storagePwd: state.session.storagePwdInMemory,
|
|
gateway: state.entrySettings.arweaveServer,
|
|
historyOnly: true,
|
|
});
|
|
renderHistory();
|
|
} catch (error) {
|
|
statusLine.textContent = toUserMessage(error, 'Не удалось загрузить файл.');
|
|
}
|
|
});
|
|
|
|
controls.querySelector('[data-action="back"]')?.addEventListener('click', () => navigate('settings-view'));
|
|
controls.querySelector('[data-action="menu"]')?.addEventListener('click', () => {
|
|
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. Файл загрузится в блокчейн-хранилище и сохранится в журнале только этой браузерной сессии.\n\n'
|
|
+ 'Потом при создании сообщения можно открыть историю загрузок и выбрать уже загруженный файл по txId. '
|
|
+ 'Если файл только что загружен, gateway может несколько минут его не отдавать, поэтому статус может быть “ещё обновляется”.'
|
|
);
|
|
});
|
|
|
|
screen.append(controls, statusLine, list);
|
|
renderHistory();
|
|
return screen;
|
|
}
|