diff --git a/VERSION.properties b/VERSION.properties
index eb3f5199..9d59f50b 100644
--- a/VERSION.properties
+++ b/VERSION.properties
@@ -1,2 +1,2 @@
-client.version=1.4.6
+client.version=1.4.7
server.version=1.4.0
diff --git a/docs/Blockchain/CHANGELOG.md b/docs/Blockchain/CHANGELOG.md
index b8c45814..7caebd29 100644
--- a/docs/Blockchain/CHANGELOG.md
+++ b/docs/Blockchain/CHANGELOG.md
@@ -1,5 +1,9 @@
# История изменений документации блокчейна
+## 2026-07-31 17:13:26 +0400
+- Базовый коммит-ориентир: `60ab476`.
+- Уточнён UI журнала загрузок Arweave: статус доступности перенесён в начало второй строки плитки, верхняя панель закреплена как fixed-полоса вне прокрутки, в меню добавлен пункт `Добавить файл`, меню закрывается при клике вне него; формат attach-блока не изменён.
+
## 2026-07-31 17:06:55 +0400
- Базовый коммит-ориентир: `bcae285`.
- Уточнён UI журнала загрузок Arweave: плитки принудительно не растягиваются по высоте, а контейнер журнала запрещает горизонтальную прокрутку; формат attach-блока не изменён.
diff --git a/shine-UI/js/pages/arweave-uploads-view.js b/shine-UI/js/pages/arweave-uploads-view.js
index 42b79804..6d5ebb14 100644
--- a/shine-UI/js/pages/arweave-uploads-view.js
+++ b/shine-UI/js/pages/arweave-uploads-view.js
@@ -11,6 +11,11 @@ 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'}`;
@@ -36,7 +41,7 @@ function renderTile(item, index) {
size.textContent = formatBytes(item.size);
const time = document.createElement('span');
time.textContent = formatArweaveHistoryTime(item.uploadedAtMs);
- meta.append(size, time, status);
+ meta.append(status, size, time);
if (item.pendingPlacement) {
const flag = document.createElement('span');
flag.className = 'ar-attachment-placement-flag';
@@ -60,10 +65,11 @@ export function render({ navigate }) {
controls.className = 'arweave-uploads-toolbar';
controls.innerHTML = `
-
Загрузка файлов
+ Загрузка файлов в блокчейн
@@ -75,6 +81,22 @@ export function render({ navigate }) {
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 = '';
@@ -104,23 +126,12 @@ export function render({ navigate }) {
}, 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="upload"]')?.addEventListener('click', uploadFile);
+ controls.querySelector('[data-action="upload-menu"]')?.addEventListener('click', uploadFile);
controls.querySelector('[data-action="back"]')?.addEventListener('click', () => navigate('settings-view'));
- controls.querySelector('[data-action="menu"]')?.addEventListener('click', () => {
+ controls.querySelector('[data-action="menu"]')?.addEventListener('click', (event) => {
+ event.stopPropagation();
const menu = controls.querySelector('[data-menu="true"]');
if (menu) menu.hidden = !menu.hidden;
});
@@ -141,6 +152,10 @@ export function render({ navigate }) {
+ 'Если файл только что загружен, gateway может несколько минут его не отдавать, поэтому статус может быть “ещё обновляется”.'
);
});
+ screen.addEventListener('click', (event) => {
+ if (controls.contains(event.target)) return;
+ closeUploadsMenu(controls);
+ });
screen.append(controls, statusLine, list);
renderHistory();
diff --git a/shine-UI/styles/components.css b/shine-UI/styles/components.css
index 5dc2d700..afb780eb 100644
--- a/shine-UI/styles/components.css
+++ b/shine-UI/styles/components.css
@@ -2597,7 +2597,7 @@ textarea.input {
background: rgba(255, 255, 255, 0.06);
border-radius: 0.34rem;
color: rgba(226, 232, 240, 0.86);
- font-size: 0.46rem;
+ font-size: 0.56rem;
line-height: 1.05;
max-width: 100%;
min-width: 0;
@@ -2647,7 +2647,7 @@ textarea.input {
min-height: 100vh;
max-width: 100%;
overflow-x: hidden;
- padding-top: 0;
+ padding-top: 3.25rem;
}
.arweave-uploads-toolbar {
@@ -2660,9 +2660,11 @@ textarea.input {
gap: 0.42rem;
grid-template-columns: 2.4rem minmax(0, 1fr) 2.4rem 2.4rem;
justify-content: stretch;
- margin: -1rem -1rem 0;
+ left: 0;
+ margin: 0;
padding: max(0.35rem, env(safe-area-inset-top)) 0.45rem 0.45rem;
- position: sticky;
+ position: fixed;
+ right: 0;
top: 0;
z-index: 15;
}
@@ -2683,6 +2685,7 @@ textarea.input {
.arweave-uploads-title {
align-self: center;
color: #f8fafc;
+ font-size: 0.94rem;
font-weight: 800;
min-width: 0;
overflow: hidden;
@@ -2715,8 +2718,8 @@ textarea.input {
}
.arweave-uploads-list {
- max-height: calc(100vh - 4.4rem);
- min-height: calc(100vh - 4.4rem);
+ max-height: calc(100vh - 4.1rem);
+ min-height: calc(100vh - 4.1rem);
width: 100%;
}