From e2c102a589e33ffb0916c9b16d2ae86ca66cd307 Mon Sep 17 00:00:00 2001 From: troyeguo <13820674+troyeguo@users.noreply.github.com> Date: Sun, 17 May 2026 18:31:54 +0800 Subject: [PATCH] feat: add functionality to copy book and note links to clipboard --- main.js | 15 ++++++++ src/assets/locales/zh-CN.json | 2 ++ .../dialogs/moreAction/component.tsx | 16 +++++++++ src/containers/header/component.tsx | 35 +++++++++++++++++++ src/containers/lists/cardList/component.tsx | 21 +++++++++++ 5 files changed, 89 insertions(+) diff --git a/main.js b/main.js index ec9f6586..7b5a5ff4 100644 --- a/main.js +++ b/main.js @@ -1697,6 +1697,9 @@ const handleCallback = (url) => { const state = parsedUrl.searchParams.get("state"); const pickerData = parsedUrl.searchParams.get("pickerData"); + const bookKey = parsedUrl.searchParams.get("bookKey"); + const noteKey = parsedUrl.searchParams.get("noteKey"); + if (code && mainWin) { mainWin.webContents.send("oauth-callback", { code, state }); } @@ -1704,6 +1707,18 @@ const handleCallback = (url) => { let config = JSON.parse(decodeURIComponent(pickerData)); mainWin.webContents.send("picker-finished", config); } + if (bookKey && mainWin) { + if (mainWin.isMinimized()) mainWin.restore(); + mainWin.show(); + mainWin.focus(); + mainWin.webContents.send("open-book-from-link", { bookKey }); + } + if (noteKey && mainWin) { + if (mainWin.isMinimized()) mainWin.restore(); + mainWin.show(); + mainWin.focus(); + mainWin.webContents.send("open-note-from-link", { noteKey }); + } } catch (error) { console.error("Error handling callback URL:", error); console.info("Problematic URL:", url); diff --git a/src/assets/locales/zh-CN.json b/src/assets/locales/zh-CN.json index 14f6fe1e..f0a970fe 100644 --- a/src/assets/locales/zh-CN.json +++ b/src/assets/locales/zh-CN.json @@ -38,6 +38,8 @@ "Your quota will be reset in": "您的额度将于 {{ttl}} 小时后重置", "Minute duration": "{{tts}}分钟", "Hour duration": "{{tts}}小时", + "Copy book link": "复制图书链接", + "Copy note link": "复制笔记链接", "Automatically sync your library with cloud at the specified interval.": "按照指定的时间间隔自动与云端同步您的书库", "The new sync interval will take effect after restarting Koodo Reader": "新的同步间隔将在重启 Koodo Reader 后生效", "Scheduled sync interval": "定时同步间隔", diff --git a/src/components/dialogs/moreAction/component.tsx b/src/components/dialogs/moreAction/component.tsx index 38c2bdbd..be93e896 100644 --- a/src/components/dialogs/moreAction/component.tsx +++ b/src/components/dialogs/moreAction/component.tsx @@ -325,6 +325,22 @@ class MoreAction extends React.Component { Delete pre-cache

+
{ + const link = `koodo-reader://open-book?bookKey=${this.props.currentBook.key}`; + navigator.clipboard.writeText(link).then(() => { + toast.success(this.props.t("Copied")); + }); + this.props.handleMoreAction(false); + this.props.handleActionDialog(false); + }} + > +

+ Copy book link +

+
{isElectron && (
{ ipcRenderer.on("reading-finished", async (event: any, config: any) => { this.handleFinishReading(); }); + ipcRenderer.on( + "open-book-from-link", + async (_event: any, config: any) => { + const book = await DatabaseService.getRecord(config.bookKey, "books"); + if (book) { + BookUtil.redirectBook(book); + } + } + ); + ipcRenderer.on( + "open-note-from-link", + async (_event: any, config: any) => { + const note = await DatabaseService.getRecord(config.noteKey, "notes"); + if (!note) return; + const book = await DatabaseService.getRecord(note.bookKey, "books"); + if (!book) return; + let bookLocation: any = {}; + try { + bookLocation = JSON.parse(note.cfi) || {}; + } catch (error) { + bookLocation.cfi = note.cfi; + bookLocation.chapterTitle = note.chapter; + } + if (bookLocation.fingerprint) { + bookLocation.chapterDocIndex = bookLocation.page - 1 + ""; + bookLocation.chapterHref = "title" + (bookLocation.page - 1); + } + ConfigService.setObjectConfig( + note.bookKey, + bookLocation, + "recordLocation" + ); + BookUtil.redirectBook(book); + } + ); } else { upgradeConfig(); const status = await LocalFileManager.getPermissionStatus(); diff --git a/src/containers/lists/cardList/component.tsx b/src/containers/lists/cardList/component.tsx index b7d52db6..41585921 100644 --- a/src/containers/lists/cardList/component.tsx +++ b/src/containers/lists/cardList/component.tsx @@ -266,6 +266,27 @@ class CardList extends React.Component { }} > + + + { + const link = `koodo-reader://open-note?noteKey=${item.key}`; + navigator.clipboard.writeText(link).then(() => { + toast(this.props.t("Copied")); + }); + }} + > +