feat(cluster): the server pills become the per-server switch
The colour already said connected; the word beside it said it again, in the widest part of a row that has to hold five servers. It goes, and the pills earn the job nothing else in the app had: reaching ONE cluster without opening Settings. Click connects or drops that session — a connecting one included, so a server retrying into a dead host can be stopped. State, retry count, address and last error move into the tooltip, where they cost no width.
This commit is contained in:
+22
-7
@@ -27,7 +27,7 @@ import {
|
||||
GetTunerGeniusStatus, GetTunerGeniusSettings, TunerGeniusAutotune, TunerGeniusSetBypass, TunerGeniusSetOperate, TunerGeniusActivate,
|
||||
GetScpStatus, ScpLookup,
|
||||
OpenExternalURL,
|
||||
ConnectAllClusters, DisconnectAllClusters, GetClusterStatus, SendClusterCommand,
|
||||
ConnectAllClusters, DisconnectAllClusters, ConnectClusterServer, DisconnectClusterServer, GetClusterStatus, SendClusterCommand,
|
||||
ListClusterServers, ClusterSpotStatuses, SendClusterSpot,
|
||||
GetCATSettings, PTTHotkeyDown, PTTHotkeyUp,
|
||||
GetSolarData,
|
||||
@@ -8133,22 +8133,37 @@ export default function App() {
|
||||
const isMaster = clusterServers
|
||||
.filter((x) => x.enabled)
|
||||
.sort((a, b) => a.sort_order - b.sort_order)[0]?.id === s.server_id;
|
||||
// The colour already says the state, so the word beside it was
|
||||
// saying it twice — and the pills are the only place a single
|
||||
// cluster can be reached without opening Settings. Clicking one
|
||||
// now drops or reopens that session; everything the word used
|
||||
// to carry (state, retries, last error, address) moves into the
|
||||
// tooltip, where it costs no width.
|
||||
const up = s.state === 'connected';
|
||||
const busy = s.state === 'connecting' || s.state === 'reconnecting';
|
||||
return (
|
||||
<span
|
||||
<button
|
||||
key={s.server_id}
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
try {
|
||||
if (up || busy) await DisconnectClusterServer(s.server_id);
|
||||
else await ConnectClusterServer(s.server_id);
|
||||
} catch (e: any) { setError(String(e?.message ?? e)); }
|
||||
await reloadClusterMeta();
|
||||
}}
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold border',
|
||||
'inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-semibold border transition-opacity hover:opacity-80',
|
||||
s.state === 'connected' ? 'bg-success-muted text-success-muted-foreground border-success-border' :
|
||||
s.state === 'connecting' || s.state === 'reconnecting' ? 'bg-warning-muted text-warning-muted-foreground border-warning-border' :
|
||||
busy ? 'bg-warning-muted text-warning-muted-foreground border-warning-border' :
|
||||
s.state === 'error' ? 'bg-danger-muted text-danger-muted-foreground border-danger-border' :
|
||||
'bg-muted text-muted-foreground border-border',
|
||||
)}
|
||||
title={`${s.host}:${s.port}${s.error ? ' — ' + s.error : ''}`}
|
||||
title={`${s.name} — ${s.state.toUpperCase()}${s.retries ? ` #${s.retries}` : ''} · ${s.host}:${s.port}${s.error ? ' — ' + s.error : ''}\n${up || busy ? t('clu.pillDisconnect') : t('clu.pillConnect')}`}
|
||||
>
|
||||
{isMaster && <span className="text-warning" title="Master (commands go here)">★</span>}
|
||||
{s.name}
|
||||
<span className="opacity-60 text-[9px] ml-0.5">{s.state.toUpperCase()}{s.retries ? ` #${s.retries}` : ''}</span>
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
<div className="flex-1" />
|
||||
|
||||
Reference in New Issue
Block a user