Skip to content

feat: make download buttons real links (copy-link-address works)#409

Merged
tomusdrw merged 6 commits intomainfrom
td-download-links
Apr 17, 2026
Merged

feat: make download buttons real links (copy-link-address works)#409
tomusdrw merged 6 commits intomainfrom
td-download-links

Conversation

@tomusdrw
Copy link
Copy Markdown
Member

@tomusdrw tomusdrw commented Apr 17, 2026

Summary

  • The Markdown and PDF download buttons in DownloadModal are now rendered as real <a> tags (via Button asChild), so right-click → Copy Link Address / Open in New Tab works natively.
  • Left-click behavior is preserved: onClick still calls preventDefault() and uses the existing fetch+Blob path so the file is downloaded with the short-hash filename, same as before.
  • Modifier-click (cmd/ctrl/shift/alt) and middle-click fall through to the browser default so users can deliberately open the link in a new tab.
  • The dynamic Generate PDF (theme) button is unchanged — it has no URL to link to.

Test plan

  • Open the Download modal and verify the Markdown / PDF buttons still look identical to before.
  • Left-click each button → file downloads with graypaper-<shortHash>.{md,pdf} filename.
  • Right-click → Copy Link Address returns the correct https://gp.fluffylabs.dev/graypaper-<fullHash>.{md,pdf} URL.
  • Cmd/Ctrl-click or middle-click opens the URL in a new tab.
  • Generate PDF (dark/light/midnight) still works as before.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

    • Redesigned Markdown and PDF download controls to use native link behavior for more reliable downloads and browser compatibility.
    • Added a processing guard to prevent duplicate/concurrent downloads and to track in-progress state.
  • Bug Fixes

    • Click handling refined so modifier clicks (e.g., open in new tab) work as expected and accidental multiple activations are blocked.

Wraps the Markdown and PDF download buttons in anchor tags via
`Button asChild`, so right-click "Copy Link Address" and modifier-click
(cmd/ctrl/shift/alt) or middle-click work natively. Left-click still
uses the fetch+blob path to force the short-hash filename and
download.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 17, 2026

Deploy Preview for graypaper-reader ready!

Name Link
🔨 Latest commit 93e6dbd
🔍 Latest deploy log https://app.netlify.com/projects/graypaper-reader/deploys/69e23e9dc702a5000700a2f9
😎 Deploy Preview https://deploy-preview-409--graypaper-reader.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 17, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-view-via-url-dark-mode-linux.png is excluded by !**/*.png

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ddd01ed4-486f-44e0-89a7-0676e0ea7350

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added an isProcessingRef gate and refactored download handlers to anchor-based downloads. Left-clicks on download links are intercepted by handleLinkClick to prevent navigation, avoid concurrent downloads, and call fetchAndSave with derived URL/filename values.

Changes

Cohort / File(s) Summary
Download Modal
src/components/DownloadModal/DownloadModal.tsx
Added isProcessingRef gating; replaced button onClick handlers and disabled usage with Button asChild wrapping <a href=... download=...> anchors; introduced handleLinkClick(url, filename) to intercept unmodified left-clicks (preventDefault, check isProcessingRef, call fetchAndSave); derived pdfUrl/pdfFilename and mdUrl/mdFilename; set/cleared isProcessingRef.current in entry/finally.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 I hop through links with tiny paws,
Guarding clicks and obeying laws,
Names and hrefs all set in line,
One gentle tap — the file is mine,
A carrot cheer for downloads done! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: converting download buttons to real tags to enable native browser functionality like right-click copy-link-address, which is the primary feature described in the PR objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch td-download-links

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DownloadModal/DownloadModal.tsx`:
- Around line 60-69: handleLinkClick currently relies on the isProcessing React
state which can race on rapid clicks; add a synchronous ref latch (e.g.,
useRef<boolean>(false)) and check/ref-set it inside handleLinkClick before
calling fetchAndSave to prevent duplicate starts, then clear the latch in a
finally block after fetchAndSave completes (or on error); keep the existing
isProcessing state updates if needed but ensure the ref is the first guard so
two quick clicks cannot both proceed — reference handleLinkClick, isProcessing,
and fetchAndSave when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c269d0dc-1392-4cf8-bf6e-d716d091084a

📥 Commits

Reviewing files that changed from the base of the PR and between 95ae39b and 020e53e.

📒 Files selected for processing (1)
  • src/components/DownloadModal/DownloadModal.tsx

Comment thread src/components/DownloadModal/DownloadModal.tsx
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 17, 2026

Visual Regression Test Report ✅ Passed

Github run id: 24569172358

🔗 Artifacts: Download

`isProcessing` is React state, so two rapid clicks within the same
render cycle could both pass the guard and start duplicate downloads.
Use a ref as the synchronous gate inside both `handleLinkClick` and
`fetchAndSave`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DownloadModal/DownloadModal.tsx`:
- Line 13: Both async paths must use the same processing latch: ensure the
shared ref isProcessingRef is checked and set at the start of every entry point
(fetchAndSave, the PDF generation handler—e.g.,
generatePdf/handleGeneratePdf—and the anchor click/download handler) to prevent
concurrent starts; return early if isProcessingRef.current is true, set
isProcessingRef.current = true and setIsProcessing(true) at the start, wrap the
async work in try/finally, and in finally set isProcessingRef.current = false
and setIsProcessing(false) so the modal state is only toggled when the guarded
work completes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0c11168d-de2c-48fa-8d47-cd74ef34f11c

📥 Commits

Reviewing files that changed from the base of the PR and between 020e53e and acefd14.

⛔ Files ignored due to path filters (7)
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-header-options-menu-dark-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-header-options-menu-light-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-sidebar-overlay-closed-light-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-sidebar-overlay-light-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-view-opened-dark-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-view-via-url-dark-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-view-via-url-light-mode-linux.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • src/components/DownloadModal/DownloadModal.tsx

Comment thread src/components/DownloadModal/DownloadModal.tsx
github-actions Bot and others added 2 commits April 17, 2026 13:56
The ref guard previously only covered `fetchAndSave`, so clicking
Generate PDF didn't block a concurrent download click and whichever
finished first flipped `isProcessing` off mid-flight. Mirror the same
ref check/set in `handleGeneratePdf` so both async paths share the
latch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/DownloadModal/DownloadModal.tsx`:
- Around line 71-79: The click handler handleLinkClick currently checks for
modifier keys before checking isProcessingRef, so modified clicks will still
navigate while the component is busy; change the logic to return immediately if
isProcessingRef.current is true (i.e., gate on the busy state first) and only
perform the modifier-key early-return when not processing, and apply the same
fix to the other download link click handlers in this file that call
fetchAndSave so modifier-clicks are inert while processing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 41d1f158-fed1-4944-807a-589d116f4b7f

📥 Commits

Reviewing files that changed from the base of the PR and between acefd14 and dc7e76f.

⛔ Files ignored due to path filters (2)
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-sidebar-overlay-light-mode-linux.png is excluded by !**/*.png
  • tools/snapshot-tests/tests/split-screen.spec.ts-snapshots/split-view-opened-light-mode-linux.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • src/components/DownloadModal/DownloadModal.tsx

Comment thread src/components/DownloadModal/DownloadModal.tsx
@tomusdrw tomusdrw merged commit b67d67a into main Apr 17, 2026
5 checks passed
@tomusdrw tomusdrw deleted the td-download-links branch April 17, 2026 14:16
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.

1 participant