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;