Skip to content

Conversation

@adalpari
Copy link
Contributor

Description

This PR is achieving different improvements suggested for the new Support:

  • Offline specific screen instead og the empty one
  • Error-specific screen instead of an error message + empty screen
  • New ticket form:
    - Site address is not capitalised anymore
    - Site address now shows the URL-specific keyboard
    - Better a11y input labels for a better SpeechToVoice navigation
    - Application logs toggle a11y label
  • Marked all the headings for a better a11y experience
  • Grouping message bubbles into a single a11y entity
  • Pencil icon substituted by a "+" to create new conversations
Screenshot 2025-10-28 at 10 00 48 Screenshot 2025-10-28 at 10 02 49

Testing instructions

  • Smoke test the changes

@adalpari
Copy link
Contributor Author

@claude

@claude
Copy link

claude bot commented Oct 28, 2025

Claude finished @adalpari's task —— View job


Code Review Complete ✅

I've performed a comprehensive review of the PR changes. Overall, this is a solid improvement to the support feature with excellent accessibility enhancements. I've also added inline comments on specific lines for key issues.


✅ Strengths

Accessibility (a11y)

  • Excellent use of semantics modifiers with contentDescription and heading() throughout
  • Message bubbles properly grouped into single accessibility entities (lines 262-278 in HEConversationDetailScreen.kt, lines 294-352 in AIBotConversationDetailScreen.kt)
  • All interactive elements have proper content descriptions
  • Form inputs use proper labels for screen readers

User Experience

  • Dedicated offline and error states provide much better UX than generic empty screens
  • Changed pencil icon to "+" icon for creating conversations - more intuitive
  • Site address field now uses KeyboardType.Uri and KeyboardCapitalization.None - excellent attention to detail
  • Pull-to-refresh properly implemented

Code Quality

  • Good separation of concerns with new common UI components (ConversationsListScreen, OfflineConversationsView, ErrorConversationsView)
  • Comprehensive preview functions for different themes and app variants
  • Proper use of Kotlin sealed classes for state management
  • Good state hoisting patterns in Compose

🔍 Issues & Suggestions

1. Error State Image may be Jetpack-Specific 💬

Location: ErrorConversationsView.kt:25

Using img_jetpack_empty_state for error view might not be appropriate for WordPress-branded app. The offline view correctly uses a generic cloud icon. Consider using a more generic error illustration or making it theme-aware.

2. Inconsistent Semantic Descriptions

Location: HEConversationDetailScreen.kt:262 and AIBotConversationDetailScreen.kt:297

In HE screen:

val messageDescription = "${message.authorName}, $timestamp. ${message.formattedText}"

In AI Bot screen:

val author = if (message.isWrittenByUser) "You" else "AI Bot"
val messageDescription = "$author, $timestamp. ${message.formattedText}"

Issue: Different patterns for constructing message descriptions. The AI Bot version is more user-friendly with "You" instead of the user's name.

Suggestion: Consider standardizing this across both screens. Using "You" for user messages is more natural for screen readers.

3. Hardcoded Emoji in UI

Location: AIBotConversationDetailScreen.kt:225

Hardcoded emoji (✨) might not render consistently across all Android versions/devices. Consider using a drawable resource or at least add a comment documenting this design choice.

4. Missing Error Handling for Network State Changes 💬

Location: ConversationsSupportViewModel.kt:100-103

The network check happens only during initial load. If the network becomes unavailable during use, the user might see generic errors instead of the offline view. Consider monitoring network state changes and updating ConversationsState accordingly.

5. Potential Memory Leak in Typing Animation

Location: AIBotConversationDetailScreen.kt:391-399

The while (true) loop in LaunchedEffect continues even when the composable leaves the screen. This is actually fine for LaunchedEffect as it auto-cancels, but it's not immediately obvious. Consider adding a comment explaining that LaunchedEffect will cancel this when the composable is disposed.

6. Accessibility: Missing Role Semantics

Location: Multiple files

