import { renderHeader } from '../components/header.js'; import { authService, isSessionInvalidError, refreshSessions, setAuthError, setAuthInfo, state, terminateCurrentSession, } from '../state.js'; export const pageMeta = { id: 'device-view', title: 'Устройства' }; function formatSessionType(sessionType) { if (Number(sessionType) === 100) return 'Homeserver'; if (Number(sessionType) === 50) return 'Wallet'; if (Number(sessionType) === 1) return 'Client'; return `Type ${Number(sessionType) || 0}`; } function formatSessionTime(ms) { return new Date(ms).toLocaleString('ru-RU', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }); } function formatOnlineStatus(onlineOnThisServer) { return onlineOnThisServer ? 'Online now' : 'Offline'; } export function render({ navigate }) { const screen = document.createElement('section'); screen.className = 'stack'; screen.append( renderHeader({ title: 'Устройства', leftAction: { label: '←', onClick: () => navigate('settings-view') }, }), ); const actions = document.createElement('div'); actions.className = 'card stack'; actions.innerHTML = ` `; actions.querySelector('#connect-device-btn').addEventListener('click', () => navigate('connect-device-view')); actions.querySelector('#show-keys-btn').addEventListener('click', () => navigate('show-keys-view')); const sessionsBlock = document.createElement('div'); sessionsBlock.className = 'card stack'; const buildList = () => { sessionsBlock.innerHTML = ''; const sessions = state.sessions || []; const current = sessions.find((s) => s.sessionId === state.session.sessionId) || sessions[0]; const others = sessions.filter((s) => s.sessionId !== current?.sessionId); const createSessionItem = (session, isCurrent) => { const item = document.createElement('button'); item.className = 'session-item'; item.type = 'button'; const sessionTypeText = formatSessionType(session.sessionType); const sessionPlatformText = session.clientPlatform ? ` · ${session.clientPlatform}` : ''; const onlineStatusText = formatOnlineStatus(!!session.onlineOnThisServer); item.innerHTML = `
${session.clientInfoFromClient || 'unknown client'} Type: ${sessionTypeText}${sessionPlatformText} Status: ${onlineStatusText} ${session.geo || 'unknown'}
${formatSessionTime(session.lastAuthenticatedAtMs || Date.now())}
${isCurrent ? '
Текущий сеанс
' : ''} `; item.addEventListener('click', () => navigate(`device-session-view/${session.sessionId}`)); return item; }; if (!current) { const empty = document.createElement('p'); empty.className = 'meta-muted'; empty.textContent = 'Активные сессии не найдены.'; sessionsBlock.append(empty); return; } const currentMenu = document.createElement('div'); currentMenu.className = 'stack'; currentMenu.innerHTML = '

Текущий сеанс

'; currentMenu.append(createSessionItem(current, true)); const endCurrentSessionBtn = document.createElement('button'); endCurrentSessionBtn.className = 'text-btn'; endCurrentSessionBtn.type = 'button'; endCurrentSessionBtn.textContent = 'Завершить текущую сессию'; endCurrentSessionBtn.addEventListener('click', async () => { const confirmed = window.confirm('Хотите завершить текущую сессию?'); if (!confirmed) return; try { await authService.closeSession(state.session.sessionId); } catch (error) { if (!isSessionInvalidError(error)) { setAuthError(error.message); window.alert(error.message); return; } } await terminateCurrentSession({ infoMessage: 'Текущая сессия завершена, данные на устройстве очищены.', }); }); currentMenu.append(endCurrentSessionBtn); const othersMenu = document.createElement('div'); othersMenu.className = 'stack'; othersMenu.innerHTML = '

Остальные активные сеансы

'; if (others.length === 0) { const empty = document.createElement('p'); empty.className = 'meta-muted'; empty.textContent = 'Других активных сеансов нет.'; othersMenu.append(empty); } else { others.forEach((session) => { othersMenu.append(createSessionItem(session, false)); }); } sessionsBlock.append(currentMenu, othersMenu); }; actions.querySelector('#reload-sessions-btn').addEventListener('click', async () => { try { await refreshSessions(); buildList(); setAuthInfo('Список сессий обновлён.'); } catch (error) { if (isSessionInvalidError(error)) { await terminateCurrentSession({ infoMessage: 'Сессия на этом устройстве уже завершена. Выполните вход заново.', }); return; } setAuthError(error.message); window.alert(error.message); } }); buildList(); screen.append(actions, sessionsBlock); return screen; }