UI: свайпы вкладок и навигация тредов

This commit is contained in:
AidarKC
2026-08-12 19:37:29 +04:00
parent b4b23afc10
commit e8a4713f6e
9 changed files with 770 additions and 26 deletions
+42 -6
View File
@@ -10,7 +10,7 @@ import {
showToast,
softHaptic,
} from '../services/channels-ux.js';
import { navigateBack } from '../router.js';
import { getPreviousTrackedPath, parseRouteFromPath } from '../router.js';
import { renderUserAvatar } from '../components/avatar-image.js';
import { markArweaveAttachmentPlaced, openArweaveAttachmentManager } from '../components/arweave-attachment-manager.js';
import {
@@ -332,6 +332,25 @@ function buildChannelRouteFromThread(selector, resolvedChannelLabel = '') {
});
}
function resolveThreadBackRoute(selector, resolvedChannelLabel = '') {
return buildChannelRouteFromThread(selector, resolvedChannelLabel) || 'channels-list';
}
function resolveThreadPreviousInChannels(selector, resolvedChannelLabel = '') {
const previousPath = String(getPreviousTrackedPath() || '').trim();
if (previousPath) {
const previousRoute = parseRouteFromPath(previousPath);
const previousPageId = String(previousRoute?.pageId || '').trim();
if (
previousPageId === 'channel-thread-view'
|| previousPageId === 'channel-view'
) {
return previousPath;
}
}
return resolveThreadBackRoute(selector, resolvedChannelLabel);
}
function buildTargetFromNode(node) {
const blockchainName = String(node?.authorBlockchainName || '').trim();
const blockNumber = Number(node?.messageRef?.blockNumber);
@@ -1118,6 +1137,7 @@ export function render({ navigate, route, chrome }) {
const selector = parseThreadSelector(route);
const channelDisplayName = resolveChannelDisplayName(selector?.channel);
const routeKey = `${selector?.message?.blockchainName || ''}:${selector?.message?.blockNumber || ''}:${selector?.message?.blockHash || ''}`;
let activeResolvedChannelLabel = channelDisplayName;
const screen = document.createElement('section');
screen.className = 'stack channels-screen channels-screen--thread';
@@ -1126,13 +1146,28 @@ export function render({ navigate, route, chrome }) {
const header = renderHeader({
title: '',
leftAction: { label: '<', onClick: () => navigateBack() },
rightActions: [{ label: 'Тред в канале: ...', onClick: () => {} }],
leftAction: { label: '<', onClick: () => navigate(resolveThreadPreviousInChannels(selector, activeResolvedChannelLabel)) },
rightActions: [],
});
const threadHeaderButton = header.querySelector('.header-actions .icon-btn');
if (threadHeaderButton) {
threadHeaderButton.classList.add('channel-header-route-btn');
header.classList.add('channel-thread-topbar');
const headerLeft = header.querySelector('.header-left');
let threadHeaderButton = null;
if (headerLeft) {
const channelsListButton = document.createElement('button');
channelsListButton.type = 'button';
channelsListButton.className = 'icon-btn';
channelsListButton.textContent = '↑';
channelsListButton.title = 'К списку каналов';
channelsListButton.setAttribute('aria-label', 'К списку каналов');
channelsListButton.addEventListener('click', () => navigate('channels-list'));
headerLeft.append(channelsListButton);
threadHeaderButton = document.createElement('button');
threadHeaderButton.type = 'button';
threadHeaderButton.className = 'icon-btn channel-header-route-btn';
threadHeaderButton.textContent = 'Тред в канале: ...';
threadHeaderButton.disabled = true;
headerLeft.append(threadHeaderButton);
}
chrome?.setTopbar(header);
@@ -1418,6 +1453,7 @@ export function render({ navigate, route, chrome }) {
if (!resolvedChannelLabel && selector?.channel?.ownerBlockchainName && selector?.channel?.channelRootBlockNumber != null) {
resolvedChannelLabel = await resolveChannelDisplayNameFromServer(selector.channel);
}
activeResolvedChannelLabel = resolvedChannelLabel;
const fallbackChannel = String(selector?.channel?.ownerBlockchainName || '').trim() || 'неизвестно';
const resolvedChannelTitle = resolvedChannelLabel || fallbackChannel;
if (threadHeaderButton) {
+1 -2
View File
@@ -16,7 +16,6 @@ import {
showToast,
softHaptic,
} from '../services/channels-ux.js';
import { navigateBack } from '../router.js';
import { renderUserAvatar } from '../components/avatar-image.js';
import { markArweaveAttachmentPlaced, openArweaveAttachmentManager } from '../components/arweave-attachment-manager.js';
import {
@@ -2036,7 +2035,7 @@ export function render({ navigate, route, chrome }) {
const header = renderHeader({
title: '',
leftAction: { label: '<', onClick: () => navigateBack() },
leftAction: { label: '<', onClick: () => navigate('channels-list') },
rightActions: [
{ label: 'Канал: ...', className: 'channel-header-route-btn', onClick: () => {} },
{ label: 'Оглавление', className: 'channel-header-entrypoint-btn', onClick: () => {} },
+2 -3
View File
@@ -26,11 +26,10 @@ function renderList(container) {
container.append(card);
}
export function render() {
export function render({ chrome } = {}) {
const screen = document.createElement('section');
screen.className = 'stack notifications-screen';
screen.append(renderHeader({ title: 'Уведомления' }));
chrome?.setTopbar(renderHeader({ title: 'Уведомления' }));
const tabs = document.createElement('div');
tabs.className = 'tabs';