Skip to content

Commit ad1de65

Browse files
adalpariclaude
andauthored
Unify bot and HE support into a single Get help conversations flow (#22946)
* Bump wordpress-rs to 1288-fbca03e9 for combined conversations support Adopts the new WpService(SiteInfo, delegate, cache) constructor in place of the removed WpService.wordpressCom / WpService.selfHosted factories, and wraps UserWithEditContext.extraCapabilities in UserCapabilitiesMap to match the updated type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add unified support conversations screen Wires a new parallel entry point on the Support screen that drives list/detail/reply through the new wordpress-rs unifiedConversations() endpoint, merging HE tickets and AI bot chats into a single chat-style view branching UI on UnifiedMessage.authorRole. Reply UX is an inline input bar gated on UnifiedConversationSummary.canAcceptReply, and a successful reply replaces local state with the server response per the new API contract. The existing HE and AI Bot flows are left unchanged so they can still create new tickets/chats. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Branch unified support reply UX by conversation type In the unified support detail screen, choose the reply affordance based on the conversation's status: - Bot conversations (status == "bot") keep the always-on inline chat input. - HE conversations that can accept a reply show a Reply button that opens a modal reply sheet reusing the HE TicketMainContentView form. - HE conversations that cannot accept a reply show a closed banner. The unified reply API only accepts a message string, so the reply sheet greys out the screenshots and app-logs controls. To support this without changing existing HE call sites, TicketMainContentView gains optional attachmentsEnabled/appLogsEnabled params that default to its enabled flag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Match Ask the Bots behavior for unified bot conversations Replicate the bot send/receive UX from the AI Bot support screen in the unified detail screen, for bot conversations only (status == "bot"): - Show an animated "bot is typing" indicator while a reply is in flight. - Disable the send button while sending or loading, keeping the input field editable (ChatInputBar now takes canSendMessage). - Auto-scroll to the bottom when the bot starts typing. HE conversations are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add HE-style list with status, + button, and new bot chat creation Make the unified conversations list match the Ask the Happiness Engineers screen and support creating new conversations: - List items now show a status badge, title, timestamp, and description. HE conversations use their ticket status; bot conversations show an "Assistant" chip. - Show a "+" action and an empty-state Create button (the shared list screen renders these when a create callback is provided). - Creating a new conversation starts a bot chat: the first message is created via the AI bot endpoint (createBotConversation) and mapped into a UnifiedConversation, mirroring the Ask the Bots flow. - Centralize the "bot" status as UnifiedConversation.STATUS_BOT/isBot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Render HE conversations like the Ask the HE screen in unified detail For non-bot conversations, the unified detail screen now mirrors the Ask the Happiness Engineers screen instead of the chat-bubble layout: - Status badge + "Last updated" header and a title card (empty top bar). - Full-width message items with an author + timestamp header. - Attachments rendered as a thumbnail grid (auth-header image loading, video first-frame with a play overlay, icon for other files) that open: image -> in-app fullscreen zoom preview, video -> in-app player, other -> system DownloadManager. Bot conversations keep their chat-bubble UI and typing indicator. Reuses the HE fullscreen preview/player composables, VideoDownloadState, ConversationStatusBadge, and AttachmentType. Adds video download + auth header to the unified ViewModel, injects ReaderFileDownloadManager in the Activity, and derives an attachment type on UnifiedAttachment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Bump wordpress-rs to 1376-7d42af3 for unified reply attachments Adapts repository tests to the WpRequestResult.UnknownError statusCode type change (UShort -> UInt). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Enable screenshots and app logs in unified reply form Wires attachment uploads into the unified conversation reply endpoint, which now accepts multipart attachments like HE replies. The reply bottom sheet gets the same screenshot picker and app logs switch as the HE reply sheet, with the form state held in the ViewModel so drafts survive configuration changes and failed sends. Extracts the attachment size validation from HESupportViewModel into a shared AttachmentStateValidator used by both flows, and removes the now-unused attachmentsEnabled/appLogsEnabled flags from TicketMainContentView. Like HE replies, the app logs switch is UI-only until the RS layer supports encrypted log ids for replies. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Send encrypted app log ids with unified conversation replies Bumps wordpress-rs to 1379-919351b, which adds encryptedLogIds to ReplyToUnifiedConversationParams. The Include app logs switch in the unified reply form now encrypts and uploads the app logs and sends the resulting UUIDs with the reply, matching the HE new-ticket flow. Extracts the log upload logic from HESupportViewModel into a shared EncryptedAppLogsUploader used by both flows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Match Ask the Bots new-chat UX and brand bot entries as Oddie bot New bot conversations in the unified screen now show the Ask the Bots welcome header (reused from AIBotConversationDetailScreen), and the first bot reply no longer drops the optimistic user question - the create endpoint only returns the bot messages, so local messages are kept like the Ask the Bots flow does. Bot conversations are labeled Oddie bot in the list pill and above bot message bubbles, with the pill using the same soft green as the user chat bubble. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Replace Ask the Bots and Ask the HE sections with single Get help entry Removes the old Ask the Bots (support/aibot) and Ask the Happiness Engineers (support/he) screens, superseded by the unified conversations section, now titled "Get help". HE ticket creation is removed: bot conversations get escalated to HE server-side and then show up as HE conversations in the combined list. - Moves the shared models, utils, and UI components from the he/aibot packages into support/unified (attachment state/validation, encrypted logs uploader, temp attachments, fullscreen attachment previews, status badge, ticket content view, relative time formatting). - Merges bot conversation creation into UnifiedSupportRepository, mapping the bot endpoint response directly to UnifiedConversation and dropping the BotConversation/BotMessage models. - Trims the main Support screen to a single Get help option and updates its strings, removing the now-unused activity registrations and ai_bot_/he_support_ strings. - Replaces the deleted tests with UnifiedSupportRepositoryTest and AttachmentStateValidatorTest, and updates SupportViewModelTest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Clean up unified support code after consolidation Removes leftovers flagged in review: the dead NavigateToNewConversation navigation path, the unused nullable create-conversation callback in the shared list components, the duplicate video cache cleanup, and unread model fields (UnifiedMessage.rawText, UnifiedAttachment.size). Simplifies the detail screen by passing the authorization header as a plain string instead of threading a getter lambda through the composable layers, deduplicates the reply sheet dismiss logic, and reuses the shared back/send strings and the Uri.fileSize() extension instead of local duplicates. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Bump wordpress-rs to 1288-85a8554 Consolidated combined-conversations build; no API adaptations needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix review findings in unified support conversations - Recalculate the attachment total size when removing an attachment so the size meter stays accurate - Surface conversation list API errors as the Error state instead of rendering an empty list - Preserve the bot chat input across configuration changes - Derive the scroll-to-bottom index from the conversation data instead of potentially stale lazy list layout info Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix detekt and lint issues in unified support code - Extract the bottom bar and attachment preview overlay into their own composables so UnifiedConversationDetailScreen stays under the cyclomatic complexity threshold - Remove stale translations of the support strings deleted by the consolidation, fixing the ExtraTranslation lint errors Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Add tests for UnifiedSupportViewModel and EncryptedAppLogsUploader Covers repository initialization, reply sending (success, failure rollback, offline, app logs, attachments and temp file cleanup), new bot conversation creation, reply form state, video downloads with caching, and encrypted log uploads. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Update support bot ID to jetpack-workflow-chat_mobile_support Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Harden unified support: scroll, send guard, video cache, attachment revalidation - Derive scroll-to-bottom from layoutInfo.totalItemsCount via snapshotFlow instead of hardcoded header/typing/spacer counts - Set _isSendingReply synchronously before launching to close the concurrent send race - Use ConcurrentHashMap for the video cache (accessed from IO coroutines and onCleared) - Revalidate rejected attachments in a single pass so the form state is published only once - Document the intentionally-empty bot top-bar title Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Use mutableFloatStateOf for typing-dot alpha to avoid autoboxing Fixes the AutoboxingStateCreation lint warning in TypingDot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Bump wordpress-rs to 1288-b699fd4edbeff43b9839abd12ad5a9774cd90588 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Address review feedback on unified support flow - Bind the bot chat input to the shared reply form state so typed text is retained on send failure (the VM clears it only on success) and survives configuration changes via the ViewModel, instead of clearing it eagerly. - Only call viewModel.init() on first creation (savedInstanceState == null) to avoid reloading conversations and resetting state on every recreation. - Simplify TempAttachmentsUtil.removeTempFiles (drop unused bookkeeping) and fix duplicated log wording. - Remove a stale comment and document that AttachmentStateValidator's rejectedUris is per-call, not accumulated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Gate support attachment auth token to trusted WP.com hosts The bearer token was attached unconditionally when loading attachment images/videos (Coil) and downloading video attachments (OkHttp). Gate these with WPUrlUtils.safeToAddWordPressComAuthToken (the same guard the app's AuthenticationUtils uses) so the token is only sent to WP.com hosts. Attachment URLs are served from public-api.wordpress.com, which passes the check, so legitimate loading is unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Clear support reply input on send, restore only on failure Previously the typed text stayed visible in the chat input while waiting for the bot/HE response, which looked like it hadn't been sent. Clear the input immediately when a reply is sent so it reads as sent, and restore the text only if the send fails (and only when the user hasn't typed a new message in the meantime). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Clear draft on conversation open and fix temp attachment name collision Clear the reply draft (text + attachments) whenever a conversation is opened, so a draft started in one conversation never leaks into another regardless of how the previous one was exited (toolbar back, system back button, or back gesture). Done via an onConversationOpened() hook on the base VM invoked from both onConversationClick and setNewConversation. Use File.createTempFile for support attachment temp files so each gets a unique name even when several small files are copied within the same millisecond, avoiding collisions that sent the same file twice. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Fix stream/temp-file leaks and reply-form state races Wrap the attachment input stream in use {} so it can't leak if copyTo throws mid-copy, and delete the temp file on failure. In createTempFilesFrom, clean up files already created when a later URI fails instead of leaving partial results in cacheDir. Convert _replyFormState read-modify-writes to MutableStateFlow.update {} so concurrent updates (e.g. addReplyAttachments on the IO dispatcher vs a removal or send-clear) are atomic and can't be lost. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Bump wordpress-rs to 96105487c29b4205f25ff722ec80704ef8baa263 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Bump wordpress-rs to trunk-96105487c29b4205f25ff722ec80704ef8baa263 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e656af2 commit ad1de65

87 files changed

Lines changed: 3124 additions & 7702 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

WordPress/src/main/AndroidManifest.xml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -479,11 +479,6 @@
479479
android:theme="@style/WordPress.NoActionBar"
480480
android:label="@string/subscribers"/>
481481

482-
<activity android:name="org.wordpress.android.support.aibot.ui.AIBotSupportActivity"
483-
android:theme="@style/WordPress.NoActionBar"
484-
android:label="@string/ai_bot_conversations_title"
485-
android:windowSoftInputMode="adjustResize"/>
486-
487482
<activity android:name="org.wordpress.android.support.main.ui.SupportActivity"
488483
android:theme="@style/WordPress.NoActionBar"
489484
android:label="@string/support_screen_title"/>
@@ -492,9 +487,9 @@
492487
android:theme="@style/WordPress.NoActionBar"
493488
android:label="@string/support_screen_application_logs_title"/>
494489

495-
<activity android:name="org.wordpress.android.support.he.ui.HESupportActivity"
490+
<activity android:name="org.wordpress.android.support.unified.ui.UnifiedSupportActivity"
496491
android:theme="@style/WordPress.NoActionBar"
497-
android:label="@string/support_screen_title"
492+
android:label="@string/unified_support_conversations_title"
498493
android:windowSoftInputMode="adjustResize"/>
499494

500495
<!-- Deep Linking Activity -->

WordPress/src/main/java/org/wordpress/android/support/aibot/model/BotConversation.kt

Lines changed: 0 additions & 14 deletions
This file was deleted.

WordPress/src/main/java/org/wordpress/android/support/aibot/model/BotMessage.kt

Lines changed: 0 additions & 14 deletions
This file was deleted.

WordPress/src/main/java/org/wordpress/android/support/aibot/repository/AIBotSupportRepository.kt

Lines changed: 0 additions & 186 deletions
This file was deleted.

0 commit comments

Comments
 (0)