Skip to content

Add affiliate tracking link copy fallback - #157

Merged
ralyodio merged 1 commit into
profullstack:masterfrom
absalonCRC:fix-affiliate-tracking-link-copy-fallback
May 23, 2026
Merged

Add affiliate tracking link copy fallback#157
ralyodio merged 1 commit into
profullstack:masterfrom
absalonCRC:fix-affiliate-tracking-link-copy-fallback

Conversation

@absalonCRC

@absalonCRC absalonCRC commented May 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a Clipboard API fallback for the affiliate offer tracking-link Copy button
  • show copied state only after the copy succeeds
  • show an inline error if both Clipboard API and fallback copy fail

Closes #155

Validation

  • pnpm exec eslint 'src/app/affiliates/[slug]/OfferDetailClient.tsx'
  • pnpm type-check
  • git diff --check -- 'src/app/affiliates/[slug]/OfferDetailClient.tsx'

Paid task

Submitted for uGig paid task 4741218f-a723-46bb-82cb-6516120331ae.

Payment address: 27sdMYXofqoM9qR13bZhccRNYeEgYn5EoHXTSJn4QWKP

Payment fallback: PayPal cultofrozen@gmail.com

@greptile-apps

greptile-apps Bot commented May 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR improves the affiliate tracking-link Copy button by adding a document.execCommand fallback for environments where the Clipboard API is unavailable, and shows a success icon/label only after the copy actually succeeds, with an inline error message if both methods fail.

  • The copyText helper correctly attempts navigator.clipboard.writeText first and catches any rejection before falling back to the deprecated execCommand textarea technique.
  • handleCopyTrackingUrl wires the result to trackingCopied state and shows an error on full failure; however, the setTimeout used to reset the "Copied" indicator is not cancelled on re-click or unmount, which can cause the indicator to disappear prematurely on rapid double-clicks.
  • Adding textarea.focus() before .select() in the fallback path improves cross-browser reliability.

Confidence Score: 4/5

Safe to merge — the change is confined to a single client component and the fallback logic is well-guarded.

The core copy-with-fallback logic is correct and the error path works. The uncleared setTimeout on rapid re-clicks is a minor UX rough edge rather than a data or functional break; the deprecated execCommand path is a reasonable stopgap.

src/app/affiliates/[slug]/OfferDetailClient.tsx — specifically the timeout management in handleCopyTrackingUrl.

Important Files Changed

Filename Overview
src/app/affiliates/[slug]/OfferDetailClient.tsx Adds clipboard copy fallback using execCommand, copied state feedback, and inline error display for the affiliate tracking-link button. The approach is correct but the setTimeout is not cleared on re-click or unmount, and the textarea fallback could be made slightly more robust.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User clicks Copy button] --> B[handleCopyTrackingUrl]
    B --> C{navigator.clipboard available?}
    C -- Yes --> D[clipboard.writeText]
    D -- Success --> E[setTrackingCopied = true]
    D -- Error --> F[Fall through to textarea]
    C -- No --> F
    F --> G[Create hidden textarea, append to body, select text]
    G --> H[document.execCommand copy]
    H -- true --> E
    H -- false --> I[setError: manual copy message]
    E --> J[setTimeout 2s]
    J --> K[setTrackingCopied = false]
Loading

Reviews (1): Last reviewed commit: "Add affiliate tracking link copy fallbac..." | Re-trigger Greptile

Comment on lines +142 to +153
async function handleCopyTrackingUrl() {
setError("");
setTrackingCopied(false);

if (await copyText(trackingUrl)) {
setTrackingCopied(true);
window.setTimeout(() => setTrackingCopied(false), 2000);
return;
}

setError("Unable to copy tracking link. Select the link and copy it manually.");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Stale timeout on rapid re-clicks or unmount

Each call to handleCopyTrackingUrl schedules a new setTimeout without cancelling the previous one. If the user clicks Copy twice within 2 seconds, the first timeout fires and resets the "Copied" state prematurely — before 2 seconds have elapsed since the second click. Additionally, if the component unmounts while the timer is pending, the timeout still fires and calls setTrackingCopied(false) on the stale closure. Storing the timer ID in a useRef and clearing it at the top of the handler (and in a useEffect cleanup) would prevent both issues.

Comment on lines +53 to +65
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.setAttribute("readonly", "");
textarea.style.position = "fixed";
textarea.style.opacity = "0";
document.body.appendChild(textarea);
textarea.select();

try {
return document.execCommand("copy");
} finally {
document.body.removeChild(textarea);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 document.execCommand("copy") is deprecated and may silently return false or throw in some browsers even when the selection succeeds. Adding textarea.focus() before .select() improves reliability across browsers.

Suggested change
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.setAttribute("readonly", "");
textarea.style.position = "fixed";
textarea.style.opacity = "0";
document.body.appendChild(textarea);
textarea.select();
try {
return document.execCommand("copy");
} finally {
document.body.removeChild(textarea);
}
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.setAttribute("readonly", "");
textarea.style.position = "fixed";
textarea.style.top = "0";
textarea.style.opacity = "0";
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
return document.execCommand("copy");
} finally {
document.body.removeChild(textarea);
}

@ralyodio
ralyodio merged commit 4ae1920 into profullstack:master May 23, 2026
4 checks passed
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.

bug: affiliate tracking link copy fails when Clipboard API is blocked

2 participants