UI: нормальное закрытие сессий и сортировка устройств

This commit is contained in:
AidarKC
2026-06-16 10:36:43 +04:00
parent 41d199e24a
commit 5c155ef503
8 changed files with 133 additions and 40 deletions
+22 -11
View File
@@ -1,6 +1,5 @@
import { renderHeader } from '../components/header.js';
import {
authService,
isSessionInvalidError,
refreshSessions,
setAuthError,
@@ -32,6 +31,15 @@ function formatOnlineStatus(onlineOnThisServer) {
return onlineOnThisServer ? 'Online now' : 'Offline';
}
function sortSessionsByOnline(sessions = []) {
return [...sessions].sort((a, b) => {
const aOnline = a?.onlineOnThisServer ? 1 : 0;
const bOnline = b?.onlineOnThisServer ? 1 : 0;
if (aOnline !== bOnline) return bOnline - aOnline;
return Number(b?.lastAuthenticatedAtMs || 0) - Number(a?.lastAuthenticatedAtMs || 0);
});
}
export function render({ navigate }) {
const screen = document.createElement('section');
screen.className = 'stack';
@@ -59,9 +67,9 @@ export function render({ navigate }) {
const buildList = () => {
sessionsBlock.innerHTML = '';
const sessions = state.sessions || [];
const sessions = sortSessionsByOnline(state.sessions || []);
const current = sessions.find((s) => s.sessionId === state.session.sessionId) || sessions[0];
const others = sessions.filter((s) => s.sessionId !== current?.sessionId);
const others = sortSessionsByOnline(sessions.filter((s) => s.sessionId !== current?.sessionId));
const createSessionItem = (session, isCurrent) => {
const item = document.createElement('button');
@@ -70,12 +78,13 @@ export function render({ navigate }) {
const sessionTypeText = formatSessionType(session.sessionType);
const sessionPlatformText = session.clientPlatform ? ` · ${session.clientPlatform}` : '';
const onlineStatusText = formatOnlineStatus(!!session.onlineOnThisServer);
const onlineStatusClass = session.onlineOnThisServer ? 'session-status session-status--online' : 'session-status';
item.innerHTML = `
<div class="row" style="align-items:flex-start;">
<div class="stack" style="gap:4px; text-align:left;">
<strong>${session.clientInfoFromClient || 'unknown client'}</strong>
<span class="meta-muted"><strong>Type:</strong> ${sessionTypeText}${sessionPlatformText}</span>
<span class="meta-muted"><strong>Status:</strong> ${onlineStatusText}</span>
<span class="${onlineStatusClass}"><strong>Status:</strong> ${onlineStatusText}</span>
<span class="meta-muted">${session.geo || 'unknown'}</span>
</div>
<span class="meta-muted">${formatSessionTime(session.lastAuthenticatedAtMs || Date.now())}</span>
@@ -108,29 +117,31 @@ export function render({ navigate }) {
if (!confirmed) return;
try {
await authService.closeSession(state.session.sessionId);
await terminateCurrentSession({
infoMessage: 'Текущая сессия завершена, данные на устройстве очищены.',
closeServerSession: true,
});
} catch (error) {
if (!isSessionInvalidError(error)) {
setAuthError(error.message);
window.alert(error.message);
return;
}
await terminateCurrentSession({
infoMessage: 'Текущая сессия завершена, данные на устройстве очищены.',
});
}
await terminateCurrentSession({
infoMessage: 'Текущая сессия завершена, данные на устройстве очищены.',
});
});
currentMenu.append(endCurrentSessionBtn);
const othersMenu = document.createElement('div');
othersMenu.className = 'stack';
othersMenu.innerHTML = '<p class="meta-muted">Остальные активные сеансы</p>';
othersMenu.innerHTML = '<p class="meta-muted">Остальные сеансы</p>';
if (others.length === 0) {
const empty = document.createElement('p');
empty.className = 'meta-muted';
empty.textContent = 'Других активных сеансов нет.';
empty.textContent = 'Других сеансов нет.';
othersMenu.append(empty);
} else {
others.forEach((session) => {