From d24d1c178b9a395157e875b5e46542f1ed62cb066870e9965b08cc785f2facbd Mon Sep 17 00:00:00 2001 From: AidarKC Date: Wed, 22 Jul 2026 14:12:10 +0400 Subject: [PATCH] Shorten public UI routes --- shine-UI/js/pages/channel-thread-view.js | 2 +- shine-UI/js/pages/channel-view.js | 2 +- shine-UI/js/pages/channels-list.js | 2 +- shine-UI/js/pages/developer-settings-view.js | 2 +- shine-UI/js/pages/messages-list.js | 2 +- shine-UI/js/pages/network-view.js | 4 +- shine-UI/js/router.js | 218 ++++++++++++++++-- shine-UI/js/services/shine-routes.js | 18 +- shine-UI/js/services/solana-wallet-service.js | 2 +- 9 files changed, 220 insertions(+), 32 deletions(-) diff --git a/shine-UI/js/pages/channel-thread-view.js b/shine-UI/js/pages/channel-thread-view.js index f34170cd..61cce350 100644 --- a/shine-UI/js/pages/channel-thread-view.js +++ b/shine-UI/js/pages/channel-thread-view.js @@ -878,7 +878,7 @@ export function render({ navigate, route }) { const login = state.session.login; const storagePwd = state.session.storagePwdInMemory; if (!login || !storagePwd) { - state.authReturnHash = window.location.pathname || '/channels-list'; + state.authReturnHash = window.location.pathname || '/channels'; navigate('login-view'); throw new Error('Для этого действия нужно войти'); } diff --git a/shine-UI/js/pages/channel-view.js b/shine-UI/js/pages/channel-view.js index ed2d0c84..9780c031 100644 --- a/shine-UI/js/pages/channel-view.js +++ b/shine-UI/js/pages/channel-view.js @@ -1200,7 +1200,7 @@ export function render({ navigate, route }) { const login = state.session.login; const storagePwd = state.session.storagePwdInMemory; if (!login || !storagePwd) { - state.authReturnHash = window.location.pathname || '/channels-list'; + state.authReturnHash = window.location.pathname || '/channels'; navigate('login-view'); throw new Error('Для этого действия нужно войти'); } diff --git a/shine-UI/js/pages/channels-list.js b/shine-UI/js/pages/channels-list.js index 98b02f6b..0c12dd65 100644 --- a/shine-UI/js/pages/channels-list.js +++ b/shine-UI/js/pages/channels-list.js @@ -1197,7 +1197,7 @@ export function render({ navigate, route }) { const rerenderList = () => { try { - const expectedPath = '/channels-list'; + const expectedPath = '/channels'; if (window.location.pathname !== expectedPath) { window.history.replaceState({}, '', expectedPath); } diff --git a/shine-UI/js/pages/developer-settings-view.js b/shine-UI/js/pages/developer-settings-view.js index b570a909..a404bbbe 100644 --- a/shine-UI/js/pages/developer-settings-view.js +++ b/shine-UI/js/pages/developer-settings-view.js @@ -185,7 +185,7 @@ function openDeveloperAvatarUploadModal({ walletLogin, storagePwd, gateway } = { async function forceUiUpdateNow() { try { - window.history.replaceState({}, '', '/settings-view'); + window.history.replaceState({}, '', '/settings'); window.dispatchEvent(new PopStateEvent('popstate')); } catch {} if (!('serviceWorker' in navigator)) { diff --git a/shine-UI/js/pages/messages-list.js b/shine-UI/js/pages/messages-list.js index 7299a77b..620d7ef3 100644 --- a/shine-UI/js/pages/messages-list.js +++ b/shine-UI/js/pages/messages-list.js @@ -142,7 +142,7 @@ export function render({ navigate }) { if (previewEl) previewEl.textContent = resolveLastMessagePreview(item.lastMessage) || 'Диалог пока пуст.'; if (timeEl) timeEl.textContent = String(item.time || ''); row.prepend(avatarWrap); - row.addEventListener('click', () => navigate(`chat-view/${encodeURIComponent(normalizeDmChatId(item.id))}`)); + row.addEventListener('click', () => navigate(`chat/${encodeURIComponent(normalizeDmChatId(item.id))}`)); return row; } diff --git a/shine-UI/js/pages/network-view.js b/shine-UI/js/pages/network-view.js index b76c1137..733e21a1 100644 --- a/shine-UI/js/pages/network-view.js +++ b/shine-UI/js/pages/network-view.js @@ -430,7 +430,7 @@ export function render({ navigate, route }) { const act = btn.dataset.act; if (act === 'close') hideNodeSheet(); else if (act === 'profile') { const r = profileInfoRoute(login); if (r) navigate(r); } - else if (act === 'write') navigate(`chat-view/${encodeURIComponent(login)}`); + else if (act === 'write') navigate(`chat/${encodeURIComponent(login)}`); }; } @@ -462,7 +462,7 @@ export function render({ navigate, route }) { point, actions: [ { label: 'Профиль', onClick: () => { const r = profileInfoRoute(login); if (r) navigate(r); } }, - { label: 'Написать', onClick: () => navigate(`chat-view/${encodeURIComponent(login)}`) }, + { label: 'Написать', onClick: () => navigate(`chat/${encodeURIComponent(login)}`) }, ], }); }, diff --git a/shine-UI/js/router.js b/shine-UI/js/router.js index 637dc031..a1b675fb 100644 --- a/shine-UI/js/router.js +++ b/shine-UI/js/router.js @@ -1,6 +1,53 @@ import { parseShineRootSegment } from './services/shine-routes.js'; const ROOT_PAGES = ['messages-list', 'channels-list', 'network-view', 'notifications-view', 'profile-view']; +const PRETTY_PATHS = new Map([ + ['start-view', 'start'], + ['entry-settings-view', 'entry-settings'], + ['register-view', 'register'], + ['registration-faq-view', 'register/faq'], + ['registration-payment-view', 'register/payment'], + ['registration-draft-keys-view', 'register/draft-keys'], + ['registration-keys-view', 'register/keys'], + ['topup-view', 'topup'], + ['devnet-topup-view', 'devnet-topup'], + ['login-view', 'login'], + ['login-camera-view', 'login/camera'], + ['login-other-device-view', 'login/device'], + ['login-password-view', 'login/password'], + ['key-storage-view', 'key-storage'], + ['profile-view', 'profile'], + ['profile-edit-view', 'profile/edit'], + ['messages-list', 'messages'], + ['contact-search-view', 'contacts'], + ['chat-view', 'chat'], + ['channels-list', 'channels'], + ['add-channel-view', 'channels/new'], + ['add-personal-public-chat-view', 'channels/new-public-chat'], + ['channel-view', 'channel'], + ['channel-thread-view', 'thread'], + ['network-view', 'network'], + ['notifications-view', 'notifications'], + ['settings-view', 'settings'], + ['server-settings-view', 'settings/servers'], + ['tools-settings-view', 'settings/tools'], + ['developer-settings-view', 'settings/developer'], + ['trusted-device-login-settings-view', 'settings/device-login'], + ['language-view', 'settings/language'], + ['app-log-view', 'settings/app-log'], + ['pwa-diagnostics-view', 'settings/pwa-diagnostics'], + ['solana-users-init-view', 'settings/solana-users-init'], + ['solana-rpc-check-view', 'settings/solana-rpc-check'], + ['wallet-view', 'wallet'], + ['device-view', 'devices'], + ['device-session-view', 'devices'], + ['connect-device-view', 'devices/connect'], + ['device-pairing-view', 'devices/pairing'], + ['device-qr-view', 'devices/qr'], + ['device-camera-view', 'devices/camera'], + ['show-keys-view', 'devices/keys'], + ['remote-addblock-session-view', 'remote-addblock-session'], +]); export const PRE_AUTH_PAGES = [ 'start-view', @@ -39,6 +86,7 @@ export function getRoute() { return value || ''; } }; + const isLikelyBlockNumber = (value) => /^[0-9]+$/.test(String(value || '').trim()); const shineLogin = parseShineRootSegment(pageId); if (shineLogin) { @@ -68,12 +116,12 @@ export function getRoute() { params: { mode: 'feed', login: shineLogin, scope: 'all' }, }; } - if (section === 'msg') { + if (segments.length === 2 && isLikelyBlockNumber(segments[1])) { return { pageId: 'channel-thread-view', params: { - messageBlockchainName: decodePart(segments[2]), - messageBlockNumber: segments[3] || '', + messageBlockchainName: shineLogin, + messageBlockNumber: segments[1] || '', messageBlockHash: '', channelOwnerBlockchainName: '', channelRootBlockNumber: '', @@ -81,10 +129,10 @@ export function getRoute() { }, }; } - if (section === 'channel') { - const ownerBlockchainName = decodePart(segments[2] || ''); - const channelName = decodePart(segments[3] || ''); - const messageBlockNumber = segments[4] || ''; + if (segments.length >= 2) { + const ownerBlockchainName = shineLogin; + const channelName = decodePart(segments[1] || ''); + const messageBlockNumber = segments[2] || ''; if (ownerBlockchainName && channelName && messageBlockNumber) { return { pageId: 'channel-thread-view', @@ -100,15 +148,147 @@ export function getRoute() { }, }; } - return { - pageId: 'channel-view', - params: { ownerBlockchainName, channelName, channelId: '' }, - }; + if (ownerBlockchainName && channelName) { + return { + pageId: 'channel-view', + params: { ownerBlockchainName, channelName, channelId: '' }, + }; + } } } - if (pageId === 'chat-view') { - return { pageId, params: { chatId: dynamicId ? decodeURIComponent(dynamicId) : '' } }; + if (pageId === 'chat' || pageId === 'chat-view') { + return { pageId: 'chat-view', params: { chatId: dynamicId ? decodeURIComponent(dynamicId) : '' } }; + } + + if (pageId === 'start') { + return { pageId: 'start-view', params: {} }; + } + + if (pageId === 'entry-settings') { + return { pageId: 'entry-settings-view', params: {} }; + } + + if (pageId === 'register') { + const sub = decodePart(segments[1] || '').toLowerCase(); + if (sub === 'faq') return { pageId: 'registration-faq-view', params: {} }; + if (sub === 'payment') return { pageId: 'registration-payment-view', params: {} }; + if (sub === 'draft-keys') return { pageId: 'registration-draft-keys-view', params: {} }; + if (sub === 'keys') return { pageId: 'registration-keys-view', params: {} }; + return { pageId: 'register-view', params: {} }; + } + + if (pageId === 'topup') { + return { pageId: 'topup-view', params: {} }; + } + + if (pageId === 'devnet-topup') { + return { pageId: 'devnet-topup-view', params: {} }; + } + + if (pageId === 'login') { + const sub = decodePart(segments[1] || '').toLowerCase(); + if (sub === 'camera') return { pageId: 'login-camera-view', params: {} }; + if (sub === 'device') return { pageId: 'login-other-device-view', params: {} }; + if (sub === 'password') return { pageId: 'login-password-view', params: {} }; + return { pageId: 'login-view', params: {} }; + } + + if (pageId === 'key-storage') { + return { pageId: 'key-storage-view', params: {} }; + } + + if (pageId === 'profile') { + const sub = decodePart(segments[1] || '').toLowerCase(); + if (sub === 'edit') return { pageId: 'profile-edit-view', params: {} }; + return { pageId: 'profile-view', params: {} }; + } + + if (pageId === 'messages') { + return { pageId: 'messages-list', params: {} }; + } + + if (pageId === 'contacts') { + return { pageId: 'contact-search-view', params: {} }; + } + + if (pageId === 'channels') { + const sub = decodePart(segments[1] || '').toLowerCase(); + if (sub === 'new') return { pageId: 'add-channel-view', params: {} }; + if (sub === 'new-public-chat') return { pageId: 'add-personal-public-chat-view', params: {} }; + return { pageId: 'channels-list', params: { mode: segments[1] ? decodePart(segments[1]) : '' } }; + } + + if (pageId === 'channel') { + if (segments.length >= 4) { + return { + pageId: 'channel-view', + params: { + ownerBlockchainName: decodePart(segments[1]), + channelRootBlockNumber: segments[2] || '', + channelRootBlockHash: segments[3] || '', + channelId: '', + }, + }; + } + return { pageId: 'channel-view', params: { channelId: dynamicId || '' } }; + } + + if (pageId === 'thread') { + return { + pageId: 'channel-thread-view', + params: { + messageBlockchainName: decodePart(segments[1]), + messageBlockNumber: segments[2] || '', + messageBlockHash: '', + channelOwnerBlockchainName: decodePart(segments[3]), + channelRootBlockNumber: segments[4] || '', + channelRootBlockHash: segments[5] || '', + }, + }; + } + + if (pageId === 'network') { + return { pageId: 'network-view', params: { mode: segments[1] ? decodePart(segments[1]) : '' } }; + } + + if (pageId === 'notifications') { + return { pageId: 'notifications-view', params: {} }; + } + + if (pageId === 'settings') { + const sub = decodePart(segments[1] || '').toLowerCase(); + if (sub === 'servers') return { pageId: 'server-settings-view', params: {} }; + if (sub === 'tools') return { pageId: 'tools-settings-view', params: {} }; + if (sub === 'developer') return { pageId: 'developer-settings-view', params: {} }; + if (sub === 'device-login') return { pageId: 'trusted-device-login-settings-view', params: {} }; + if (sub === 'language') return { pageId: 'language-view', params: {} }; + if (sub === 'app-log') return { pageId: 'app-log-view', params: {} }; + if (sub === 'pwa-diagnostics') return { pageId: 'pwa-diagnostics-view', params: {} }; + if (sub === 'solana-users-init') return { pageId: 'solana-users-init-view', params: {} }; + if (sub === 'solana-rpc-check') return { pageId: 'solana-rpc-check-view', params: {} }; + return { pageId: 'settings-view', params: {} }; + } + + if (pageId === 'wallet') { + return { pageId: 'wallet-view', params: {} }; + } + + if (pageId === 'devices') { + const sub = decodePart(segments[1] || '').toLowerCase(); + if (sub === 'connect') return { pageId: 'connect-device-view', params: {} }; + if (sub === 'pairing') return { pageId: 'device-pairing-view', params: {} }; + if (sub === 'qr') return { pageId: 'device-qr-view', params: {} }; + if (sub === 'camera') return { pageId: 'device-camera-view', params: {} }; + if (sub === 'keys') return { pageId: 'show-keys-view', params: {} }; + if (dynamicId) { + return { pageId: 'device-session-view', params: { sessionId: decodeURIComponent(dynamicId) } }; + } + return { pageId: 'device-view', params: {} }; + } + + if (pageId === 'remote-addblock-session') { + return { pageId: 'remote-addblock-session-view', params: {} }; } if (pageId === 'channel-view') { @@ -160,7 +340,7 @@ export function getRoute() { } export function navigate(path) { - const cleanPath = String(path || '').replace(/^\/+/, ''); + const cleanPath = toPrettyPath(path); const nextPath = cleanPath ? `/${cleanPath}` : '/'; if (window.location.pathname !== nextPath) { window.history.pushState({}, '', nextPath); @@ -168,6 +348,16 @@ export function navigate(path) { window.dispatchEvent(new PopStateEvent('popstate')); } +export function toPrettyPath(path) { + const raw = String(path || '').replace(/^\/+/, '').replace(/\/+$/, ''); + if (!raw) return ''; + const segments = raw.split('/').filter(Boolean); + if (!segments.length) return ''; + const [head, ...tail] = segments; + const prettyHead = PRETTY_PATHS.get(head) || head; + return [prettyHead, ...tail].join('/'); +} + export function navigateBack() { if (window.history.length <= 1) return; window.history.back(); diff --git a/shine-UI/js/services/shine-routes.js b/shine-UI/js/services/shine-routes.js index 5b50929f..6026e628 100644 --- a/shine-UI/js/services/shine-routes.js +++ b/shine-UI/js/services/shine-routes.js @@ -23,17 +23,17 @@ export function extractLoginFromBlockchainName(value = '') { export function makeProfileRoute(login = '') { const clean = normalizeLogin(login); - return clean ? `shine.${encodeRoutePart(clean)}` : 'profile-view'; + return clean ? `shine.${encodeRoutePart(clean)}` : 'profile'; } export function makeProfileLinksRoute(login = '') { const clean = normalizeLogin(login); - return clean ? `shine.${encodeRoutePart(clean)}/links` : 'network-view/keep-history'; + return clean ? `shine.${encodeRoutePart(clean)}/links` : 'network/keep-history'; } export function makeProfileChannelsRoute(login = '', scope = 'all') { const clean = normalizeLogin(login); - if (!clean) return 'channels-list/feed'; + if (!clean) return 'channels/feed'; const normalizedScope = String(scope || '').trim().toLowerCase(); if (normalizedScope === 'owned') return `shine.${encodeRoutePart(clean)}/channels/owned`; if (normalizedScope === 'following') return `shine.${encodeRoutePart(clean)}/channels/following`; @@ -41,21 +41,19 @@ export function makeProfileChannelsRoute(login = '', scope = 'all') { } export function makeShineChannelRoute({ ownerLogin = '', ownerBlockchainName = '', channelName = '', messageBlockNumber = '' }) { - const cleanOwnerLogin = normalizeLogin(ownerLogin) || extractLoginFromBlockchainName(ownerBlockchainName); const ownerBch = String(ownerBlockchainName || '').trim(); const chName = String(channelName || '').trim(); const msgNo = String(messageBlockNumber || '').trim(); - if (!cleanOwnerLogin || !ownerBch || !chName) return ''; - if (msgNo) return `shine.${encodeRoutePart(cleanOwnerLogin)}/channel/${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}/${encodeRoutePart(msgNo)}`; - return `shine.${encodeRoutePart(cleanOwnerLogin)}/channel/${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}`; + if (!ownerBch || !chName) return ''; + if (msgNo) return `shine.${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}/${encodeRoutePart(msgNo)}`; + return `shine.${encodeRoutePart(ownerBch)}/${encodeRoutePart(chName)}`; } export function makeShineMessageRoute({ ownerLogin = '', messageBlockchainName = '', messageBlockNumber = '' }) { - const cleanOwnerLogin = normalizeLogin(ownerLogin); const msgBch = String(messageBlockchainName || '').trim(); const msgNo = String(messageBlockNumber || '').trim(); - if (!cleanOwnerLogin || !msgBch || !msgNo) return ''; - return `shine.${encodeRoutePart(cleanOwnerLogin)}/msg/${encodeRoutePart(msgBch)}/${encodeRoutePart(msgNo)}`; + if (!msgBch || !msgNo) return ''; + return `shine.${encodeRoutePart(msgBch)}/${encodeRoutePart(msgNo)}`; } export function parseShineRootSegment(segment = '') { diff --git a/shine-UI/js/services/solana-wallet-service.js b/shine-UI/js/services/solana-wallet-service.js index defdc926..444ff2cf 100644 --- a/shine-UI/js/services/solana-wallet-service.js +++ b/shine-UI/js/services/solana-wallet-service.js @@ -4,7 +4,7 @@ import { SOLANA_ENDPOINT_DEFAULT } from '../solana-programs.js'; import { loadSolanaWeb3 } from '../vendor/solana-web3-loader.js'; const DEFAULT_SOLANA_ENDPOINT = SOLANA_ENDPOINT_DEFAULT; -const TOPUP_SITE_URL = '/devnet-topup-view'; +const TOPUP_SITE_URL = '/devnet-topup'; let solanaLibPromise = null; const BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]+$/;