From ef09ebcc36c063d0e96a776a22069b4e7e0ad362 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Mon, 25 Dec 2023 11:34:19 +0100 Subject: [PATCH] Add button to copy request/response payload The button copies the full request/response to the clipboard. The content type label has been removed to make space for this button. See #362 --- .../adapters/PayloadAdapter.java | 39 +++++++++++++------ .../res/drawable/ic_content_copy_small.xml | 5 +++ app/src/main/res/layout/payload_item.xml | 33 ++++++++++------ 3 files changed, 54 insertions(+), 23 deletions(-) create mode 100644 app/src/main/res/drawable/ic_content_copy_small.xml diff --git a/app/src/main/java/com/emanuelef/remote_capture/adapters/PayloadAdapter.java b/app/src/main/java/com/emanuelef/remote_capture/adapters/PayloadAdapter.java index 872f059c0..892a1a4f5 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/adapters/PayloadAdapter.java +++ b/app/src/main/java/com/emanuelef/remote_capture/adapters/PayloadAdapter.java @@ -27,6 +27,7 @@ import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.CheckResult; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; @@ -40,6 +41,7 @@ import com.emanuelef.remote_capture.model.PayloadChunk; import com.emanuelef.remote_capture.model.PayloadChunk.ChunkType; import com.emanuelef.remote_capture.model.Prefs; +import com.google.android.material.button.MaterialButton; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; @@ -111,18 +113,24 @@ PayloadChunk getPayloadChunk() { return mChunk; } - private void makeText() { - int dump_len = mIsExpanded ? mChunk.payload.length : Math.min(mChunk.payload.length, COLLAPSE_CHUNK_SIZE); + @CheckResult + private String makeText(boolean expanded) { + int dump_len = expanded ? mChunk.payload.length : Math.min(mChunk.payload.length, COLLAPSE_CHUNK_SIZE); if(!mShowAsPrintable) - mTheText = Utils.hexdump(mChunk.payload, 0, dump_len); + return Utils.hexdump(mChunk.payload, 0, dump_len); else - mTheText = new String(mChunk.payload, 0, dump_len, StandardCharsets.UTF_8); + return new String(mChunk.payload, 0, dump_len, StandardCharsets.UTF_8); + } + + @CheckResult + private String makeText() { + return makeText(mIsExpanded); } void expand() { mIsExpanded = true; - makeText(); + mTheText = makeText(); // round up div mNumPages = (mTheText.length() + VISUAL_PAGE_SIZE - 1) / VISUAL_PAGE_SIZE; @@ -138,7 +146,7 @@ void collapse() { String getText(int start, int end) { if(mTheText == null) - makeText(); + mTheText = makeText(); if((start == 0) && (end >= mTheText.length() - 1)) { return mTheText; @@ -147,11 +155,15 @@ String getText(int start, int end) { return mTheText.substring(start, end); } + String getExpandedText() { + return makeText(true); + } + Page getPage(int pageIdx) { assert(pageIdx < mNumPages); if(mTheText == null) - makeText(); + mTheText = makeText(); if(!mIsExpanded) return new Page(this, 0, mTheText.length() - 1, true); @@ -189,8 +201,8 @@ protected static class PayloadViewHolder extends RecyclerView.ViewHolder { View dumpBox; TextView header; TextView dump; - TextView contentType; ImageView expandButton; + MaterialButton copybutton; public PayloadViewHolder(View view) { super(view); @@ -200,7 +212,7 @@ public PayloadViewHolder(View view) { dump = view.findViewById(R.id.dump); dumpBox = view.findViewById(R.id.dump_box); expandButton = view.findViewById(R.id.expand_button); - contentType = view.findViewById(R.id.content_type); + copybutton = view.findViewById(R.id.copy_button); } } @@ -227,6 +239,13 @@ public PayloadViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewT } }); + holder.copybutton.setOnClickListener(v -> { + int pos = holder.getAbsoluteAdapterPosition(); + String payload = getItem(pos).adaptChunk.getExpandedText(); + + Utils.copyToClipboard(mContext, payload); + }); + return holder; } @@ -251,8 +270,6 @@ public void onBindViewHolder(@NonNull PayloadViewHolder holder, int position) { getHeaderTag(chunk), (new SimpleDateFormat("HH:mm:ss.SSS", locale)).format(new Date(chunk.timestamp)), Utils.formatBytes(chunk.payload.length))); - - holder.contentType.setText((chunk.contentType != null) ? chunk.contentType : ""); } else holder.headerLine.setVisibility(View.GONE); diff --git a/app/src/main/res/drawable/ic_content_copy_small.xml b/app/src/main/res/drawable/ic_content_copy_small.xml new file mode 100644 index 000000000..31122df82 --- /dev/null +++ b/app/src/main/res/drawable/ic_content_copy_small.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/payload_item.xml b/app/src/main/res/layout/payload_item.xml index fd971f0b0..fb9f1244d 100644 --- a/app/src/main/res/layout/payload_item.xml +++ b/app/src/main/res/layout/payload_item.xml @@ -26,20 +26,29 @@ android:textStyle="bold" tools:text="#1 [TX] 11:02:03.154 — 120 B" /> - + + + app:icon="@drawable/ic_content_copy_small" + app:iconGravity="textStart" + app:iconPadding="0dp" + app:iconTint="@color/colorTabText" + style="@style/Widget.MaterialComponents.Button.TextButton" />