Refine client setup state and subscription controls

This commit is contained in:
2026-07-11 10:43:28 +03:00
parent 99f7f58fcb
commit e19d33adb9
7 changed files with 266 additions and 13 deletions

View File

@@ -20,12 +20,15 @@ export function ClientOverviewPage({
setPendingTag,
onFetchSubscription,
onRefreshSubscriptionInfo,
onForgetSubscription,
onApply,
onRestart,
onStop,
}) {
const connected = Boolean(state?.singboxRunning);
const hasSubscription = Boolean(state?.hasSubscription);
const selectedTag = pendingTag || state?.selectedTag || '';
const showPower = hasSubscription && Boolean(selectedTag);
const canStart = Boolean(selectedTag || state?.configExists);
const [now, setNow] = useState(Date.now());
const [editingSubscription, setEditingSubscription] = useState(!state?.hasSubscription);
@@ -82,6 +85,10 @@ export function ClientOverviewPage({
if (editingSubscription) subscriptionInputRef.current?.focus();
}, [editingSubscription]);
useEffect(() => {
if (!hasSubscription) setEditingSubscription(true);
}, [hasSubscription]);
useEffect(() => {
if (!editingSubscription || !state?.hasSubscription || subscriptionUrl) return undefined;
const timer = setTimeout(() => setEditingSubscription(false), 5000);
@@ -89,7 +96,7 @@ export function ClientOverviewPage({
}, [editingSubscription, state?.hasSubscription, subscriptionUrl]);
useEffect(() => {
if (!editingSubscription) return undefined;
if (!editingSubscription || !hasSubscription) return undefined;
const closeOnOutsideClick = (event) => {
if (subscriptionRef.current?.contains(event.target)) return;
setSubscriptionUrl('');
@@ -97,7 +104,7 @@ export function ClientOverviewPage({
};
document.addEventListener('pointerdown', closeOnOutsideClick);
return () => document.removeEventListener('pointerdown', closeOnOutsideClick);
}, [editingSubscription, setSubscriptionUrl]);
}, [editingSubscription, hasSubscription, setSubscriptionUrl]);
useEffect(() => {
if (!state?.hasSubscription) return undefined;
@@ -176,7 +183,8 @@ export function ClientOverviewPage({
return (
<div className="client-shell">
<main className="client-panel">
<main className={`client-panel${showPower ? '' : ' is-setup'}`}>
{showPower && (
<section className="client-power-section" aria-labelledby="connection-title">
<button
className="client-power"
@@ -232,6 +240,7 @@ export function ClientOverviewPage({
</div>
</section>
</section>
)}
<div className="client-form">
<div
@@ -257,6 +266,18 @@ export function ClientOverviewPage({
<path d="M21 12a9 9 0 0 0-15.2-6.5L3 8m0-5v5h5M3 12a9 9 0 0 0 15.2 6.5L21 16m0 5v-5h-5" />
</svg>
</button>
<button
className="client-subscription-delete"
type="button"
aria-label="Удалить подписку"
title="Удалить подписку"
disabled={busy}
onClick={onForgetSubscription}
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M4 7h16M9 7V4h6v3m-9 0 1 13h10l1-13M10 11v5M14 11v5" />
</svg>
</button>
</div>
<button
className="client-subscription-domain-button"
@@ -305,7 +326,7 @@ export function ClientOverviewPage({
</form>
</div>
{hasUsage && (
{hasSubscription && hasUsage && (
<section className={`client-usage${usageUpdated ? ' is-updated' : ''}`} aria-label="Статистика подписки">
<span>Использовано</span>
<strong>
@@ -335,7 +356,9 @@ export function ClientOverviewPage({
</section>
)}
<section className="client-servers" aria-label="Серверы">
{hasSubscription && (
<section className="client-servers" aria-label="Выберите сервер">
{!showPower && <span className="client-server-prompt">Выберите сервер</span>}
<div
className={`client-server-grid${serversLeaving ? ' is-leaving' : ''}`}
key={`${serverKey}:${serverRevealVersion}`}
@@ -367,6 +390,7 @@ export function ClientOverviewPage({
})}
</div>
</section>
)}
</div>
</main>