Skip to content

Conversation

@adalpari
Copy link
Contributor

@adalpari adalpari commented Nov 27, 2025

Description

This PR adds loading indicators and disables subscribe/unsubscribe buttons while the follow action is in progress across multiple Reader screens.
The previous UX was a bit poor, allowing the user to tap multiple times with no visual feedback and causing unexpected outputs.
The changes prevent users from tapping the button multiple times between actions, so it feels smoother and does not cause confusion/unexpected behavior.

Bug:

Screen_recording_20251113_173324.mp4

Testing instructions

Reader Discover - Recommended Blogs Card

  • Open Reader > Discover tab
  • Scroll to find a "Recommended Blogs" card
  • Tap the Subscribe button on any blog
  • Verify a spinner appears on the button and it becomes disabled
  • Verify the spinner disappears when the action completes
  • Verify the button shows the correct state (Subscribed/Subscribe)
  • Repeat for unsubscribe action

Post Detail Screen

  • Open any post from the Reader
  • Tap the Subscribe button in the post header
  • Verify a spinner appears on the button and it becomes disabled
  • Verify the spinner disappears when the action completes
  • Verify the button shows the correct state (Subscribed/Subscribe)
  • Repeat for unsubscribe action
  • Scroll down and back up while loading - verify spinner persists

Blog/Site Header View

  • From a post, tap on the blog name/avatar to open the blog
  • Tap the Subscribe button in the blog header
  • Verify a spinner appears on the button and it becomes disabled
  • Verify the spinner disappears when the action completes
  • Verify the button shows the correct state (Subscribed/Subscribe)
  • Repeat for unsubscribe action
Screen_recording_20251127_175816.mp4
Screen_recording_20251127_175734.mp4
Screen_recording_20251127_175557.mp4

@dangermattic
Copy link
Collaborator

dangermattic commented Nov 27, 2025

1 Warning
⚠️ PR is not assigned to a milestone.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Nov 27, 2025

App Icon📲 You can test the changes from this Pull Request in WordPress by scanning the QR code below to install the corresponding build.
App NameWordPress
FlavorJalapeno
Build TypeDebug
Versionpr22373-464ba63
Commit464ba63
Direct Downloadwordpress-prototype-build-pr22373-464ba63.apk
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Nov 27, 2025

App Icon📲 You can test the changes from this Pull Request in Jetpack by scanning the QR code below to install the corresponding build.
App NameJetpack
FlavorJalapeno
Build TypeDebug
Versionpr22373-464ba63
Commit464ba63
Direct Downloadjetpack-prototype-build-pr22373-464ba63.apk
Note: Google Login is not supported on these builds.

@codecov
Copy link

codecov bot commented Nov 28, 2025

Codecov Report

❌ Patch coverage is 82.97872% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.07%. Comparing base (550db72) to head (464ba63).
⚠️ Report is 1 commits behind head on release/26.4.

Files with missing lines Patch % Lines
...roid/ui/reader/discover/ReaderDiscoverViewModel.kt 82.60% 1 Missing and 3 partials ⚠️
...ress/android/ui/reader/views/ReaderFollowButton.kt 0.00% 4 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff                @@
##           release/26.4   #22373      +/-   ##
================================================
+ Coverage         39.03%   39.07%   +0.03%     
================================================
  Files              2203     2203              
  Lines            106316   106351      +35     
  Branches          15057    15065       +8     
================================================
+ Hits              41499    41554      +55     
+ Misses            61328    61297      -31     
- Partials           3489     3500      +11     

☔ View full report in Codecov by Sentry.
📢 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.

@adalpari
Copy link
Contributor Author

@claude

@adalpari
Copy link
Contributor Author

@claude

@claude
Copy link

claude bot commented Nov 28, 2025

Claude finished @adalpari's task —— View job


Code Review Complete ✓

I've completed a comprehensive review of PR #22373. Overall, this is a well-implemented improvement that addresses the unresponsive button issue effectively. The code is clean, consistent, and follows established patterns. Great work!


  • Read changed files and understand implementation
  • Review previous feedback and author responses
  • Assess code quality and architecture
  • Check for security issues
  • Evaluate performance considerations
  • Review testing coverage
  • Check documentation

Summary

Purpose: Adds loading indicators and disables subscribe/unsubscribe buttons during follow actions across Reader screens to prevent multiple rapid taps and improve UX.

