feat: add functionality to copy book and note links to clipboard

This commit is contained in:
troyeguo
2026-05-17 18:31:54 +08:00
parent 05a7750988
commit e2c102a589
5 changed files with 89 additions and 0 deletions

15
main.js
View File

@@ -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);

View File

@@ -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": "定时同步间隔",

View File

@@ -325,6 +325,22 @@ class MoreAction extends React.Component<MoreActionProps, MoreActionState> {
<Trans>Delete pre-cache</Trans>
</p>
</div>
<div
className="action-dialog-edit"
style={{ paddingLeft: "0px" }}
onClick={() => {
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);
}}
>
<p className="action-name">
<Trans>Copy book link</Trans>
</p>
</div>
{isElectron && (
<div
className="action-dialog-edit"

View File

@@ -123,6 +123,41 @@ class Header extends React.Component<HeaderProps, HeaderState> {
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();

View File

@@ -266,6 +266,27 @@ class CardList extends React.Component<CardListProps, CardListStates> {
}}
></span>
</span>
<span
data-tooltip-id="my-tooltip"
data-tooltip-content={this.props.t("Copy note link")}
>
<span
className="icon-copy-line"
style={{
fontSize: "18px",
marginLeft: "15px",
position: "relative",
top: "2px",
}}
onClick={() => {
const link = `koodo-reader://open-note?noteKey=${item.key}`;
navigator.clipboard.writeText(link).then(() => {
toast(this.props.t("Copied"));
});
}}
></span>
</span>
</div>
</div>
</li>