SHA256
Добавить смену профилей, но она пока не работает
This commit is contained in:
@@ -206,7 +206,7 @@ export function render({ navigate }) {
|
||||
await authService.reconnect(state.entrySettings.shineServer);
|
||||
const session = await authService.createSessionFromImportedSecrets(scannedTransfer.login, scannedTransfer.keys);
|
||||
await terminateCurrentSession({ closeServerSession: true });
|
||||
await clearStoredMessages().catch(() => {});
|
||||
await clearStoredMessages(session.login).catch(() => {});
|
||||
clearBrowserClientData();
|
||||
await clearClientAuthData().catch(() => {});
|
||||
await saveEncryptedUserSecrets(session.login, session.storagePwd, scannedTransfer.keys);
|
||||
|
||||
@@ -183,7 +183,7 @@ export function render({ navigate }) {
|
||||
const finalizeAuthorizedLogin = async (keys, login) => {
|
||||
const session = await authService.createSessionFromImportedSecrets(login, keys);
|
||||
await terminateCurrentSession({ closeServerSession: true, notifySessionReset: false });
|
||||
await clearStoredMessages().catch(() => {});
|
||||
await clearStoredMessages(session.login).catch(() => {});
|
||||
clearBrowserClientData();
|
||||
await clearClientAuthData().catch(() => {});
|
||||
await saveEncryptedUserSecrets(session.login, session.storagePwd, keys);
|
||||
@@ -216,7 +216,7 @@ export function render({ navigate }) {
|
||||
};
|
||||
|
||||
await terminateCurrentSession({ closeServerSession: true, notifySessionReset: false });
|
||||
await clearStoredMessages().catch(() => {});
|
||||
await clearStoredMessages(login).catch(() => {});
|
||||
clearBrowserClientData();
|
||||
await clearClientAuthData().catch(() => {});
|
||||
await authService.persistSessionMaterial(login, sessionMaterial);
|
||||
|
||||
@@ -91,6 +91,7 @@ export function render({ navigate, chrome }) {
|
||||
{ label: 'Редактировать профиль', iconSrc: '/assets/profile-icon-profile.svg', action: () => navigate('profile-edit-view') },
|
||||
{ label: 'Кошелёк', iconSrc: '/assets/profile-icon-wallet.svg', action: () => navigate('wallet-view') },
|
||||
{ label: 'Настройки', iconSrc: '/assets/profile-icon-settings.svg', action: () => navigate('settings-view') },
|
||||
{ label: 'Сменить профиль', action: () => navigate('profiles-view') },
|
||||
],
|
||||
});
|
||||
chrome?.setTopbar(topbar);
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
import { renderHeader } from '../components/header.js';
|
||||
import {
|
||||
closeAllSavedProfiles,
|
||||
closeSavedProfile,
|
||||
getSavedProfiles,
|
||||
prepareAddProfileLogin,
|
||||
state,
|
||||
switchToSavedProfile,
|
||||
} from '../state.js';
|
||||
|
||||
export const pageMeta = { id: 'profiles-view', title: 'Профили' };
|
||||
|
||||
function reloadTo(path) {
|
||||
const clean = String(path || '/profile').trim() || '/profile';
|
||||
window.location.assign(clean.startsWith('/') ? clean : `/${clean}`);
|
||||
}
|
||||
|
||||
export function render({ navigate }) {
|
||||
const screen = document.createElement('section');
|
||||
screen.className = 'stack profiles-screen';
|
||||
|
||||
screen.append(renderHeader({
|
||||
title: 'Профили',
|
||||
leftAction: { label: '←', onClick: () => navigate('profile-view') },
|
||||
}));
|
||||
|
||||
const intro = document.createElement('div');
|
||||
intro.className = 'meta-muted profiles-summary';
|
||||
|
||||
const list = document.createElement('div');
|
||||
list.className = 'stack profiles-list';
|
||||
|
||||
const status = document.createElement('div');
|
||||
status.className = 'status-line';
|
||||
status.hidden = true;
|
||||
|
||||
const actions = document.createElement('div');
|
||||
actions.className = 'stack profiles-actions';
|
||||
|
||||
const addButton = document.createElement('button');
|
||||
addButton.type = 'button';
|
||||
addButton.className = 'secondary-btn';
|
||||
addButton.textContent = 'Добавить профиль';
|
||||
addButton.addEventListener('click', () => {
|
||||
prepareAddProfileLogin();
|
||||
navigate('login-view');
|
||||
});
|
||||
|
||||
const closeAllButton = document.createElement('button');
|
||||
closeAllButton.type = 'button';
|
||||
closeAllButton.className = 'secondary-btn profiles-close-all';
|
||||
closeAllButton.textContent = 'Закрыть все профили';
|
||||
closeAllButton.addEventListener('click', async () => {
|
||||
const profiles = getSavedProfiles();
|
||||
if (!profiles.length) return;
|
||||
const confirmed = window.confirm('Закрыть все профили на этом устройстве? После этого откроется экран входа.');
|
||||
if (!confirmed) return;
|
||||
closeAllButton.disabled = true;
|
||||
status.hidden = false;
|
||||
status.textContent = 'Закрываем профили…';
|
||||
try {
|
||||
await closeAllSavedProfiles();
|
||||
reloadTo('/start');
|
||||
} catch (error) {
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.textContent = `Не удалось закрыть профили: ${error?.message || 'unknown'}`;
|
||||
closeAllButton.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
actions.append(addButton, closeAllButton);
|
||||
screen.append(intro, list, status, actions);
|
||||
|
||||
const renderList = () => {
|
||||
const profiles = getSavedProfiles();
|
||||
const active = profiles.find((item) => item.isActive);
|
||||
intro.textContent = profiles.length
|
||||
? `Профилей на устройстве: ${profiles.length}. Активен: ${active?.login || state.session.login || '—'}`
|
||||
: 'На устройстве нет сохранённых профилей.';
|
||||
closeAllButton.disabled = profiles.length === 0;
|
||||
list.innerHTML = '';
|
||||
|
||||
profiles.forEach((profile) => {
|
||||
const row = document.createElement('div');
|
||||
row.className = `card profiles-row${profile.isActive ? ' is-active' : ''}`;
|
||||
|
||||
const select = document.createElement('button');
|
||||
select.type = 'button';
|
||||
select.className = 'profiles-select';
|
||||
select.innerHTML = `<span class="profiles-login">${profile.login}</span>${profile.isActive ? '<span class="badge">Активный</span>' : ''}`;
|
||||
select.disabled = profile.isActive;
|
||||
select.addEventListener('click', async () => {
|
||||
if (profile.isActive) return;
|
||||
const confirmed = window.confirm(`Переключиться на профиль «${profile.login}»?`);
|
||||
if (!confirmed) return;
|
||||
status.hidden = false;
|
||||
status.className = 'status-line';
|
||||
status.textContent = `Подключаем профиль ${profile.login}…`;
|
||||
try {
|
||||
await switchToSavedProfile(profile.login);
|
||||
reloadTo('/profile');
|
||||
} catch (error) {
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.textContent = `Не удалось переключить профиль: ${error?.message || 'unknown'}`;
|
||||
}
|
||||
});
|
||||
|
||||
const close = document.createElement('button');
|
||||
close.type = 'button';
|
||||
close.className = 'profiles-close';
|
||||
close.setAttribute('aria-label', `Закрыть профиль ${profile.login}`);
|
||||
close.textContent = '×';
|
||||
close.addEventListener('click', async () => {
|
||||
const others = profiles.filter((item) => item.login.toLowerCase() !== profile.login.toLowerCase());
|
||||
const message = profile.isActive
|
||||
? (others.length
|
||||
? `Закрыть текущий профиль «${profile.login}»? После закрытия приложение переключится на следующий сохранённый профиль.`
|
||||
: `Закрыть текущий профиль «${profile.login}»? После закрытия откроется экран входа.`)
|
||||
: `Закрыть профиль «${profile.login}» на этом устройстве?`;
|
||||
if (!window.confirm(message)) return;
|
||||
|
||||
status.hidden = false;
|
||||
status.className = 'status-line';
|
||||
status.textContent = `Закрываем профиль ${profile.login}…`;
|
||||
try {
|
||||
const result = await closeSavedProfile(profile.login);
|
||||
if (profile.isActive) {
|
||||
reloadTo(result.nextProfile ? '/profile' : '/start');
|
||||
return;
|
||||
}
|
||||
status.hidden = true;
|
||||
renderList();
|
||||
} catch (error) {
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.textContent = `Не удалось закрыть профиль: ${error?.message || 'unknown'}`;
|
||||
}
|
||||
});
|
||||
|
||||
row.append(select, close);
|
||||
list.append(row);
|
||||
});
|
||||
};
|
||||
|
||||
renderList();
|
||||
return screen;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ export function render({ navigate }) {
|
||||
state.registrationDraft.pendingKeyBundle.blockchainPair = null;
|
||||
}
|
||||
|
||||
await clearStoredMessages().catch(() => {});
|
||||
await clearStoredMessages(state.registrationDraft.login).catch(() => {});
|
||||
|
||||
authorizeSession({
|
||||
login: state.registrationDraft.login,
|
||||
|
||||
@@ -107,7 +107,7 @@ async function completeRegistrationLogin({ navigate, keyBundle }) {
|
||||
},
|
||||
);
|
||||
await authService.persistSessionMaterial(result.login, result.sessionMaterial);
|
||||
await clearStoredMessages().catch(() => {});
|
||||
await clearStoredMessages(state.registrationDraft.login).catch(() => {});
|
||||
|
||||
const resumed = await authService.resumeSession(result.login, result.sessionId);
|
||||
const resumedLogin = resumed.login || result.login;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { renderHeader } from '../components/header.js';
|
||||
import { addAppLogEntry, authService, closeCurrentSessionAndSignOut } from '../state.js';
|
||||
import { addAppLogEntry, authService, closeSavedProfile, state } from '../state.js';
|
||||
|
||||
export const pageMeta = { id: 'settings-view', title: 'Настройки' };
|
||||
|
||||
@@ -77,7 +77,7 @@ export function render({ navigate }) {
|
||||
const signOutBtn = card.querySelector('#settings-signout');
|
||||
signOutBtn.addEventListener('click', async () => {
|
||||
const confirmed = window.confirm(
|
||||
'Завершить текущую сессию на сервере, отключиться, очистить локальные данные и перейти на стартовый экран?'
|
||||
'Завершить текущий профиль на этом устройстве? Если есть другие сохранённые профили, приложение переключится на следующий.'
|
||||
);
|
||||
if (!confirmed) return;
|
||||
|
||||
@@ -88,9 +88,8 @@ export function render({ navigate }) {
|
||||
source: 'session',
|
||||
message: 'Запрошено завершение текущей сессии',
|
||||
});
|
||||
await closeCurrentSessionAndSignOut({
|
||||
infoMessage: 'Сеанс завершён. Выполните вход заново.',
|
||||
});
|
||||
const result = await closeSavedProfile(state.session.login);
|
||||
window.location.assign(result?.nextProfile ? '/profile' : '/start');
|
||||
} finally {
|
||||
signOutBtn.disabled = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user