UI: карточка автора в канале, профиль user и назад по истории

This commit is contained in:
AidarKC
2026-05-19 13:58:49 +03:00
parent db2d9a666b
commit 90d10086d7
10 changed files with 80 additions and 28 deletions
+2 -13
View File
@@ -11,6 +11,7 @@ import {
softHaptic,
} from '../services/channels-ux.js';
import { openSpeechInputModal } from '../components/speech-input-modal.js';
import { navigateBack } from '../router.js';
export const pageMeta = { id: 'channel-thread-view', title: 'Тред' };
@@ -197,17 +198,6 @@ async function resolveChannelDisplayNameFromServer(channelSelector) {
}
}
function buildBackRoute(selector) {
if (selector?.short?.ownerBlockchainName && selector?.short?.channelName) {
return [
'channel',
encodeRoutePart(selector.short.ownerBlockchainName),
encodeRoutePart(selector.short.channelName),
].join('/');
}
return 'channels-list';
}
function buildThreadRouteFromTarget(target, selector) {
if (!target) return '';
return [
@@ -501,7 +491,6 @@ function renderSkeleton(screen) {
export function render({ navigate, route }) {
const selector = parseThreadSelector(route);
const backRoute = buildBackRoute(selector);
const channelDisplayName = resolveChannelDisplayName(selector?.channel);
const routeKey = `${selector?.message?.blockchainName || ''}:${selector?.message?.blockNumber || ''}:${selector?.message?.blockHash || ''}`;
@@ -624,7 +613,7 @@ export function render({ navigate, route }) {
screen.append(
renderHeader({
title: 'Тред',
leftAction: { label: '<', onClick: () => navigate(backRoute) },
leftAction: { label: '<', onClick: () => navigateBack() },
}),
);
screen.append(channelIndicator, statusBox);
+20 -5
View File
@@ -17,6 +17,7 @@ import {
softHaptic,
} from '../services/channels-ux.js';
import { openSpeechInputModal } from '../components/speech-input-modal.js';
import { navigateBack } from '../router.js';
export const pageMeta = { id: 'channel-view', title: 'Канал' };
const CHANNEL_TYPE_PERSONAL = 100;
@@ -628,8 +629,9 @@ function renderPostCard(post, {
const card = document.createElement('article');
card.className = 'card stack channel-message-card';
const topRow = document.createElement('div');
topRow.className = 'channel-message-top';
const authorTile = document.createElement('button');
authorTile.type = 'button';
authorTile.className = 'channel-message-author-tile';
const avatar = document.createElement('div');
avatar.className = 'channel-message-avatar';
@@ -654,13 +656,19 @@ function renderPostCard(post, {
title.append(loginEl, numberEl);
authorBlock.append(title, timestamp);
topRow.append(avatar, authorBlock);
authorTile.append(avatar, authorBlock);
authorTile.addEventListener('click', (event) => {
event.stopPropagation();
const cleanLogin = String(post.authorLogin || '').trim();
if (!cleanLogin) return;
navigate(`user/${encodeRoutePart(cleanLogin)}/channel-view`);
});
const body = document.createElement('p');
body.className = 'channel-message-body';
body.textContent = post.body;
card.append(topRow, body);
card.append(authorTile, body);
const refKey = messageRefKey(post.messageRef);
if (refKey) {
@@ -688,6 +696,7 @@ function renderPostCard(post, {
`;
likeButton.disabled = isPending;
likeButton.addEventListener('click', async (event) => {
event.stopPropagation();
animatePress(event.currentTarget);
if (isPending) return;
if (!isLiked) {
@@ -710,6 +719,7 @@ function renderPostCard(post, {
<span class="channel-action-counter">${post.repliesCount || 0}</span>
`;
replyButton.addEventListener('click', (event) => {
event.stopPropagation();
animatePress(event.currentTarget);
openReplyModal({
navigate,
@@ -726,6 +736,7 @@ function renderPostCard(post, {
<span class="channel-action-label">Тред</span>
`;
openThreadButton.addEventListener('click', (event) => {
event.stopPropagation();
animatePress(event.currentTarget);
const route = buildThreadRoute(post.messageRef, selector);
if (route) navigate(route);
@@ -747,6 +758,10 @@ function renderPostCard(post, {
actions.append(openThreadButton, shareButton);
card.append(actions);
card.addEventListener('click', () => {
const route = buildThreadRoute(post.messageRef, selector);
if (route) navigate(route);
});
return card;
}
@@ -978,7 +993,7 @@ export function render({ navigate, route }) {
screen.append(
renderHeader({
title: '',
leftAction: { label: '<', onClick: () => navigate('channels-list') },
leftAction: { label: '<', onClick: () => navigateBack() },
}),
);
screen.append(statusBox);
+1 -1
View File
@@ -53,7 +53,7 @@ export function render({ navigate }) {
<div class="meta-muted">Профиль</div>
`;
row.addEventListener('click', () => {
navigate(`user-profile-view/${encodeURIComponent(login)}/contact-search-view`);
navigate(`user/${encodeURIComponent(login)}/contact-search-view`);
});
resultsList.append(row);
});
+1 -1
View File
@@ -533,7 +533,7 @@ export function render({ navigate, route }) {
const cleanLogin = normalizeLogin(login);
if (!cleanLogin) return '';
if (normKey(cleanLogin) === normKey(state.session.login)) return 'profile-view';
return `user-profile-view/${encodeURIComponent(cleanLogin)}/${encodeURIComponent('network-view/keep-history')}`;
return `user/${encodeURIComponent(cleanLogin)}/${encodeURIComponent('network-view/keep-history')}`;
}
function helpText() {
+4 -3
View File
@@ -7,7 +7,9 @@ import {
} from '../services/user-connections.js';
import { renderUserAvatar } from '../components/avatar-image.js';
export const pageMeta = { id: 'user-profile-view', title: 'Чужой профиль' };
import { navigateBack } from '../router.js';
export const pageMeta = { id: 'user', title: 'Чужой профиль' };
function escapeHtml(text) {
return String(text || '')
@@ -147,7 +149,6 @@ function renderReadOnlyParams(card) {
export function render({ navigate, route }) {
const requestedLogin = String(route.params.login || '').trim();
const fromPage = String(route.params.fromPage || 'messages-list').trim() || 'messages-list';
const sessionLogin = String(state.session.login || '').trim();
const screen = document.createElement('section');
@@ -163,7 +164,7 @@ export function render({ navigate, route }) {
screen.append(
renderHeader({
title: 'Профиль пользователя',
leftAction: { label: '←', onClick: () => navigate(fromPage) },
leftAction: { label: '←', onClick: () => navigateBack() },
rightActions: [{ label: 'Обновить', onClick: () => refresh() }],
}),
status,