Skip to content

[SAAS-19849] Update audio recording widget UX #3768

Open
avazirna wants to merge 8 commits into
masterfrom
saas-19849_audio-recording-ux-changes
Open

[SAAS-19849] Update audio recording widget UX #3768
avazirna wants to merge 8 commits into
masterfrom
saas-19849_audio-recording-ux-changes

Conversation

@avazirna

@avazirna avazirna commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Stacked PR — base branch is saas-19792_audio-recording-ui-revamp, not master. Review/merge that one first.

Product Description

Two recorder UX changes from SAAS-19849 (short-recording flow):

  • Direct start — the recorder begins recording immediately when opened (no intermediate "tap to record" step).
  • Direct stop & save — stopping a recording finalizes and saves it straight away, removing the in-dialog playback/confirm step. Playback now happens in the audio widget itself.
Before After
before_audio_recording.mp4
after_ux_changes.mp4

Technical Summary

Implements SAAS-19849. All changes are in RecordingFragment.java:

  • Lifecycle split — extract resource caching into initMediaResources() and move the reload-vs-start decision into onViewCreated.
  • Auto-start — start recording on open when there's no existing recording, gated on savedInstanceState == null so a configuration-change recreation doesn't re-trigger a recording.
  • Save on stopstopRecording(boolean shouldSave); stopping a non-pausable recording saves and dismisses directly. The flag lets the Save-from-paused path stop without re-triggering save.
  • Dead-code removal — the post-stop playback transition was the only entry into the fragment's own playback path, so playAudio/pause/resume/reset, the MediaPlayer field, and the unused MediaPlayer/Uri imports are now removed (playback lives in CommCareAudioWidget).

Safety Assurance

Safety story

Scoped to the recorder dialog; no data-model/storage changes. AudioRecordingService.stopRecording() is synchronous (MediaRecorder.stop() blocks until the file is finalized), so save-on-stop reads a fully-written file.

Automated test coverage

No automated tests added (UI flow).

Labels and Review

  • Manual QA / RELEASES.md updated as needed
  • Major-change communication via RELEASES.md if needed
  • Risk label set correctly
  • Reviewers appropriate for risk level

avazirna and others added 4 commits June 19, 2026 00:04
Begin recording immediately when the recorder opens without an existing recording, removing the intermediate tap-to-record step. Gated on savedInstanceState == null so a configuration-change recreation doesn't re-trigger a new recording.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stopping now finalizes and saves directly, removing the intermediate playback step. stopRecording takes a shouldSave flag so Save-from-paused stops without re-triggering save.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removing the post-stop playback transition left the recorder fragment's own playback path unreachable (playAudio/pause/resume/reset, the MediaPlayer field, and the onDismiss release were all circularly dead). Playback now happens in CommCareAudioWidget. Drops the dead methods and the now-unused MediaPlayer/Uri imports.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avazirna avazirna self-assigned this Jun 19, 2026
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 25.95%. Comparing base (ef24f5b) to head (de18937).
⚠️ Report is 69 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##             master    #3768   +/-   ##
=========================================
  Coverage     25.94%   25.95%           
  Complexity     4431     4431           
=========================================
  Files           961      961           
  Lines         57618    57604   -14     
  Branches       6869     6864    -5     
=========================================
  Hits          14951    14951           
+ Misses        40829    40814   -15     
- Partials       1838     1839    +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@avazirna avazirna changed the title Auto-start recording and save directly on stop [SAAS-19849] Update audio recording widget UX Jun 23, 2026
@avazirna avazirna marked this pull request as ready for review June 23, 2026 11:23
Adds an upload-artifact step (gated on failure()) that publishes the testCommcareDebug HTML report so failing unit tests can be inspected from the run's artifacts.

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

@conroy-ricketts conroy-ricketts 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.

Out of curiosity, what does the UI look like after a recording is deleted?

Comment on lines +96 to +103
- name: Upload unit test report
if: ${{ failure() }}
uses: actions/upload-artifact@v6
with:
name: unit-test-report
path: commcare-android/app/build/reports/tests/testCommcareDebugUnitTest
if-no-files-found: warn
retention-days: 14

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.

Was this added by mistake?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The build failed a couple of times because of one of the unit tests, UpdateActivityTest.invalidUpdateTest(), and I added this to get more info around the error. But after that addition, the builds were successful. I think this is a good addition but not in the scope of this PR, so the plan is to PR this separately.

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.

think a 3 day retention should be sufficient here, one can always re-trigger the build to get this info again.

shubham1g5
shubham1g5 previously approved these changes Jun 25, 2026

@shubham1g5 shubham1g5 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.

looks good, would be nice to add safety story around phone rotation on this change.

Base automatically changed from saas-19792_audio-recording-ui-revamp to master June 26, 2026 08:07
@avazirna avazirna dismissed shubham1g5’s stale review June 26, 2026 08:07

