Commit ad1de65
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
- WordPress/src
- main
- java/org/wordpress/android/support
- aibot
- model
- repository
- ui
- util
- common/ui
- he
- model
- repository
- ui
- util
- main/ui
- unified
- model
- repository
- ui
- util
- res
- values-ar
- values-bg
- values-cs
- values-da
- values-de
- values-en-rGB
- values-es-rCO
- values-es
- values-fr-rCA
- values-fr
- values-gl
- values-he
- values-id
- values-it
- values-ja
- values-ko
- values-nl
- values-pl
- values-pt-rBR
- values-ro
- values-ru
- values-sq
- values-sv
- values-tr
- values-zh-rCN
- values-zh-rHK
- values-zh-rTW
- values
- test/java/org/wordpress/android/support
- aibot
- repository
- ui
- common/ui
- he
- repository
- ui
- main/ui
- unified
- repository
- ui
- util
- gradle
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
479 | 479 | | |
480 | 480 | | |
481 | 481 | | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | 482 | | |
488 | 483 | | |
489 | 484 | | |
| |||
492 | 487 | | |
493 | 488 | | |
494 | 489 | | |
495 | | - | |
| 490 | + | |
496 | 491 | | |
497 | | - | |
| 492 | + | |
498 | 493 | | |
499 | 494 | | |
500 | 495 | | |
| |||
Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 0 additions & 186 deletions
This file was deleted.
0 commit comments