Repository navigation
Gate audio controls to desktop only via DesktopAudioControl - #45
Merged
Merged
Conversation
Audio is a desktop-only enrichment. Mobile browsers gate the Web Audio API behind autoplay/gesture rules (and a suspended AudioContext) that a single "hear it" tap can't reliably satisfy, so on a phone the control taps to silence — a dead button that reads as broken. Rather than chase per-device resume hacks, don't offer the affordance where it can't deliver: the visuals carry each module on mobile, and audio stays a desktop feature. Add one shared gate, <DesktopAudioControl>, keyed off the same `lg` breakpoint the overlay-drawer layout uses (useIsCompactViewport), and route the three audio buttons (rotating phasor, analog modulation, quantization) through it. On desktop the gate renders a Fragment, leaving the button a direct child of its flex row exactly as before — desktop layout and behavior are untouched. Below `lg` it renders nothing, and the flex gap collapses cleanly (no orphaned spacing). The audio hooks build their AudioContext lazily on the button press, so a hidden button never initializes audio — nothing audio-related runs on mobile. A guard test scans the modules and fails if one triggers Web Audio without routing through the gate, the way <Slider> guards against raw range inputs — so a new audio module can't reintroduce a dead mobile button by forgetting to. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H3H6X9cPYBPSp7pVFQMNca
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 26d6683ea0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Hiding the trigger wasn't enough. If a listener starts audio on desktop and then crosses below `lg` — dragging the window narrow, rotating a tablet, split-screen — the gate unmounted only the button, while the audio hook lives on in the parent module and keeps the oscillator/buffer running. The result: sound with no visible way to stop it until the viewport grows again or the module unmounts. Keep "no control" and "no sound" in lockstep. <DesktopAudioControl> gains an optional onSuppress callback and fires it as it crosses into compact; each module passes its audio stop (the rotating phasor also clears its local playing flag so the button reads correctly if the viewport grows back). Desktop is still untouched — onSuppress only fires on the transition into compact, never at `lg+`. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H3H6X9cPYBPSp7pVFQMNca
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Audio playback is a desktop-only enrichment in Wavefront — mobile browsers' autoplay and gesture rules make a single "hear it" tap unreliable, leaving users with a dead button that reads as broken. This PR introduces a
<DesktopAudioControl>wrapper that suppresses audio controls below thelgbreakpoint, ensuring the affordance only appears where it can deliver.Changes
New component:
src/audio/DesktopAudioControl.tsx— A simple gate that renders its children onlg+and returnsnullbelowlg, keyed off the same breakpoint as the overlay-drawer layout (useIsCompactViewport). On desktop, it wraps the control in a Fragment, leaving layout and behavior untouched. Audio hooks build their AudioContext lazily on button press, so a hidden button never initializes audio — nothing audio-related runs on mobile.New test:
src/audio/DesktopAudioControl.test.tsx— Verifies the component renders on desktop and suppresses on mobile. Includes a structural guard that scans all modules insrc/modules/to enforce that every module using a Web Audio playback hook (@/audio/use*) also gates it through<DesktopAudioControl>. This prevents future audio modules from reintroducing a dead mobile button by forgetting the gate.Updated three modules to wrap their audio controls:
src/modules/signal-chain-sdr/quantization/QuantizationModule.tsxsrc/modules/direction-finding/rotating-phasor/PhasorModule.tsxsrc/modules/modulations-and-waveforms/analog/AnalogModule.tsxImplementation notes
display: none, so the control is never mounted on mobile and audio initialization never runs.lg+.https://claude.ai/code/session_01H3H6X9cPYBPSp7pVFQMNca