feat: Emberwake, Crucible phases, Linux agent, musical dashboard, e2e

Emberwake spread/waterhole UI, campaign DB, spread handler, spread-kit web publisher, and SPREAD_TECHNIQUES doc. Crucible Phase A-C: expanded ops, port-forward matrix, remote dir browser, crucible help/tests.

Linux agent hardening: credential vault, persistence audit, firewall/defender deploy, SMB spread status, CPU stats, screenshots/crypt/file-ops split. Docker compose and agent/server images with e2e validation script and docs.

Musical dashboard: ambient music player, hover SFX, SoundContext/AmbientMusicContext, steampunk polish. Public builds API, dropper handler updates, SessionGate and fleet UX. README and PROBLEMS.md refresh.
This commit is contained in:
AetherForge
2026-06-04 21:53:31 -07:00
parent 8466c7aa9b
commit 1551bd5dad
138 changed files with 7523 additions and 489 deletions

View File

@@ -19,6 +19,8 @@ import NeonCard from '../components/NeonCard/NeonCard';
import FleetTasksPanel from '../components/Fleet/FleetTasksPanel';
import { AuditLogStrip } from '../components/Fleet/FleetOpsWidgets';
import { useSound } from '../context/SoundContext';
import { useAmbientMusic } from '../context/AmbientMusicContext';
import { AMBIENT_MUSIC_SRC } from '../audio/ambientMusic';
import { useVisualEffects } from '../context/VisualEffectsContext';
import './Pages.css';
@@ -46,7 +48,19 @@ export function deepMerge<T extends object>(base: T, override: Partial<T>): T {
}
export default function SettingsPage() {
const { enabled: sfxEnabled, volume: sfxVolume, setEnabled: setSfxEnabled, setVolume: setSfxVolume, preview: previewSfx } = useSound();
const {
enabled: sfxEnabled,
volume: sfxVolume,
hoverEnabled,
hoverVolume,
setEnabled: setSfxEnabled,
setVolume: setSfxVolume,
setHoverEnabled,
setHoverVolume,
preview: previewSfx,
previewHover,
} = useSound();
const { enabled: bgmEnabled, volume: bgmVolume, setEnabled: setBgmEnabled, setVolume: setBgmVolume } = useAmbientMusic();
const { glowParticles, setGlowParticles } = useVisualEffects();
const [config, setConfig] = useState<ServerConfig | null>(null);
const [serverInfo, setServerInfo] = useState<{ suggested_url: string; local_ips: string[] } | null>(null);
@@ -490,6 +504,82 @@ export default function SettingsPage() {
Preview share
</button>
</div>
<hr style={{ border: 'none', borderTop: '1px solid var(--border-dim)', margin: '1.25rem 0' }} />
<h3 className="font-tech" style={{ fontSize: '0.85rem', marginBottom: '0.35rem' }}>Hover highlight sounds</h3>
<p className="section-desc" style={{ marginBottom: '0.75rem' }}>
Subtle dubstep-style blips when hovering buttons, cards, nav links, and fleet rows. Debounced so rapid
mouse movement stays quiet. Muted when click sounds are off.
</p>
<div className="form-group checkbox-group">
<label className="checkbox-label">
<input
type="checkbox"
className="checkbox"
checked={hoverEnabled}
disabled={!sfxEnabled}
onChange={(e) => setHoverEnabled(e.target.checked)}
/>
<span>Enable hover highlight sounds</span>
</label>
</div>
<div className="form-group">
<label htmlFor="cfg-hover-volume" className="label">
Hover volume ({Math.round(hoverVolume * 100)}%)
</label>
<input
id="cfg-hover-volume"
type="range"
className="input"
min={0}
max={100}
step={5}
value={Math.round(hoverVolume * 100)}
disabled={!sfxEnabled || !hoverEnabled}
onChange={(e) => setHoverVolume(parseInt(e.target.value, 10) / 100)}
/>
</div>
<button
type="button"
className="btn btn-outline btn-sm"
disabled={!sfxEnabled || !hoverEnabled}
onClick={previewHover}
>
Preview hover
</button>
<hr style={{ border: 'none', borderTop: '1px solid var(--border-dim)', margin: '1.25rem 0' }} />
<h3 className="font-tech" style={{ fontSize: '0.85rem', marginBottom: '0.35rem' }}>Background music</h3>
<p className="section-desc" style={{ marginBottom: '0.75rem' }}>
Optional looping ambient track served from <code className="mono-sm">{AMBIENT_MUSIC_SRC}</code>. Use the
mini player in the bottom-right corner on any page, or enable here. Defaults off browsers block autoplay
until you press play or toggle this on.
</p>
<div className="form-group checkbox-group">
<label className="checkbox-label">
<input
type="checkbox"
className="checkbox"
checked={bgmEnabled}
onChange={(e) => setBgmEnabled(e.target.checked)}
/>
<span>Enable background music</span>
</label>
</div>
<div className="form-group">
<label htmlFor="cfg-bgm-volume" className="label">
Music volume ({Math.round(bgmVolume * 100)}%)
</label>
<input
id="cfg-bgm-volume"
type="range"
className="input"
min={0}
max={100}
step={5}
value={Math.round(bgmVolume * 100)}
disabled={!bgmEnabled}
onChange={(e) => setBgmVolume(parseInt(e.target.value, 10) / 100)}
/>
</div>
</NeonCard>
<NeonCard accent="brass" className="settings-section">