From 39752b2c5f00175eb07c700f97f886679f938853 Mon Sep 17 00:00:00 2001 From: wukko Date: Mon, 20 Jan 2025 21:26:55 +0600 Subject: [PATCH] web/Omnibox: improve pasting links from clipboard - `text/uri-list` type is now accepted (such as clipboard data from bluesky) - http links are now allowed (such as those from rednote) - rednote share link is properly extracted --- web/src/components/save/Omnibox.svelte | 25 ++++++++++++++----------- web/src/lib/clipboard.ts | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 web/src/lib/clipboard.ts diff --git a/web/src/components/save/Omnibox.svelte b/web/src/components/save/Omnibox.svelte index 8da051d4..c10db574 100644 --- a/web/src/components/save/Omnibox.svelte +++ b/web/src/components/save/Omnibox.svelte @@ -11,6 +11,7 @@ import dialogs from "$lib/state/dialogs"; import { link } from "$lib/state/omnibox"; import { updateSetting } from "$lib/state/settings"; + import { pasteLinkFromClipboard } from "$lib/clipboard"; import { turnstileEnabled, turnstileSolved } from "$lib/state/turnstile"; import type { Optional } from "$lib/types/generic"; @@ -41,7 +42,7 @@ const validLink = (url: string) => { try { - return /^https:/i.test(new URL(url).protocol); + return /^https?\:/i.test(new URL(url).protocol); } catch {} }; @@ -59,22 +60,24 @@ goto("/", { replaceState: true }); } - const pasteClipboard = () => { + const pasteClipboard = async () => { if ($dialogs.length > 0 || isDisabled || isLoading) { return; } - navigator.clipboard.readText().then(async (text: string) => { - let matchLink = text.match(/https:\/\/[^\s]+/g); - if (matchLink) { - $link = matchLink[0]; + const pastedData = await pasteLinkFromClipboard(); + if (!pastedData) return; - if (!isBotCheckOngoing) { - await tick(); // wait for button to render - downloadButton.download($link); - } + const linkMatch = pastedData.match(/https?\:\/\/[^\s]+/g); + + if (linkMatch) { + $link = linkMatch[0].split(',')[0]; + + if (!isBotCheckOngoing) { + await tick(); // wait for button to render + downloadButton.download($link); } - }); + } }; const changeDownloadMode = (mode: DownloadModeOption) => { diff --git a/web/src/lib/clipboard.ts b/web/src/lib/clipboard.ts new file mode 100644 index 00000000..221d17ae --- /dev/null +++ b/web/src/lib/clipboard.ts @@ -0,0 +1,17 @@ +const allowedLinkTypes = new Set(["text/plain", "text/uri-list"]); + +export const pasteLinkFromClipboard = async () => { + const clipboard = await navigator.clipboard.read(); + + if (clipboard?.length) { + const clipboardItem = clipboard[0]; + for (const type of clipboardItem.types) { + if (allowedLinkTypes.has(type)) { + const blob = await clipboardItem.getType(type); + const blobText = await blob.text(); + + return blobText; + } + } + } +}