Remove fleet lobby follow notifications

This commit is contained in:
2026-09-21 19:33:57 -04:00
parent e448457d58
commit f875260b7e
5 changed files with 10 additions and 123 deletions
+4 -34
View File
@@ -9,7 +9,7 @@
import SectionHeader from '$ui/components/primitives/SectionHeader.svelte';
import EmptyState from '$ui/components/primitives/EmptyState.svelte';
import StatusPip from '$ui/components/primitives/StatusPip.svelte';
import { fleet, fleetServers, fleetError, fleetRefreshing, fleetIntegrations, refreshFleet, lobbyWatches, followLobby, cancelWatch } from '$ui/stores/fleet.js';
import { fleet, fleetServers, fleetError, fleetRefreshing, fleetIntegrations, refreshFleet } from '$ui/stores/fleet.js';
import { telemetryByServer, uiNow } from '$ui/stores/servers.js';
import { currentRound, fleetIdentity, freshServer, matchesFleet } from '$lib/fleet-overview.js';
import type { FleetServer, FleetFilter, FleetSort } from '$lib/fleet-overview.js';
@@ -119,16 +119,6 @@
function launch(selection: { game: ZombieGame; slug: string } | null = null) {
initialGame = selection?.game ?? 't5'; initialMapSlug = selection?.slug ?? ''; deployOpen = true;
}
function watch(server: FleetServer, event: Event) {
const input = event.currentTarget as HTMLSelectElement;
const value = input.value;
input.value = '';
if (value === 'empty' || value === 'online') followLobby(server.name, value);
else {
const operation = activeOperations.find(op => op.key === value);
if (operation) followLobby(server.name, 'operation', operation);
}
}
function resetFilters() { query = ''; filter = 'all'; game = ''; }
</script>
@@ -183,18 +173,9 @@
</a>
{/if}
{#if activeOperations.length || $lobbyWatches.length}
{#if activeOperations.length}
<details id="fleet-operations" class="operations" bind:open={operationsOpen}>
<summary>Activity · {activeOperations.length} operations{ $lobbyWatches.length ? ` · ${$lobbyWatches.length} lobby watches` : ''}{attentionOperations.length ? ` · ${attentionOperations.length} need attention` : ''}</summary>
{#if $lobbyWatches.length}
<div class="watches" aria-label="Lobby watches">
<div><strong>Following {$lobbyWatches.length} {$lobbyWatches.length === 1 ? 'condition' : 'conditions'}</strong><span class="hint">Notifications stay active as you navigate. Keep this app open.</span></div>
{#each $lobbyWatches as item (item.id)}
<button title="Cancel this watch" onclick={() => cancelWatch(item.id)} aria-label="Cancel {item.kind} watch for {serverTitle(item.server)}">{serverTitle(item.server)} · {item.kind === 'empty' ? 'when empty' : item.kind === 'online' ? 'when online' : 'when complete'} ×</button>
{/each}
</div>
{/if}
<summary>Activity · {activeOperations.length} operations{attentionOperations.length ? ` · ${attentionOperations.length} need attention` : ''}</summary>
<div class="operation-list">{#each activeOperations as operation (operation.key)}
<a href={operation.href} class:issue={operation.state === 'attention'}><strong>{serverTitle(operation.server)}</strong><span>{operation.label}</span><small>{operation.detail}</small></a>
{/each}</div>
@@ -269,14 +250,6 @@
{#snippet serverActions(server: FleetServer)}
<button class="pin" class:selected={pinned.includes(server.name)} aria-pressed={pinned.includes(server.name)} aria-label="Pin {serverTitle(server.name)}" onclick={() => togglePin(server.name)}>{pinned.includes(server.name) ? '★ Pinned' : '☆ Pin'}</button>
<select class="watch-select" aria-label="Follow {serverTitle(server.name)}" onchange={event => watch(server, event)}>
<option value="">Follow lobby…</option>
<option value="empty" disabled={freshServer(server, $uiNow) && server.last_players === 0}>Tell me when it’s empty</option>
<option value="online" disabled={freshServer(server, $uiNow)}>Tell me when it’s online</option>
{#each activeOperations.filter(op => op.server === server.name && (op.kind === 'campaign' || op.kind === 'deployment') && op.state === 'active') as operation (operation.key)}
<option value={operation.key}>When complete: {operation.label}</option>
{/each}
</select>
{/snippet}
<style>
@@ -319,7 +292,7 @@
input::placeholder { color: var(--text-secondary); }
.filter-row, .result-count { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.chips, .view-toggle { display: flex; gap: 6px; flex-wrap: wrap; }
.chips button, .view-toggle button, .pin, .watches button { background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-md); padding: 8px 12px; color: var(--text-secondary); font-size: 12px; }
.chips button, .view-toggle button, .pin { background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-md); padding: 8px 12px; color: var(--text-secondary); font-size: 12px; }
.chips button span { margin-left: 8px; opacity: .75; font-variant-numeric: tabular-nums; }
button.selected { background: color-mix(in srgb, var(--accent-primary) 15%, var(--surface)); color: var(--accent-primary-hover); border-color: color-mix(in srgb, var(--accent-primary) 50%, transparent); }
.result-count { justify-content: flex-start; font-size: 12px; color: var(--text-secondary); }
@@ -334,7 +307,6 @@
.server-tile :global(.card) { border-radius: 0; }
.tile-actions { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 12px 16px; border-top: 1px solid var(--border-subtle); }
.pin { white-space: nowrap; }
.watch-select { font-size: 12px; min-height: 36px; min-width: 0; width: 145px; padding: 6px; }
.server-operations { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px; font-size: 12px; }
.server-operations a { text-decoration: none; color: var(--accent-primary-hover); overflow-wrap: anywhere; }
.server-operations small { display: block; margin-top: 5px; color: var(--text-secondary); }
@@ -344,8 +316,6 @@
.operation-list { display: grid; gap: 10px; margin-top: 16px; }
.operation-list a { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 20px; padding: 12px; text-decoration: none; background: var(--surface); border-radius: var(--radius-md); color: var(--text-primary); }
.operation-list small { grid-column: 1 / -1; color: var(--text-secondary); overflow-wrap: anywhere; }
.watches { margin-top: 16px; display: flex; flex-wrap: wrap; align-items: center; gap: 10px; font-size: 13px; }
.watches > div { margin-right: auto; }
.error { padding: 16px; border: 1px solid var(--state-warning); border-radius: var(--radius-md); font-size: 13px; line-height: 1.7; }
.error button { margin-left: 8px; }
.loading { padding: 70px 20px; text-align: center; color: var(--text-secondary); background: var(--surface); border-radius: var(--radius-lg); }