Unify UI workflows and streamline fleet management
This commit is contained in:
@@ -10,6 +10,7 @@ export const fleet = writable<{ servers: FleetServer[]; operations: FleetOperati
|
||||
});
|
||||
export const fleetError = writable('');
|
||||
export const fleetRefreshing = writable(false);
|
||||
export const fleetIntegrations = writable<{ rcon: boolean; komodo: boolean; rconTimeoutMs: number; defaultRconHost: string } | null>(null);
|
||||
export const lobbyWatches = writable<LobbyWatch[]>([]);
|
||||
|
||||
export const fleetServers = derived([fleet, statusByServer, statusReceivedAt], ([snapshot, live, received]) =>
|
||||
@@ -17,7 +18,7 @@ export const fleetServers = derived([fleet, statusByServer, statusReceivedAt], (
|
||||
const status = received > snapshot.receivedAt ? live.get(server.name) : undefined;
|
||||
return status ? { ...server, last_players: status.players, last_map: status.map,
|
||||
last_gametype: status.gametype, last_seen_at: status.lastSeenAt, last_error: status.lastError,
|
||||
roster: status.roster, health: status.health, active_since: status.activeSince,
|
||||
roster: status.roster, health: status.health, endpoint: status.endpoint, replySnippet: status.replySnippet, active_since: status.activeSince,
|
||||
inactive_since: status.inactiveSince, game_started_at: status.gameStartedAt,
|
||||
game_ended_at: status.gameEndedAt } : server;
|
||||
}));
|
||||
@@ -39,6 +40,7 @@ export function refreshFleet(): Promise<void> {
|
||||
if (responses.some(response => !response.ok)) throw new Error('Could not refresh Fleet. Retrying automatically.');
|
||||
const [servers, operations] = await Promise.all(responses.map(response => response.json()));
|
||||
fleetError.set('');
|
||||
fleetIntegrations.set(servers.integrations);
|
||||
fleet.set({ servers: servers.servers, operations: operations.operations, receivedAt: requestedAt });
|
||||
} catch (error) {
|
||||
fleetError.set(error instanceof Error && error.name !== 'AbortError'
|
||||
@@ -79,7 +81,9 @@ export function startFleetMonitor(): () => void {
|
||||
try { sessionStorage.setItem('electric-cherry:lobby-watches', JSON.stringify(watches)); } catch { /* Optional storage. */ }
|
||||
});
|
||||
void refreshFleet();
|
||||
const interval = setInterval(() => void refreshFleet(), 10_000);
|
||||
const interval = setInterval(() => {
|
||||
if (document.visibilityState !== 'hidden' || get(lobbyWatches).length) void refreshFleet();
|
||||
}, 10_000);
|
||||
const onFocus = () => { if (document.visibilityState === 'visible') void refreshFleet(); };
|
||||
document.addEventListener('visibilitychange', onFocus);
|
||||
const check = () => {
|
||||
|
||||
@@ -23,7 +23,7 @@ function updateDeployment(id: string, mutate: (d: PipelineDeployment) => void):
|
||||
});
|
||||
}
|
||||
|
||||
export function startPipelineStream(): void {
|
||||
export function startPipelineStream(): (() => void) | undefined {
|
||||
if (!browser || source) return;
|
||||
source = new EventSource('/api/events/pipeline');
|
||||
|
||||
@@ -49,4 +49,5 @@ export function startPipelineStream(): void {
|
||||
d.servers.set(data.server, { state: data.state, players: data.players, error: data.error });
|
||||
});
|
||||
});
|
||||
return () => { source?.close(); source = null; };
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ let tickInterval: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
let source: EventSource | null = null;
|
||||
|
||||
export function startServerStream(): void {
|
||||
export function startServerStream(): (() => void) | undefined {
|
||||
if (!browser || source) return;
|
||||
source = new EventSource('/api/events/servers');
|
||||
source.addEventListener('server-telemetry', (evt) => {
|
||||
@@ -73,4 +73,5 @@ export function startServerStream(): void {
|
||||
if (tickInterval === null) {
|
||||
tickInterval = setInterval(() => _uiNow.set(Date.now()), 1000);
|
||||
}
|
||||
return () => { source?.close(); source = null; if (tickInterval) clearInterval(tickInterval); tickInterval = null; };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user