Skip to content

feat: Long-press copy button to choose raw or formatted body#1613

Merged
cortinico merged 7 commits into
ChuckerTeam:mainfrom
yogen-p:yogen-p/json-clipboard-copy
Apr 29, 2026
Merged

feat: Long-press copy button to choose raw or formatted body#1613
cortinico merged 7 commits into
ChuckerTeam:mainfrom
yogen-p:yogen-p/json-clipboard-copy

Conversation

@yogen-p

@yogen-p yogen-p commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Summary

The transaction payload screen has a single copy button next to each request/response body. Today, tapping it copies transaction.requestBody / responseBody verbatim — even though the body is rendered pretty-printed and syntax-highlighted on screen, so users often paste a one-line JSON blob and lose the on-screen formatting.

This PR keeps the existing tap behaviour (copy raw body) and adds a long-press affordance that opens a popup with two explicit choices:

  • Copy rawtransaction.requestBody / responseBody verbatim (same as the tap default).
  • Copy formatted — runs the body through HttpTransaction.getFormattedRequestBody() / getFormattedResponseBody(), which delegates to the existing FormatUtils.formatJson / formatXml / formatUrlEncodedForm pretty-printers based on the recorded content type.

Implementation notes

  • TransactionBodyAdapter constructor now takes two callbacks: onCopyBodyListener: () -> Unit (tap) and onCopyMenuListener: (View) -> Unit (long-press, anchor for the popup). CopyViewHolder wires both setOnClickListener and setOnLongClickListener on responseCopy. Long-click consumes the event by returning true.
  • TransactionPayloadFragment replaces copyResponse() with three private helpers — copyDefault(), copyRawPayload(transaction), copyFormattedPayload(transaction) — and showCopyMenu(anchor) to inflate R.menu.chucker_copy_payload via PopupMenu. The when (payloadType) is exhaustive, no else branch, mirroring the prior code.
  • New menu resource: library/src/main/res/menu/chucker_copy_payload.xml with copy_raw and copy_formatted items.
  • Strings: added chucker_copy_raw, chucker_copy_formatted, and per-mode toast strings (chucker_request_copied_raw, chucker_request_copied_formatted, chucker_response_copied_raw, chucker_response_copied_formatted) in values/, values-es/, and values-ru/. Removed the now-unused chucker_request_copied / chucker_response_copied. The pre-existing chucker_copy_response is retained because chucker_transaction_item_copy.xml still uses it as the copy button's contentDescription.

Behaviour matrix

Action Request tab Response tab
Tap copy button Raw requestBody Raw responseBody
Long-press → Copy raw Raw requestBody Raw responseBody
Long-press → Copy formatted getFormattedRequestBody() getFormattedResponseBody()

Bodies that are empty are skipped (no toast, no clipboard write).

Feature video

Screen_recording_20260427_161124.mp4

Test plan

  • Run ./gradlew :library:assembleDebug (project requires JDK 21 — I was unable to run this locally; CI should validate).
  • Sample app: trigger a JSON request and a JSON response, then on each tab:
    • Tap copy → clipboard contains the raw body, "Raw {request,response} copied" toast appears.
    • Long-press copy → popup shows Copy raw and Copy formatted.
    • Long-press → Copy raw produces the same output as a tap.
    • Long-press → Copy formatted produces a pretty-printed version (different from the raw output when the wire body is minified).
  • Repeat with an XML body and a application/x-www-form-urlencoded body to confirm the formatted path uses the right pretty-printer for each content type.
  • Repeat with an empty body — no toast, no crash.
  • Verify Spanish (values-es) and Russian (values-ru) toast strings render via locale switch.

🤖 Generated with Claude Code

Tap on the copy button in a transaction's request/response payload still
copies the body verbatim, preserving the prior default. A long-press now
opens a popup with explicit "Copy raw" and "Copy formatted" choices, the
latter going through the existing pretty-printer. Adds matching toasts
and Spanish/Russian translations; drops the now-unused
chucker_request_copied / chucker_response_copied strings.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@yogen-p yogen-p requested a review from a team as a code owner April 27, 2026 15:14
@yogen-p yogen-p marked this pull request as draft April 27, 2026 15:17
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@yogen-p yogen-p marked this pull request as ready for review April 27, 2026 15:29
@yogen-p yogen-p changed the title Long-press copy button to choose raw or formatted body feat: Long-press copy button to choose raw or formatted body Apr 27, 2026
@cortinico cortinico requested a review from Copilot April 27, 2026 16:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a long-press copy affordance on the transaction payload screen so users can explicitly copy either the raw body or a pretty-printed (“formatted”) version, while keeping the existing tap-to-copy-raw behavior.

Changes:

  • Extend the payload “copy” row to support both tap (default/raw) and long-press (popup menu) actions.
  • Add a popup menu to choose between copying raw vs formatted request/response bodies.
  • Add new menu + localized strings for the new copy options and toast messages.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
library/src/main/kotlin/com/chuckerteam/chucker/internal/ui/transaction/TransactionPayloadFragment.kt Wires tap-to-copy-raw and long-press popup; adds raw/formatted copy helpers and updated toast messages.
library/src/main/kotlin/com/chuckerteam/chucker/internal/ui/transaction/TransactionPayloadAdapter.kt Adds a long-press callback on the copy button to open the popup menu.
library/src/main/res/menu/chucker_copy_payload.xml New popup menu with “copy raw” and “copy formatted”.
library/src/main/res/values/strings.xml Adds new copy option + toast strings; removes old generic copied strings.
library/src/main/res/values-es/strings.xml Spanish translations for new copy option + toast strings.
library/src/main/res/values-ru/strings.xml Russian translations for new copy option + toast strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

yogen-p and others added 2 commits April 27, 2026 17:20
Switches the copy popup to androidx.appcompat.widget.PopupMenu so it
picks up AppCompat theming consistent with the rest of the screen, and
moves getFormattedRequestBody / getFormattedResponseBody off the main
thread via lifecycleScope + Dispatchers.Default to avoid jank on large
JSON/XML bodies. The clipboard write and toast still run on the main
thread once formatting completes.

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

@cortinico cortinico left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you also update the CHANGELOG.md file please?

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Comment thread library/src/main/res/values/strings.xml Outdated
yogen-p and others added 2 commits April 29, 2026 10:37
- Rename copyDefault to copyRawPayWrapper for clarity
- Restore Request Copied / Response Copied toasts for the raw path
- Title-case new copy menu and toast strings (en/es/ru)
- Add TransactionBodyAdapter tests covering tap, long-press, and menu inflation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@cortinico cortinico enabled auto-merge (squash) April 29, 2026 17:10
@cortinico cortinico merged commit a982c6b into ChuckerTeam:main Apr 29, 2026
6 checks passed
@yogen-p yogen-p deleted the yogen-p/json-clipboard-copy branch April 30, 2026 13:52
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