feat: 集成漫画源并支持在线阅读

This commit is contained in:
lofyer
2026-08-08 19:32:47 +08:00
parent c2292da442
commit 87dcc307e6
30 changed files with 3681 additions and 58 deletions
+32 -5
View File
@@ -1,15 +1,25 @@
const { contextBridge, ipcRenderer } = require('electron');
let downloadSeq = 0;
function runDownload(requestId, url, suggestName, entryId, extraHeaders, meta, onProgress) {
function invokeWithProgress(progressChannel, invokeChannel, requestId, args, onProgress) {
const listener = (_event, data) => {
if (!data || data.requestId !== requestId || typeof onProgress !== 'function') return;
try { onProgress(data); } catch (e) { /* 渲染层进度回调异常不影响下载 */ }
};
if (typeof onProgress === 'function') ipcRenderer.on('download:progress', listener);
if (typeof onProgress === 'function') ipcRenderer.on(progressChannel, listener);
return ipcRenderer
.invoke('download:file', url, suggestName, entryId, extraHeaders, meta, requestId)
.finally(() => ipcRenderer.removeListener('download:progress', listener));
.invoke(invokeChannel, ...args, requestId)
.finally(() => ipcRenderer.removeListener(progressChannel, listener));
}
function runDownload(requestId, url, suggestName, entryId, extraHeaders, meta, onProgress) {
return invokeWithProgress(
'download:progress',
'download:file',
requestId,
[url, suggestName, entryId, extraHeaders, meta],
onProgress
);
}
function downloadFile(url, suggestName, entryId, extraHeaders, meta, onProgress) {
@@ -40,13 +50,30 @@ function captureReaderRect(rect) {
return ipcRenderer.invoke('reader:captureRect', area);
}
let chapterDownloadSeq = 0;
function runChapterDownload(sourceId, payload, onProgress) {
const requestId = `chapter_${Date.now().toString(36)}_${(++chapterDownloadSeq).toString(36)}`;
return invokeWithProgress(
'source:chapterProgress',
'source:downloadChapter',
requestId,
[sourceId, payload],
onProgress
);
}
contextBridge.exposeInMainWorld('api', {
sources: {
list: () => ipcRenderer.invoke('sources:list'),
browse: (sourceId, page) => ipcRenderer.invoke('source:list', sourceId, page),
search: (sourceId, keyword, page) => ipcRenderer.invoke('source:search', sourceId, keyword, page),
detail: (sourceId, postId) => ipcRenderer.invoke('source:detail', sourceId, postId),
download: (sourceId, postId) => ipcRenderer.invoke('source:download', sourceId, postId)
download: (sourceId, postId) => ipcRenderer.invoke('source:download', sourceId, postId),
chapters: (sourceId, postId, page, options) => (
ipcRenderer.invoke('source:chapters', sourceId, postId, page, options)
),
readOnline: (sourceId, input) => ipcRenderer.invoke('source:readOnline', sourceId, input),
downloadChapter: (sourceId, payload, onProgress) => runChapterDownload(sourceId, payload, onProgress)
},
library: {
list: () => ipcRenderer.invoke('library:list'),