diff --git a/VERSION.properties b/VERSION.properties
index da975c1..4b7b44e 100644
--- a/VERSION.properties
+++ b/VERSION.properties
@@ -1,2 +1,2 @@
-client.version=1.2.54
-server.version=1.2.48
+client.version=1.2.55
+server.version=1.2.49
diff --git a/shine-UI/js/app.js b/shine-UI/js/app.js
index 618a081..225b149 100644
--- a/shine-UI/js/app.js
+++ b/shine-UI/js/app.js
@@ -30,7 +30,6 @@ import {
markIncomingReadByBaseKey,
markOutgoingReadByBaseKey,
setContacts,
- cancelAddAccountFlow,
} from './state.js';
import * as startView from './pages/start-view.js';
@@ -45,7 +44,6 @@ import * as loginPasswordView from './pages/login-password-view.js';
import * as keyStorageView from './pages/key-storage-view.js';
import * as profileView from './pages/profile-view.js';
-import * as accountSwitcherView from './pages/account-switcher-view.js';
import * as profileEditView from './pages/profile-edit-view.js';
import * as walletView from './pages/wallet-view.js';
import * as settingsView from './pages/settings-view.js';
@@ -85,7 +83,6 @@ const routes = {
'login-password-view': loginPasswordView,
'key-storage-view': keyStorageView,
'profile-view': profileView,
- 'account-switcher-view': accountSwitcherView,
'profile-edit-view': profileEditView,
'wallet-view': walletView,
'settings-view': settingsView,
@@ -679,13 +676,10 @@ function renderApp() {
return;
}
- if (state.session.isAuthorized && PRE_AUTH_PAGES.includes(pageId) && !state.accountAddingMode) {
+ if (state.session.isAuthorized && PRE_AUTH_PAGES.includes(pageId)) {
navigate('messages-list');
return;
}
- if (state.session.isAuthorized && !PRE_AUTH_PAGES.includes(pageId) && state.accountAddingMode) {
- cancelAddAccountFlow();
- }
const page = routes[pageId] || routes['start-view'];
diff --git a/shine-UI/js/components/toolbar.js b/shine-UI/js/components/toolbar.js
index f7e9512..67ef9dd 100644
--- a/shine-UI/js/components/toolbar.js
+++ b/shine-UI/js/components/toolbar.js
@@ -9,7 +9,6 @@ const ITEMS = [
{ pageId: 'profile-view', label: 'Профиль', icon: '👤' },
];
const CHANNEL_HOLD_MS = 260;
-const PROFILE_HOLD_MS = 320;
const CHANNEL_MODES = Object.freeze([
{ key: 'feed', label: 'Каналы' },
{ key: 'dialogs', label: 'Чаты' },
@@ -63,8 +62,6 @@ export function renderToolbar(currentPageId, navigate) {
}
if (item.pageId === 'channels-list') {
installChannelsHoldSwitcher(btn, navigate);
- } else if (item.pageId === 'profile-view') {
- installProfileHoldMenu(btn, navigate);
} else {
btn.addEventListener('click', () => navigate(item.pageId));
}
@@ -74,73 +71,6 @@ export function renderToolbar(currentPageId, navigate) {
return root;
}
-function installProfileHoldMenu(button, navigate) {
- let holdTimer = 0;
- let pressed = false;
- let holdActive = false;
- let overlay = null;
-
- const clearTimer = () => {
- if (holdTimer) {
- window.clearTimeout(holdTimer);
- holdTimer = 0;
- }
- };
-
- const closeOverlay = () => {
- if (overlay) overlay.remove();
- overlay = null;
- holdActive = false;
- };
-
- const openOverlay = () => {
- const rect = button.getBoundingClientRect();
- overlay = document.createElement('div');
- overlay.className = 'toolbar-channels-hold-overlay';
- overlay.style.minWidth = '190px';
- overlay.style.left = `${Math.round(rect.left + rect.width / 2)}px`;
- overlay.style.top = `${Math.round(rect.top - 12)}px`;
- overlay.innerHTML = ``;
- overlay.querySelector('[data-action="switch-profile"]')?.addEventListener('click', (event) => {
- event.preventDefault();
- event.stopPropagation();
- closeOverlay();
- navigate('account-switcher-view');
- });
- document.body.append(overlay);
- holdActive = true;
- };
-
- button.addEventListener('pointerdown', () => {
- pressed = true;
- holdActive = false;
- clearTimer();
- holdTimer = window.setTimeout(() => {
- if (!pressed) return;
- openOverlay();
- }, PROFILE_HOLD_MS);
- });
-
- button.addEventListener('pointerup', () => {
- clearTimer();
- const wasHold = holdActive;
- pressed = false;
- if (wasHold) {
- window.setTimeout(closeOverlay, 80);
- return;
- }
- navigate('profile-view');
- });
-
- button.addEventListener('pointercancel', () => {
- clearTimer();
- pressed = false;
- closeOverlay();
- });
-
- button.addEventListener('contextmenu', (event) => event.preventDefault());
-}
-
function installChannelsHoldSwitcher(button, navigate) {
let holdTimer = 0;
let pressed = false;
diff --git a/shine-UI/js/pages/account-switcher-view.js b/shine-UI/js/pages/account-switcher-view.js
deleted file mode 100644
index 1f3739c..0000000
--- a/shine-UI/js/pages/account-switcher-view.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { renderHeader } from '../components/header.js';
-import { beginAddAccountFlow, state, switchToAccount } from '../state.js';
-import { toUserMessage } from '../services/ui-error-texts.js';
-
-export const pageMeta = { id: 'account-switcher-view', title: 'Сменить профиль' };
-
-export function render({ navigate }) {
- const screen = document.createElement('section');
- screen.className = 'stack';
-
- screen.append(
- renderHeader({
- title: 'Сменить профиль',
- leftAction: { label: '<', onClick: () => navigate('profile-view') },
- }),
- );
-
- const list = document.createElement('div');
- list.className = 'stack';
- const status = document.createElement('div');
- status.className = 'meta-muted';
-
- const accounts = Array.isArray(state.accounts) ? state.accounts : [];
- const activeLogin = String(state.session.login || '').trim().toLowerCase();
-
- if (!accounts.length) {
- const empty = document.createElement('div');
- empty.className = 'card meta-muted';
- empty.textContent = 'Сохранённых аккаунтов пока нет.';
- list.append(empty);
- } else {
- accounts.forEach((account) => {
- const login = String(account?.login || '').trim();
- if (!login) return;
- const card = document.createElement('button');
- card.type = 'button';
- card.className = 'card row';
- card.style.justifyContent = 'space-between';
- card.style.alignItems = 'center';
- card.innerHTML = `
- ${login}
- ${login.toLowerCase() === activeLogin ? 'Активный' : 'Переключить'}
- `;
- card.addEventListener('click', async () => {
- if (login.toLowerCase() === activeLogin) return;
- status.textContent = 'Переключаем аккаунт...';
- try {
- await switchToAccount(login);
- status.textContent = '';
- navigate('profile-view');
- } catch (error) {
- status.textContent = toUserMessage(error, 'Не удалось переключить аккаунт.');
- }
- });
- list.append(card);
- });
- }
-
- const actions = document.createElement('div');
- actions.className = 'form-actions-grid';
- actions.innerHTML = `
-
-
- `;
- actions.querySelector('#account-switcher-add-login')?.addEventListener('click', () => {
- beginAddAccountFlow();
- navigate('login-view');
- });
- actions.querySelector('#account-switcher-add-register')?.addEventListener('click', () => {
- beginAddAccountFlow();
- navigate('register-view');
- });
-
- screen.append(list, actions, status);
- return screen;
-}
diff --git a/shine-UI/js/router.js b/shine-UI/js/router.js
index 0024ee4..9378a0b 100644
--- a/shine-UI/js/router.js
+++ b/shine-UI/js/router.js
@@ -142,7 +142,6 @@ export function resolveToolbarActive(pageId) {
if (ROOT_PAGES.includes(pageId)) return pageId;
if (
pageId === 'profile-edit-view' ||
- pageId === 'account-switcher-view' ||
pageId === 'wallet-view' ||
pageId === 'settings-view' ||
pageId === 'developer-settings-view' ||
diff --git a/shine-UI/js/state.js b/shine-UI/js/state.js
index 386567b..9e5245e 100644
--- a/shine-UI/js/state.js
+++ b/shine-UI/js/state.js
@@ -3,7 +3,6 @@ import { listStoredMessages, putStoredMessage } from './services/message-store.j
const clone = (value) => JSON.parse(JSON.stringify(value));
const SESSION_STORAGE_KEY = 'shine-ui-current-session-v1';
-const ACCOUNTS_STORAGE_KEY = 'shine-ui-accounts-v1';
const REACTIONS_STORAGE_KEY = 'shine-ui-message-reactions-v2';
const WEB_PUSH_SUBSCRIPTION_KEY = 'shine-ui-webpush-subscription-v1';
const ENTRY_SETTINGS_STORAGE_KEY = 'shine-ui-entry-settings-v1';
@@ -117,33 +116,6 @@ function loadStoredSession() {
}
}
-function loadStoredAccounts() {
- try {
- const raw = localStorage.getItem(ACCOUNTS_STORAGE_KEY);
- if (!raw) return [];
- const parsed = JSON.parse(raw);
- if (!Array.isArray(parsed)) return [];
- return parsed
- .map((item) => ({
- login: String(item?.login || '').trim(),
- sessionId: String(item?.sessionId || '').trim(),
- updatedAtMs: Number(item?.updatedAtMs || Date.now()),
- }))
- .filter((item) => item.login && item.sessionId);
- } catch {
- return [];
- }
-}
-
-function persistStoredAccounts(accounts) {
- try {
- const payload = Array.isArray(accounts) ? accounts : [];
- localStorage.setItem(ACCOUNTS_STORAGE_KEY, JSON.stringify(payload));
- } catch {
- // ignore storage errors
- }
-}
-
function loadStoredReactions() {
try {
const raw = localStorage.getItem(REACTIONS_STORAGE_KEY);
@@ -216,7 +188,6 @@ function persistEntrySettings(settings) {
function clearBrowserClientData() {
const localKeys = [
SESSION_STORAGE_KEY,
- ACCOUNTS_STORAGE_KEY,
REACTIONS_STORAGE_KEY,
WEB_PUSH_SUBSCRIPTION_KEY,
CHANNEL_NOTIFY_KEY,
@@ -239,7 +210,6 @@ function clearBrowserClientData() {
function createInitialState({ withStoredSession = true } = {}) {
const storedSession = withStoredSession ? loadStoredSession() : null;
- const storedAccounts = loadStoredAccounts();
const storedReactions = loadStoredReactions();
const storedEntrySettings = loadStoredEntrySettings();
const initialShineServer = LOCAL_WS_OVERRIDE_URL || DEFAULT_SHINE_SERVER;
@@ -259,9 +229,6 @@ function createInitialState({ withStoredSession = true } = {}) {
sessionId: storedSession?.sessionId || '',
storagePwdInMemory: '',
},
- accounts: storedAccounts,
- activeAccountLogin: String(storedSession?.login || ''),
- accountAddingMode: false,
startHint: '',
entrySettings: {
language: String(storedEntrySettings?.language || 'ru'),
@@ -731,19 +698,6 @@ export function authorizeSession({
login,
sessionId,
});
- const loginKey = String(login || '').trim().toLowerCase();
- const nextAccounts = [
- {
- login: String(login || '').trim(),
- sessionId: String(sessionId || '').trim(),
- updatedAtMs: Date.now(),
- },
- ...state.accounts.filter((item) => String(item?.login || '').trim().toLowerCase() !== loginKey),
- ];
- state.accounts = nextAccounts;
- state.activeAccountLogin = String(login || '').trim();
- state.accountAddingMode = false;
- persistStoredAccounts(nextAccounts);
state.startHint = '';
if (onSessionAuthorized) {
onSessionAuthorized();
@@ -767,20 +721,6 @@ export async function refreshSessions() {
return state.sessions;
}
-export async function switchToAccount(login) {
- const targetLogin = String(login || '').trim();
- if (!targetLogin) throw new Error('Не передан логин аккаунта.');
- const account = (state.accounts || []).find((item) => String(item?.login || '').trim().toLowerCase() === targetLogin.toLowerCase());
- if (!account?.sessionId) throw new Error('Сессия аккаунта не найдена.');
- const resumed = await authService.resumeSession(account.login, account.sessionId);
- authorizeSession({
- login: resumed.login || account.login,
- sessionId: resumed.sessionId || account.sessionId,
- storagePwd: resumed.storagePwd || state.session.storagePwdInMemory,
- });
- return resumed;
-}
-
function resetStateForSignedOut() {
const next = createInitialState({ withStoredSession: false });
state.chats = next.chats;
@@ -792,9 +732,6 @@ function resetStateForSignedOut() {
state.notificationsTab = next.notificationsTab;
state.pageLabelCollapsed = next.pageLabelCollapsed;
state.session = next.session;
- state.accounts = next.accounts;
- state.activeAccountLogin = next.activeAccountLogin;
- state.accountAddingMode = next.accountAddingMode;
state.startHint = next.startHint;
state.entrySettings = next.entrySettings;
state.registrationDraft = next.registrationDraft;
@@ -811,10 +748,6 @@ function resetStateForSignedOut() {
}
export async function terminateCurrentSession({ infoMessage = '' } = {}) {
- const currentLogin = String(state.session.login || '').trim().toLowerCase();
- const nextAccounts = (state.accounts || []).filter((item) => String(item?.login || '').trim().toLowerCase() !== currentLogin);
- state.accounts = nextAccounts;
- persistStoredAccounts(nextAccounts);
clearStoredSession();
resetStateForSignedOut();
authService.close();
@@ -849,14 +782,6 @@ export async function closeCurrentSessionAndSignOut({ infoMessage = '' } = {}) {
await terminateCurrentSession({ infoMessage });
}
-export function beginAddAccountFlow() {
- state.accountAddingMode = true;
-}
-
-export function cancelAddAccountFlow() {
- state.accountAddingMode = false;
-}
-
export function refreshRegistrationBalance() {
const next = (0.005 + Math.random() * 0.03).toFixed(4);
state.registrationPayment.balanceSOL = next;