SHA256
Добавить состояние чтения каналов
This commit is contained in:
@@ -13,32 +13,93 @@ function parseAvatar(raw) {
|
||||
}
|
||||
|
||||
const TITLES = {
|
||||
friends: 'Друзья', close_friends: 'Близкие друзья', primary_received: 'Подтвердили аккаунт',
|
||||
friends: 'Друзья', close_friends: 'Друзья', primary_received: 'Подтвердили аккаунт',
|
||||
primary_given: 'Подтверждённые аккаунты', shine_received: 'Подтвердили сияние', shine_given: 'Подтверждённые сияющие',
|
||||
channels_owned: 'Каналы', channels_following: 'Подписки на каналы',
|
||||
};
|
||||
|
||||
export function render({navigate, route, chrome}) {
|
||||
const login = String(route?.params?.login || '').trim();
|
||||
const kind = String(route?.params?.kind || '').trim();
|
||||
const screen = document.createElement('section'); screen.className = 'stack';
|
||||
const body = document.createElement('div'); body.className = 'stack';
|
||||
const status = document.createElement('div'); status.className = 'status-line'; status.textContent = 'Загрузка...';
|
||||
chrome?.setTopbar(createTopBar({ title: TITLES[kind] || 'Список', back: { label: '←', onClick: () => navigateBack() } }));
|
||||
screen.append(
|
||||
status,
|
||||
body,
|
||||
);
|
||||
function friendTabsHtml(activeKind) {
|
||||
return `
|
||||
<div class="profile-list-tabs" role="tablist" aria-label="Тип друзей">
|
||||
<button type="button" class="profile-list-tab${activeKind === 'friends' ? ' is-active' : ''}" data-friend-kind="friends" role="tab" aria-selected="${activeKind === 'friends'}">Друзья</button>
|
||||
<button type="button" class="profile-list-tab${activeKind === 'close_friends' ? ' is-active' : ''}" data-friend-kind="close_friends" role="tab" aria-selected="${activeKind === 'close_friends'}">Близкие друзья</button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
export function render({ navigate, route, chrome }) {
|
||||
const login = String(route?.params?.login || '').trim();
|
||||
const initialKind = String(route?.params?.kind || '').trim();
|
||||
let activeKind = initialKind;
|
||||
const isFriendsScreen = initialKind === 'friends' || initialKind === 'close_friends';
|
||||
|
||||
const screen = document.createElement('section');
|
||||
screen.className = 'stack';
|
||||
const body = document.createElement('div');
|
||||
body.className = 'stack';
|
||||
const status = document.createElement('div');
|
||||
status.className = 'status-line';
|
||||
status.textContent = 'Загрузка...';
|
||||
|
||||
chrome?.setTopbar(createTopBar({
|
||||
title: TITLES[initialKind] || 'Список',
|
||||
back: { label: '←', onClick: () => navigateBack() },
|
||||
}));
|
||||
|
||||
if (isFriendsScreen) {
|
||||
const tabs = document.createElement('div');
|
||||
tabs.innerHTML = friendTabsHtml(activeKind);
|
||||
screen.append(tabs.firstElementChild);
|
||||
}
|
||||
screen.append(status, body);
|
||||
|
||||
let loadGeneration = 0;
|
||||
|
||||
function renderRelationRows(rows) {
|
||||
rows.forEach((row) => {
|
||||
const el = document.createElement('button');
|
||||
el.type = 'button';
|
||||
el.className = 'ui-button card row profile-list-row';
|
||||
el.append(renderUserAvatar({
|
||||
login: row.login,
|
||||
firstName: row.firstName,
|
||||
lastName: row.lastName,
|
||||
avatar: parseAvatar(row.avatarAr),
|
||||
size: 'md',
|
||||
}));
|
||||
const fullName = userDisplayName(row);
|
||||
const t = document.createElement('div');
|
||||
t.className = 'profile-list-row-text';
|
||||
const marks = [
|
||||
row.relationType && row.relationType !== 'none' ? ({ contact: 'контакт', friend: 'друг', close_friend: 'близкий друг' }[row.relationType] || row.relationType) : '',
|
||||
row.accountRole === 'primary' ? 'основной' : row.accountRole === 'non_voting' ? 'голос не учитывается' : '',
|
||||
row.shineStatus === 'shining' ? 'сияющий' : row.shineStatus === 'not_interested' ? 'сияние неинтересно' : '',
|
||||
row.primaryConfirmed ? 'основной подтверждён ✓' : '',
|
||||
row.shineConfirmed ? 'сияющий подтверждён ✓' : '',
|
||||
].filter(Boolean).join(' · ');
|
||||
t.innerHTML = `<b>${fullName}</b><small>@${String(row.login || '')}${marks ? ` · ${marks}` : ''}</small>`;
|
||||
el.append(t);
|
||||
el.addEventListener('click', () => navigate(`SHiNE/${encodeURIComponent(row.login)}`));
|
||||
body.append(el);
|
||||
});
|
||||
}
|
||||
|
||||
async function load(kind) {
|
||||
const generation = ++loadGeneration;
|
||||
status.className = 'status-line';
|
||||
status.textContent = 'Загрузка...';
|
||||
body.replaceChildren();
|
||||
try {
|
||||
if (kind === 'channels_owned' || kind === 'channels_following') {
|
||||
const payload = await authService.listUserProfileChannels(login, kind === 'channels_owned' ? 'owned' : 'following', 200, 0);
|
||||
if (generation !== loadGeneration) return;
|
||||
const rows = Array.isArray(payload?.channels) ? payload.channels : [];
|
||||
rows.forEach((row) => {
|
||||
const el = document.createElement('button'); el.type = 'button'; el.className = 'ui-button card row profile-list-row';
|
||||
const el = document.createElement('button');
|
||||
el.type = 'button';
|
||||
el.className = 'ui-button card row profile-list-row';
|
||||
el.append(renderUserAvatar({ login: row.ownerLogin, firstName: row.displayName, lastName: '', avatar: parseAvatar(row.avatarAr), size: 'md' }));
|
||||
const t = document.createElement('div'); t.className = 'profile-list-row-text';
|
||||
const t = document.createElement('div');
|
||||
t.className = 'profile-list-row-text';
|
||||
t.innerHTML = `<b>${String(row.displayName || row.slug || '')}</b><small>${String(row.ownerLogin || '')} / ${String(row.slug || '')}</small>`;
|
||||
el.append(t);
|
||||
el.addEventListener('click', () => navigate(`channel/${encodeURIComponent(row.ownerBlockchainName)}/${Number(row.rootBlockNumber || 0)}/${encodeURIComponent(row.rootBlockHashHex || '')}/about`));
|
||||
@@ -47,25 +108,35 @@ export function render({navigate, route, chrome}) {
|
||||
status.textContent = rows.length ? '' : 'Список пуст.';
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = await authService.listUserProfileRelations(login, kind, 200, 0);
|
||||
if (generation !== loadGeneration) return;
|
||||
const rows = Array.isArray(payload?.users) ? payload.users : [];
|
||||
rows.forEach((row) => {
|
||||
const el = document.createElement('button'); el.type = 'button'; el.className = 'ui-button card row profile-list-row';
|
||||
el.append(renderUserAvatar({ login: row.login, firstName: row.firstName, lastName: row.lastName, avatar: parseAvatar(row.avatarAr), size: 'md' }));
|
||||
const fullName = userDisplayName(row);
|
||||
const t = document.createElement('div'); t.className = 'profile-list-row-text';
|
||||
const marks = [
|
||||
row.relationType && row.relationType !== 'none' ? ({contact:'контакт',friend:'друг',close_friend:'близкий друг'}[row.relationType] || row.relationType) : '',
|
||||
row.accountRole === 'primary' ? 'основной' : row.accountRole === 'non_voting' ? 'голос не учитывается' : '',
|
||||
row.shineStatus === 'shining' ? 'сияющий' : row.shineStatus === 'not_interested' ? 'сияние неинтересно' : '',
|
||||
row.primaryConfirmed ? 'основной подтверждён ✓' : '',
|
||||
row.shineConfirmed ? 'сияющий подтверждён ✓' : '',
|
||||
].filter(Boolean).join(' · ');
|
||||
t.innerHTML = `<b>${fullName}</b><small>${String(row.login || '')}${marks ? ` · ${marks}` : ''}</small>`;
|
||||
el.append(t); el.addEventListener('click', () => navigate(`SHiNE/${encodeURIComponent(row.login)}`)); body.append(el);
|
||||
});
|
||||
renderRelationRows(rows);
|
||||
status.textContent = rows.length ? '' : 'Список пуст.';
|
||||
} catch (e) { status.className = 'status-line is-unavailable'; status.textContent = `Ошибка: ${e.message || 'unknown'}`; }
|
||||
})();
|
||||
} catch (e) {
|
||||
if (generation !== loadGeneration) return;
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.textContent = `Ошибка: ${e.message || 'unknown'}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (isFriendsScreen) {
|
||||
screen.addEventListener('click', (event) => {
|
||||
const tab = event.target.closest('[data-friend-kind]');
|
||||
if (!tab) return;
|
||||
const nextKind = String(tab.dataset.friendKind || '');
|
||||
if (!nextKind || nextKind === activeKind) return;
|
||||
activeKind = nextKind;
|
||||
screen.querySelectorAll('[data-friend-kind]').forEach((button) => {
|
||||
const selected = button.dataset.friendKind === activeKind;
|
||||
button.classList.toggle('is-active', selected);
|
||||
button.setAttribute('aria-selected', selected ? 'true' : 'false');
|
||||
});
|
||||
void load(activeKind);
|
||||
});
|
||||
}
|
||||
|
||||
void load(activeKind);
|
||||
return screen;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user