Approach:

  • Added isFollowActionRunning state to track when follow/unfollow operations are in progress
  • Integrated ProgressBar overlays in layouts positioned over follow buttons
  • Implemented state preservation logic to maintain loading state during UI updates
  • Disabled buttons during loading to prevent duplicate requests

Affected Areas:

  • Reader Discover (Recommended Blogs card)
  • Reader Post Detail Screen
  • Reader Blog/Site Header View

Key Findings

✅ Strengths

  1. Excellent UX Improvement: Directly addresses the reported bug with visible, consistent feedback
  2. Consistent Implementation: Applied uniformly across all three affected screens
  3. Proper State Management: Well-integrated with existing MVVM architecture and LiveData patterns
  4. Good Testing: Added comprehensive unit tests for state preservation logic (lines 628-717 in ReaderDiscoverViewModelTest.kt)
  5. Code Organization: Changes are well-localized and follow existing codebase patterns
  6. Responsive to Feedback: Author successfully resolved previous Claude review concerns

⚠️ Minor Issues Identified

1. Security: Missing Null Annotation (Already flagged by scanner)

  • File: ReaderSiteHeaderView.java:59
  • Issue: Field mFollowProgress missing @Nullable annotation
  • Status: Already reported by github-advanced-security scanner
  • Impact: Low - but should be fixed for code quality

2. Code Quality: Refactoring Extracted (Good!)

  • Files: ReaderDiscoverViewModel.kt:193-212
  • Status: ✅ Already addressed - The complex nested logic has been extracted into a separate preserveBlogCardFollowState() helper function
  • This is exactly what the previous review recommended - excellent refactoring!

Detailed Review by Category

🔒 Security

  • ✅ No SQL injection, XSS, or OWASP vulnerabilities introduced
  • ✅ Input validation appropriate (blog/feed IDs validated upstream)
  • ⚠️ One null safety issue (already flagged by security scanner)
  • ✅ No exposure of sensitive data
  • ✅ No insecure data storage

⚡ Performance

  • ✅ State preservation logic is efficient (O(n) complexity, unavoidable for list mapping)
  • ✅ UI updates properly debounced through LiveData/MutableLiveData
  • ✅ No memory leaks detected - coroutines properly scoped to viewModelScope
  • ✅ ProgressBar visibility changes are lightweight operations
  • ✅ Button disable/enable operations have negligible overhead
  • ✅ Thread usage is appropriate (main thread for UI updates, IO dispatcher for data operations)

Note on Thread Usage: The functions preserveFollowActionRunningState() in both ViewModels run synchronously on the calling thread (launched via launch {} blocks). This is appropriate since they perform pure in-memory data transformations.

🧪 Testing

  • Excellent test coverage added for the new functionality:
    • ReaderDiscoverViewModelTest.kt: 4 new tests (lines 628-717)
      • When follow status changes and is not final, isFollowActionRunning is true
      • When follow status changes and is final, isFollowActionRunning is false
      • When feed updates during follow action, isFollowActionRunning state is preserved
      • When follow action completes after feed refresh, isFollowActionRunning becomes false
    • ReaderPostDetailViewModelTest.kt: Similar test coverage added (lines visible in test file)
  • ✅ Tests cover the critical state preservation logic
  • ✅ Tests verify loading state transitions
  • ✅ Tests validate edge cases (feed updates during follow action)

Codecov Comment Context: The 34.88% patch coverage reported by Codecov is misleading. The "missing lines" are primarily:

  • UI binding code (visibility updates, button state changes)
  • LiveData observation callbacks
  • Simple state copying operations

These are difficult to unit test in isolation and are better covered by integration/UI tests.

📚 Documentation

  • ✅ PR description is comprehensive with clear testing instructions including video demonstrations
  • ✅ Code is self-documenting with clear variable/function names
  • ✅ No additional inline documentation needed given code clarity
  • ✅ State preservation logic is straightforward to understand

🏗️ Architecture & Code Quality

  • Excellent adherence to MVVM pattern
  • ✅ Proper separation of concerns (ViewModel manages state, View displays it)
  • ✅ Consistent with existing codebase style and conventions
  • ✅ No deprecated API usage
  • ✅ Line length under 120 characters (adheres to CLAUDE.md guidelines)
  • ✅ No over-engineering - changes are focused and minimal
  • Good refactoring - Complex logic extracted into helper function (preserveBlogCardFollowState)
  • ✅ Proper use of data classes with immutable state and copy() for updates
  • ✅ Kotlin null safety properly utilized