While content descriptions are excellent, some interactive elements could benefit from explicit role semantics (e.g., role = Role.Button) to make their purpose clearer to screen readers.

Suggestion: Consider adding role semantics to buttons and clickable cards:

.semantics { 
    role = Role.Button
    contentDescription = "..."
}

7. Potential Race Condition in Message Sending

Location: HEConversationDetailScreen.kt:369-385

The LaunchedEffect depends on messageSendResult but there's no guarantee about the timing of clearing the result vs dismissing the sheet. This appears to be handled correctly with the callbacks, but ensure onClearMessageSendResult() is called in a way that doesn't trigger the LaunchedEffect again before the sheet dismisses.

8. String Concatenation in Accessibility Descriptions

Location: Multiple locations, e.g., HEConversationDetailScreen.kt:195-196

String concatenation with hardcoded punctuation (". ") might not work well for all languages. Consider using a dedicated string resource for combined descriptions to support proper localization:

<string name="he_support_header_description">%1$s. %2$s</string>

🧪 Testing Recommendations

  1. Accessibility Testing

    • Test with TalkBack enabled on various screen sizes
    • Verify that message bubbles are announced as single entities
    • Test keyboard navigation through form fields
  2. Network State Testing

    • Test offline state by disabling network before opening conversations
    • Test switching between online/offline while viewing conversations
    • Test error recovery when network is restored
  3. Edge Cases

    • Test with very long site URLs in the form
    • Test with empty/null user names in accessibility descriptions
    • Test rapid message sending to ensure proper state management
  4. Localization

    • Test with RTL languages to ensure message bubble alignment works correctly
    • Test with languages that have longer strings to ensure UI doesn't break

📋 Minor Nitpicks

  1. Preview Function Naming: Some preview functions have inconsistent naming (e.g., ReplyBottomSheetPreview vs HENewTicketScreenPreview). Not critical but could be more consistent.

  2. Magic Number: PAGINATION_TRIGGER_THRESHOLD = 4 in AIBotConversationDetailScreen.kt:63 - consider adding a comment explaining why 4 was chosen.

  3. Unused Parameter: In TypingDot composable, the delay parameter could be better named as initialDelayMs for clarity.


🎯 Summary

Overall Assessment: ✅ Approve with minor suggestions

This PR demonstrates excellent attention to accessibility and user experience. The code is well-structured, properly organized, and follows good Compose patterns. The issues identified are mostly minor improvements and edge cases rather than critical problems.

Key Achievements:

  • ✅ Significantly improved accessibility
  • ✅ Better error handling and offline states
  • ✅ Improved form UX (keyboard types, capitalization)
  • ✅ Good code organization and reusability
  • ✅ Comprehensive preview functions

