Skip to content

Port the web sound-wave recording bar to the mobile composer - #2034

Merged
SawyerHood merged 1 commit into
mainfrom
bb/improve-mobile-speech-to-text-indicator-thr_6hhbjy69em
Aug 20, 2026
Merged

SawyerHood merged 1 commit into
mainfrom
bb/improve-mobile-speech-to-text-indicator-thr_6hhbjy69em

Conversation

@SawyerHood

Copy link
Copy Markdown
Collaborator

What was wrong

The mobile composer's voice bar (apps/mobile/src/composer/VoiceBar.tsx) showed a red dot, a "Listening…" label, and an elapsed timer. It gave no live audio feedback and did not look like the web VoiceRecordingBar, which draws scrolling sound-wave bars from the microphone level.

What changed

  • apps/mobile/src/composer/voice-waveform-model.ts (new): pure port of the web WaveformVisualizer math. meteringToAmplitude converts expo-audio metering (dBFS) to a bar amplitude with the same noise floor, gain, and gamma as the web RMS path; plus the scrolling bar buffer and the SVG path builder.
  • apps/mobile/src/composer/VoiceWaveform.tsx (new): draws the bars as one react-native-svg path (3px bars, 2px gaps, round caps, newest at the right, oldest fading on the left via a gradient stroke). Samples readLevel() at ~30 Hz while active, freezes when inactive, shows flat idle bars under reduce-motion.
  • apps/mobile/src/composer/VoiceBar.tsx: web layout — round ghost cancel · waveform · round primary confirm. While transcribing the bars freeze and breathe (the animate-shine-icon stand-in) and the confirm button shows a spinner.
  • apps/mobile/src/composer/useComposerVoice.ts: records with isMeteringEnabled: true and exposes readLevel(); the elapsed-seconds ticker is removed.
  • apps/mobile/app/dev/ui.tsx: a "Voice bar (synthetic levels)" gallery section so the bar can be exercised without a mic.

No wire changes.

How you verified

  • New voice-waveform-model.test.ts (dB mapping floor/clamp/monotonic, scroll buffer, path geometry). pnpm exec turbo run test typecheck lint --filter=@bb/mobile pass.
  • iOS Simulator (iPhone 17 Pro) through the dev client and the UI gallery: recording scrolls right→left with the left-edge fade; Check → transcribing freezes and breathes with a spinner; X → recording resumes. Checked dark and light.

Fixes #

AGENT GENERATED: by Claude Opus 5

The mobile voice bar showed a red dot, a label, and a timer. The web
VoiceRecordingBar shows live scrolling sound-wave bars. This ports that
waveform to React Native (expo-audio metering → an SVG path) and matches
the web layout: cancel · waveform · confirm, with the bars frozen and
breathing while transcribing.

Co-Authored-By: Claude <noreply@anthropic.com>

@bb-slop-cop bb-slop-cop Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 SLOP COP 🚨 · review

I am the Slop Cop. I am reviewing this change for security, code quality, performance, architecture, and end-to-end behavior.

@SawyerHood
SawyerHood merged commit f4ab03f into main Aug 20, 2026
13 checks passed
@SawyerHood
SawyerHood deleted the bb/improve-mobile-speech-to-text-indicator-thr_6hhbjy69em branch August 20, 2026 14:37
opacity.set(withTiming(1, { duration: 150 }));
return;
}
opacity.set(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 slopcop/review — Respect the system Reduce Motion setting.

The waveform stops under Reduce Motion, but this infinite opacity loop still runs during transcription.

The web source also disables its shine animation under prefers-reduced-motion.

Use useReducedMotion() here, and keep opacity at 1 when the setting is active.

@bb-slop-cop bb-slop-cop Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 SLOP COP 🚨 · review

Plain English summary: This pull request replaces the mobile recording timer with a live sound-wave display. The display freezes during transcription.

I found one medium issue. The transcription breath animation ignores the user's Reduce Motion setting. I left an inline comment on the animation.

I found no security or privacy issue. Microphone permission, audio upload, cancellation, data storage, and SVG input stay within existing boundaries.

The 33 ms sample loop has bounded work and correct cleanup. I found no other performance or resource problem.

The mobile model repeats waveform constants and RMS shaping code from the web app. A future refactor can move that neutral math into @bb/core-ui.

The canvas, SVG, Expo metering, and audio-source code must stay in their platform apps. I do not consider the duplication a merge blocker.

Validation passed:

  • The mobile typecheck passed.
  • The mobile lint task passed.
  • All 821 mobile tests passed across 120 files.
  • The iOS Expo bundle completed with 8,777 modules.
  • All current GitHub checks passed. GitHub skipped the iOS simulator flow.

I could not run a native end-to-end flow. The simulator had no BB app, and Maestro was not installed.

Doobie controls browser documents and cannot control this React Native view. The new showcase exists only in the native UI gallery.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant