From 162ef861d7a4e3bfbdaf3bd8d65a94bc1ffb09b9 Mon Sep 17 00:00:00 2001 From: Dmitriy Petrov Date: Tue, 14 Jul 2026 22:06:38 +0300 Subject: [PATCH] Simplify client overview access controls and layout --- src/shared/versions.js | 4 +- src/web/components/ClientOverviewPage.jsx | 138 +++++++------------- src/web/styles.css | 84 ++++++------ src/web/utils/clientControls.js | 9 -- test/web/client-controls.test.js | 11 -- test/web/responsive-layout-contract.test.js | 13 ++ test/web/rule-editor-contract.test.js | 10 +- 7 files changed, 104 insertions(+), 165 deletions(-) diff --git a/src/shared/versions.js b/src/shared/versions.js index b4d0a0a..807808e 100644 --- a/src/shared/versions.js +++ b/src/shared/versions.js @@ -1,6 +1,6 @@ export const HARBOR_VERSIONS = Object.freeze({ - macClient: '0.8.3', - gatewayClient: '0.8.3', + macClient: '0.8.4', + gatewayClient: '0.8.4', gatewayBackend: '0.8.0', }); diff --git a/src/web/components/ClientOverviewPage.jsx b/src/web/components/ClientOverviewPage.jsx index 81ede1a..147fadf 100644 --- a/src/web/components/ClientOverviewPage.jsx +++ b/src/web/components/ClientOverviewPage.jsx @@ -2,7 +2,6 @@ import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { flushSync } from 'react-dom'; import { api } from '../api.js'; import { - accessTabForKey, connectionAction, connectionDurationParts, copyText, @@ -27,10 +26,6 @@ import { const SUBSCRIPTION_REVEAL_DELAY_MS = 1350; const DURATION_MODE_STORAGE_KEY = 'harbor-duration-mode'; -const ACCESS_TABS = [ - ['gateway', 'Gateway'], - ['proxy', 'Gateway Proxy'], -]; function CloudTooltip({ children }) { return {children}; @@ -632,7 +627,6 @@ export function ClientOverviewPage({ const [editingSubscription, setEditingSubscription] = useState(!state?.hasSubscription); const [showIntro, setShowIntro] = useState(!hasSubscription); const [subscriptionContentReady, setSubscriptionContentReady] = useState(hasSubscription); - const [accessTab, setAccessTab] = useState('gateway'); const [copyFeedback, setCopyFeedback] = useState(null); const [subscriptionValidation, setSubscriptionValidation] = useState({ url: '', @@ -666,6 +660,11 @@ export function ClientOverviewPage({ const proxyUrls = localProxyUrls(state?.proxyPort, gatewayAddress); const usage = subscriptionUsage(state?.userInfo); const duration = connectionDurationParts(state?.singboxStartedAt, now); + const wordClockDuration = [ + ['hours', duration.hours], + ['minutes', duration.minutes], + ['seconds', duration.seconds], + ].filter(([name, part]) => duration.days.value || part.value || name === 'seconds'); const connectionTitle = connected ? gatewayDirect ? 'Gateway подключён' : 'VPN включён' : 'Подключение выключено'; @@ -932,14 +931,6 @@ export function ClientOverviewPage({ copyTimerRef.current = setTimeout(() => setCopyFeedback(null), 800); } - function navigateAccessTabs(event, current) { - if (!['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) return; - event.preventDefault(); - const next = accessTabForKey(ACCESS_TABS.map(([tab]) => tab), current, event.key); - setAccessTab(next); - requestAnimationFrame(() => document.getElementById(`client-access-tab-${next}`)?.focus()); - } - async function refreshSubscription() { const startedAt = performance.now(); setRefreshingInfo(true); @@ -1158,24 +1149,27 @@ export function ClientOverviewPage({ : {durationMode === 'digital' ? 'Показать время словами' : 'Показать цифровой таймер'} @@ -1188,54 +1182,8 @@ export function ClientOverviewPage({ -
- {isGateway && ( -
- {ACCESS_TABS.map(([tab, label]) => ( - - ))} -
- )} - {isGateway && ( - - )} -