The base branch was changed.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates the Android PR workflow to upload the unit test report on failure. It also extends release notes with audio recording revamp entries and changes RecordingFragment to initialize media resources during view creation, remove in-fragment playback state, and make stopping a recording optionally save the file through stopRecording(boolean).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • OrangeAndGreen
  • Jignesh-dimagi
  • shubham1g5
  • conroy-ricketts
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately reflects the audio recording UX update in this PR.
Description check ✅ Passed The description includes all required template sections and covers product, technical, safety, tests, and review notes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch saas-19849_audio-recording-ux-changes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/org/commcare/views/widgets/RecordingFragment.java (1)

280-310: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve a discard path for new recordings.

At Line 280 and Line 386, both stop flows now commit immediately. Because recording also makes the dialog non-cancelable (Line 231) and hides discardRecording during capture (Line 289), a fresh recorder session no longer has a way to back out without saving unwanted audio. CommCareAudioWidget.onRecordingCompletion() (app/src/org/commcare/views/widgets/CommCareAudioWidget.java:153-162) will then promote that file to the field value as soon as it exists.

Also applies to: 384-391

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/org/commcare/views/widgets/RecordingFragment.java` around lines 280 -
310, The stop-recording flow in RecordingFragment is always finalizing the
audio, which removes the ability to back out of a new recording session; update
stopRecording(boolean shouldSave) and the related stop paths so a discard option
still exists for fresh recordings. Keep the discardRecording / negative-action
behavior available when starting or stopping a new capture, and only call
saveRecording() for explicit save actions so
CommCareAudioWidget.onRecordingCompletion() does not promote unwanted audio
automatically.
🧹 Nitpick comments (1)
.github/workflows/commcare-android-pr-workflow.yml (1)

96-103: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider reducing retention from 14 days to 3 days.

The retention-days: 14 is significantly longer than other artifacts in this workflow (qaAutomation APKs use 3 days). A previous reviewer noted that 3 days should be sufficient since one can re-trigger the build to get fresh artifacts. Longer retention consumes more storage quota without proportional value for ephemeral test reports.

-          retention-days: 14
+          retention-days: 3
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/commcare-android-pr-workflow.yml around lines 96 - 103,
Reduce the artifact retention for the unit test report upload in the workflow to
match the shorter lifespan used elsewhere. Update the Upload unit test report
step in commcare-android-pr-workflow.yml so the actions/upload-artifact@v6
configuration uses a 3-day retention instead of 14 days.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/org/commcare/views/widgets/RecordingFragment.java`:
- Around line 137-139: The auto-start path in RecordingFragment still leaves the
mic button active while startRecording() is being triggered, which allows a
second tap to re-enter the same recording session through toggleRecording and
AudioRecordingService.onStartCommand. Update RecordingFragment’s auto-start flow
so the mic control is switched into a disabled/loading state before calling
startRecording(), and keep it non-interactive until the recording startup
completes to prevent duplicate start requests.

---

Outside diff comments:
In `@app/src/org/commcare/views/widgets/RecordingFragment.java`:
- Around line 280-310: The stop-recording flow in RecordingFragment is always
finalizing the audio, which removes the ability to back out of a new recording
session; update stopRecording(boolean shouldSave) and the related stop paths so
a discard option still exists for fresh recordings. Keep the discardRecording /
negative-action behavior available when starting or stopping a new capture, and
only call saveRecording() for explicit save actions so
CommCareAudioWidget.onRecordingCompletion() does not promote unwanted audio
automatically.

---

Nitpick comments:
In @.github/workflows/commcare-android-pr-workflow.yml:
- Around line 96-103: Reduce the artifact retention for the unit test report
upload in the workflow to match the shorter lifespan used elsewhere. Update the
Upload unit test report step in commcare-android-pr-workflow.yml so the
actions/upload-artifact@v6 configuration uses a 3-day retention instead of 14
days.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3443268f-6cec-4914-bd0b-a71a5617c1ae

📥 Commits

Reviewing files that changed from the base of the PR and between f309d4a and de18937.

📒 Files selected for processing (3)
  • .github/workflows/commcare-android-pr-workflow.yml
  • RELEASES.md
  • app/src/org/commcare/views/widgets/RecordingFragment.java

Comment on lines +137 to 139
} else if (savedInstanceState == null) {
startRecording();
}

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Disable the mic before the auto-start call.

At Line 137, the fragment calls startRecording() while toggleRecording is still wired to startRecording(). A user tap in that bind window issues a second start request, and AudioRecordingService.onStartCommand() (app/src/org/commcare/views/widgets/AudioRecordingService.java:26-60) re-enters the recorder start path for the same session. Flip the button into a disabled/loading state before auto-starting so this path can only run once.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/org/commcare/views/widgets/RecordingFragment.java` around lines 137 -
139, The auto-start path in RecordingFragment still leaves the mic button active
while startRecording() is being triggered, which allows a second tap to re-enter
the same recording session through toggleRecording and
AudioRecordingService.onStartCommand. Update RecordingFragment’s auto-start flow
so the mic control is switched into a disabled/loading state before calling
startRecording(), and keep it non-interactive until the recording startup
completes to prevent duplicate start requests.

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.

3 participants