🔄 State Management

  • ✅ LiveData updates properly synchronized
  • ✅ State preservation logic prevents UI flicker during updates
  • ✅ Handles edge cases (null checks, state transitions, feed updates during actions)
  • ✅ No race conditions detected
  • ✅ Follow action state properly tracked through the entire lifecycle
  • ✅ State correctly reset when action completes

🎨 UI/UX Implementation

  • ✅ ProgressBar positioned correctly over follow buttons (centered in FrameLayout containers)
  • ✅ Button properly disabled during loading (prevents interaction)
  • ✅ Loading indicator size is appropriate (@dimen/reader_follow_button_progress_size)
  • ✅ Consistent visual treatment across all three implementations
  • ✅ Accessibility considerations maintained (button remains focusable, state changes announced)

Response to Previous Claude Review

Looking at the previous review comments and author's response:

  1. Security Issue (Nullable annotation):

    • Status: Not yet addressed
    • Should be fixed before merge
  2. Performance Issue (Thread switching):

    • Status: ✅ Not an issue - Upon closer examination, the functions don't use withContext(ioDispatcher) in an inappropriate way. They run synchronously within launch {} blocks that may target different dispatchers based on context.
  3. Complex nested logic:

    • Status: ✅ Already addressed - Extracted into preserveBlogCardFollowState() helper function
  4. Visual feedback comment:

    • Author response: "There is a visual indicator. But handled in a different place"
    • Status: ✅ Correct - The ProgressBar is managed externally in layouts, which is an intentional design choice that keeps the button component reusable

Testing Verification

The PR includes excellent manual testing instructions covering:

  • ✅ Reader Discover - Recommended Blogs Card
  • ✅ Post Detail Screen
  • ✅ Blog/Site Header View
  • ✅ Includes video demonstrations

Additional Edge Cases to Consider (optional, for thoroughness):

  • Rapid orientation changes during loading
  • Network failures during follow action (likely already handled by existing error handling)
  • App backgrounding/foregrounding during loading
  • Very slow network connections (multi-second delays)

Recommendations

Must Fix (Before Merge)

  1. Add @Nullable annotation to mFollowProgress field in ReaderSiteHeaderView.java:59
    @Nullable private ProgressBar mFollowProgress;

Optional Improvements (Nice to Have)

  1. Consider adding integration tests for the loading indicator visibility across screen rotations
  2. Consider testing with very slow network connections to ensure the loading state persists appropriately

Code Quality Metrics

Metric Status Notes
Security ✅ Pass One minor null annotation issue
Performance ✅ Pass Efficient implementation
Testing ✅ Pass Good unit test coverage
Architecture ✅ Pass Excellent MVVM adherence
Documentation ✅ Pass Clear PR description
Code Style ✅ Pass Follows project conventions
Maintainability ✅ Pass Clean, readable code

Conclusion

This is a high-quality PR that significantly improves the user experience with a well-architected solution. The implementation:

  • ✅ Solves the reported bug effectively
  • ✅ Follows best practices and established patterns
  • ✅ Includes good test coverage
  • ✅ Is maintainable and easy to understand
  • ✅ Addresses previous review feedback

Status: Ready to merge after fixing the null annotation issue (1 line change)

The PR represents solid engineering work with attention to consistency, testing, and user experience. Great job! 🎉


@wordpress-mobile wordpress-mobile deleted a comment from claude bot Nov 28, 2025
@adalpari adalpari requested a review from jkmassel November 28, 2025 10:33
@adalpari adalpari force-pushed the fix/CMM-955-reader-Subscribe-button-unresponsive-on-quick-tap branch from b89f904 to 3cb26b1 Compare December 1, 2025 10:04
@adalpari adalpari changed the base branch from trunk to release/26.4 December 1, 2025 10:04
@adalpari
Copy link
Contributor Author

adalpari commented Dec 1, 2025

Retargeting to: release/26.4

@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 1, 2025

@nbradbury nbradbury self-assigned this Dec 2, 2025
Copy link
Contributor

@nbradbury nbradbury left a comment

Choose a reason for hiding this comment

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

This looks great to me. All tests passed, and Claude did a very thorough code review. :shipit:

@adalpari adalpari merged commit 94f8cd1 into release/26.4 Dec 2, 2025
23 checks passed
@adalpari adalpari deleted the fix/CMM-955-reader-Subscribe-button-unresponsive-on-quick-tap branch December 2, 2025 17:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants