feat: add duplicate bookmark check and error message for existing bookmarks

This commit is contained in:
troyeguo
2026-03-01 14:58:52 +08:00
parent e92631aa8c
commit c7ce763f4e
4 changed files with 40 additions and 13 deletions

34
main.js
View File

@@ -963,14 +963,18 @@ const createMainWin = () => {
});
ipcMain.on("get-file-data", function (event) {
if (fs.existsSync(path.join(dirPath, "log.json"))) {
const _data = JSON.parse(
fs.readFileSync(path.join(dirPath, "log.json"), "utf-8") || "{}"
);
if (_data && _data.filePath) {
filePath = _data.filePath;
setTimeout(() => {
fs.writeFileSync(path.join(dirPath, "log.json"), "", "utf-8");
}, 1000);
try {
const _data = JSON.parse(
fs.readFileSync(path.join(dirPath, "log.json"), "utf-8") || "{}"
);
if (_data && _data.filePath) {
filePath = _data.filePath;
setTimeout(() => {
fs.writeFileSync(path.join(dirPath, "log.json"), "", "utf-8");
}, 1000);
}
} catch (error) {
console.error("Error reading log.json:", error);
}
}
@@ -979,11 +983,15 @@ const createMainWin = () => {
});
ipcMain.on("check-file-data", function (event) {
if (fs.existsSync(path.join(dirPath, "log.json"))) {
const _data = JSON.parse(
fs.readFileSync(path.join(dirPath, "log.json"), "utf-8") || "{}"
);
if (_data && _data.filePath) {
filePath = _data.filePath;
try {
const _data = JSON.parse(
fs.readFileSync(path.join(dirPath, "log.json"), "utf-8") || "{}"
);
if (_data && _data.filePath) {
filePath = _data.filePath;
}
} catch (error) {
console.error("Error reading log.json:", error);
}
}

View File

@@ -28,6 +28,7 @@
"Auto open book in full screen": "图书窗口自动全屏",
"Your quota will be reset in": "您的额度将于 {{ttl}} 后重置",
"System font": "系统字体",
"Bookmark already exists": "书签已存在",
"Access token expired, refetching token": "凭证过期,重新获取中",
"Access token received, please continue": "获取凭证成功,请继续之前的操作",
"Change log": "更新日志",

View File

@@ -21,6 +21,9 @@ class Background extends React.Component<BackgroundProps, BackgroundState> {
nextProps.htmlBook.rendition.on("page-changed", async () => {
await this.handlePageNum(nextProps.htmlBook.rendition);
});
nextProps.htmlBook.rendition.on("rendered", async () => {
await this.handlePageNum(nextProps.htmlBook.rendition);
});
}
if (nextProps.readerMode !== this.props.readerMode) {
this.setState({ isSingle: nextProps.readerMode !== "double" });

View File

@@ -99,6 +99,21 @@ class OperationPanel extends React.Component<
let text = bookLocation.text;
let chapter = bookLocation.chapterTitle;
let percentage = bookLocation.percentage;
let isDuplicate = false;
let bookmarks = await DatabaseService.getRecordsByBookKey(
this.props.currentBook.key,
"bookmarks"
);
for (let i = 0; i < bookmarks.length; i++) {
if (bookmarks[i].percentage === bookLocation.percentage) {
isDuplicate = true;
break;
}
}
if (isDuplicate) {
toast.error(this.props.t("Bookmark already exists"));
return;
}
let cfi = JSON.stringify(bookLocation);
if (!text) {