Recommended Actions:

  1. Address the Jetpack-specific error image (Menu Drawer Item refactor #1) 💬
  2. Consider standardizing message descriptions (Implementing WordPress.com Notifications Activities #2)
  3. Add network state monitoring for better offline detection (Fix for bug #403 #4) 💬
  4. Add more semantic role information for screen readers (Select first row of notifications after refresh on tablet #6)

Great work on this PR! The improvements to accessibility and user experience are substantial and well-implemented.


💬 = Has inline comment with more details

@dangermattic
Copy link
Collaborator

dangermattic commented Oct 28, 2025

2 Warnings
⚠️ strings.xml files should only be updated on release branches, when the translations are downloaded by our automation.
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

private suspend fun loadConversations() {
try {
_isLoadingConversations.value = true
if (!networkUtilsWrapper.isNetworkAvailable()) {
Copy link

Choose a reason for hiding this comment

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

The network check happens only during initial load. Consider monitoring network state changes throughout the lifecycle to provide better offline detection. If the network becomes unavailable while the user is viewing conversations, they might see generic errors instead of the dedicated offline view.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Oct 28, 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
Versionpr22320-865b0ee
Commit865b0ee
Direct Downloadwordpress-prototype-build-pr22320-865b0ee.apk
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Oct 28, 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
Versionpr22320-865b0ee
Commit865b0ee
Direct Downloadjetpack-prototype-build-pr22320-865b0ee.apk
Note: Google Login is not supported on these builds.

@codecov
Copy link

codecov bot commented Oct 28, 2025

Codecov Report

❌ Patch coverage is 4.80000% with 238 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.33%. Comparing base (e126063) to head (865b0ee).
⚠️ Report is 12 commits behind head on feat/CMM-883-support-Oddie-bot-conversation-pagination.

Files with missing lines Patch % Lines
...droid/support/common/ui/ConversationsListScreen.kt 0.00% 44 Missing ⚠️
...ndroid/support/common/ui/ErrorConversationsView.kt 0.00% 27 Missing ⚠️
...roid/support/common/ui/OfflineConversationsView.kt 0.00% 27 Missing ⚠️
...rdpress/android/support/he/ui/HENewTicketScreen.kt 0.00% 25 Missing ⚠️
...d/support/aibot/ui/AIBotConversationsListScreen.kt 0.00% 23 Missing ⚠️
...ess/android/support/he/ui/TicketMainContentView.kt 0.00% 22 Missing ⚠️
...android/support/he/ui/HEConversationsListScreen.kt 0.00% 21 Missing ⚠️
.../support/aibot/ui/AIBotConversationDetailScreen.kt 0.00% 20 Missing ⚠️
...ndroid/support/he/ui/HEConversationDetailScreen.kt 0.00% 19 Missing ⚠️
...wordpress/android/support/main/ui/SupportScreen.kt 0.00% 6 Missing ⚠️
... and 2 more
Additional details and impacted files
@@                                    Coverage Diff                                     @@
##           feat/CMM-883-support-Oddie-bot-conversation-pagination   #22320      +/-   ##
==========================================================================================
- Coverage                                                   39.36%   39.33%   -0.04%     
==========================================================================================
  Files                                                        2195     2198       +3     
  Lines                                                      105296   105394      +98     
  Branches                                                    14978    14983       +5     
==========================================================================================
+ Hits                                                        41454    41460       +6     
- Misses                                                      60351    60442      +91     
- Partials                                                     3491     3492       +1     

☔ 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 adalpari marked this pull request as ready for review October 29, 2025 11:29
@adalpari adalpari requested a review from dcalhoun October 29, 2025 11:29
@adalpari
Copy link
Contributor Author

@dcalhoun, these are some of the changes you suggested here

@adalpari adalpari changed the title CMM 894 new support general improvements CMM-894 new support general improvements Oct 29, 2025
Copy link
Member

@dcalhoun dcalhoun left a comment

Choose a reason for hiding this comment

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

Noticed a few small things, but overall these are solid improvements. Thanks!

The loading indicator appears to be obscured by the header navigation:

Loading indicator screenshot

Image

Comment on lines 324 to 326
.semantics(mergeDescendants = true) {
contentDescription = messageDescription
}
Copy link
Member

Choose a reason for hiding this comment

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

Currently, TalkBack announces the author, date, and message contents twice. This is less than ideal and can significantly increase the amount of noise when navigating long messages.

I believe the issue originates from combining mergeDescendants and contentDescription. We should likely do one of two things here and anywhere else we are taking this approach:

  1. Keep the semantics(mergeDescendants = true) with contentDescription on the Box. Add .semantics { invisibleToUser() } to both Text composables inside the Column.
  2. Keep semantics(mergeDescendants = true) but remove the contentDescription assignment. Optionally prepend the author information to the message text itself.

The first option likely makes the most sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Fixing it!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

<string name="ai_bot_empty_conversations_message">Start a new conversation to get help with your WordPress site or account.</string>
<string name="ai_bot_empty_conversations_button">Start conversation</string>
<string name="ai_bot_you">You</string>
<string name="ai_bot_odie" translatable="false">Odie</string>
Copy link
Member

Choose a reason for hiding this comment

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

Do we surface the name "Odie" anywhere else? If not, this might be confusing. Should we use a generic "Bot" instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mmm, good question. I'll figure it out.

@sonarqubecloud
Copy link

@adalpari adalpari merged commit e066a74 into feat/CMM-883-support-Oddie-bot-conversation-pagination Oct 30, 2025
23 checks passed
@adalpari adalpari deleted the feat/CMM-894-new-support-general-improvements branch October 30, 2025 08:21
adalpari added a commit that referenced this pull request Oct 30, 2025
* Support pagination

* Triggering in the 4th element

* detekt

* TODO for debug purposes

* Claude PR suggestions

Mutex and constant

* Support pagination

* Triggering in the 4th element

* detekt

* TODO for debug purposes

* Claude PR suggestions

Mutex and constant

* Detekt

* Removing testing code

* CMM-894 new support general improvements (#22320)

* Put ConversationListView in common between bots and HE

* Empty and error state

* Skip site capitalization

* Adding a11c labels

* Adding headings labels

* adding accessible labels to chat bubbles

* detekt

* Fixing tests

* PR suggestion about bot chat bubble

* Fixing tests

* Fixing TalkBack duplication
adalpari added a commit that referenced this pull request Oct 30, 2025
* Adding basic UI

* Renaming

* Some styling

* Renaming and dummy data

* Using proper "new conversation icon"

* Conversation details screen

* Creating the reply bottomsheet

* Linking to the support screen

* bottomsheet fix

* Mov navigation form activity to viewmodel

* Adding create ticket screen

* More screen adjustments

* Extracting common code

* Margin fix

* detekt

* Style

* New ticket check

* Creating tests

* Creating repository and load conversations function

* Adding createConversation function

* Creating loadConversation func

* Loading conversations form the viewmodel

* Adding loading spinner

* Pull to refresh

* Proper ionitialization

* Adding empty screen

* Handling send new conversation

* Show loading when sending

* New ticket creation fix

* Using snackbar for errors

* Error handling

* Answering conversation

* Adding some test to the repository

* More tests!

* Compile fixes

* Similarities improvements

* Using snackbar in bots activity

* Extracting EmptyConversationsView

* Renaming

* Extracting VM and UI common code

* Extracting navigation common code

* Renaming VMs for clarification

* More refactor

* Capitalise text fields

* Updating rs library

* Loading conversation UX

* Style fix

* Fixing scaffolds paddings

* userID fix

* Fixing the padding problem in bot chat when the keyboard is opened

* Apply padding to create ticket screen when the keyboard is opened

* Fixing scroll state in reply bottomsheet

* Adding tests for the new common viewmodel

* Fixing AIBotSupportViewModel tests

* detekt

* Improvements int he conversation interaction

* Adding tests for HE VM

* Saving draft state

* Properly navigating when a ticket is selected

* Error parsing improvement

* accessToken suggestion improvements

* General suggestions

* Send message error UX improvement

* Fixing tests

* Converting the UI to more AndroidMaterial style

* Bots screen renaming

* Bots screens renaming

* Make NewTicket screen more Android Material theme as well

* Adding preview for EmptyConversationsView

* Button fix

* detekt

* Ticket selection change

* Supporting markdown text

* detekt

* Improving MarkdownUtils

* Formatting text in the repository layer instead the ui

* Renaming

* Fixing tests

* Parsing markdown more exhaustively

* New links support

* Detekt

* CMM-883 support Odie bot conversation pagination (#22316)

* Support pagination

* Triggering in the 4th element

* detekt

* TODO for debug purposes

* Claude PR suggestions

Mutex and constant

* Support pagination

* Triggering in the 4th element

* detekt

* TODO for debug purposes

* Claude PR suggestions

Mutex and constant

* Detekt

* Removing testing code

* CMM-894 new support general improvements (#22320)

* Put ConversationListView in common between bots and HE

* Empty and error state

* Skip site capitalization

* Adding a11c labels

* Adding headings labels

* adding accessible labels to chat bubbles

* detekt

* Fixing tests

* PR suggestion about bot chat bubble

* Fixing tests

* Fixing TalkBack duplication
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