fix: 修复漫画阅读器卡死并支持章节直读
This commit is contained in:
@@ -51,14 +51,14 @@ app.whenReady().then(async () => {
|
||||
const mangaDex = require(path.join(ROOT, 'src', 'sources', 'mangadex'));
|
||||
mangaDex.chapters = async () => ({
|
||||
items: [
|
||||
{ chapterId: 'online-c1', label: '在线第 1 话', pages: 1 },
|
||||
{ chapterId: 'online-c2', label: '在线第 2 话', pages: 1 }
|
||||
{ chapterId: 'online-c1', label: '在线第 1 话', pages: 8 },
|
||||
{ chapterId: 'online-c2', label: '在线第 2 话', pages: 8 }
|
||||
],
|
||||
page: 1,
|
||||
maxPage: 1
|
||||
});
|
||||
mangaDex.chapterImageUrls = async () => ({
|
||||
urls: [imageUrl],
|
||||
urls: Array(8).fill(imageUrl),
|
||||
mustReport: false,
|
||||
quality: 'dataSaver'
|
||||
});
|
||||
@@ -125,6 +125,7 @@ app.whenReady().then(async () => {
|
||||
mangaId: 'online-manga',
|
||||
title: '在线阅读夹具',
|
||||
authors: ['测试作者'],
|
||||
initialChapterId: 'online-c2',
|
||||
language: 'zh',
|
||||
quality: 'dataSaver'
|
||||
})`);
|
||||
@@ -137,30 +138,37 @@ app.whenReady().then(async () => {
|
||||
try {
|
||||
firstChapter = await waitUntil(() => onlineWindow.webContents.executeJavaScript(
|
||||
`document.querySelectorAll('.chapter-item').length === 2
|
||||
&& document.querySelector('.manga-page img')
|
||||
&& document.querySelector('.manga-page img').naturalWidth > 0`
|
||||
&& document.getElementById('chapterTitle').textContent === '在线第 2 话'
|
||||
&& Array.from(document.querySelectorAll('.manga-page img'))
|
||||
.filter((image) => image.naturalWidth > 0).length >= 4`
|
||||
));
|
||||
} catch (error) { /* 由下面的诊断状态报告 */ }
|
||||
const onlineState = await onlineWindow.webContents.executeJavaScript(`(() => ({
|
||||
status: document.getElementById('readerStatus').textContent,
|
||||
statusHidden: document.getElementById('readerStatus').classList.contains('hidden'),
|
||||
chapterTitle: document.getElementById('chapterTitle').textContent,
|
||||
chapters: document.querySelectorAll('.chapter-item').length,
|
||||
pages: document.querySelectorAll('.manga-page').length,
|
||||
scrollTop: document.getElementById('pageScroller').scrollTop,
|
||||
pageState: document.querySelector('.manga-page')?.dataset.state || '',
|
||||
pageText: document.querySelector('.manga-page')?.dataset.placeholder || ''
|
||||
}))()`);
|
||||
check('在线阅读器读取整部章节目录并通过主进程显示图片',
|
||||
!!firstChapter, JSON.stringify(onlineState));
|
||||
let secondChapter = false;
|
||||
check('章节阅读入口会直接打开指定章节',
|
||||
firstChapter && onlineState.chapterTitle === '在线第 2 话', JSON.stringify(onlineState));
|
||||
check('漫画长图异步展开时停留在章节第一页',
|
||||
firstChapter && onlineState.scrollTop === 0, JSON.stringify(onlineState));
|
||||
let previousChapter = false;
|
||||
if (firstChapter) {
|
||||
await onlineWindow.webContents.executeJavaScript(`document.getElementById('nextChapterBtn').click()`);
|
||||
secondChapter = await waitUntil(() => onlineWindow.webContents.executeJavaScript(`(() => {
|
||||
await onlineWindow.webContents.executeJavaScript(`document.getElementById('prevChapterBtn').click()`);
|
||||
previousChapter = await waitUntil(() => onlineWindow.webContents.executeJavaScript(`(() => {
|
||||
const image = document.querySelector('.manga-page img');
|
||||
return document.getElementById('chapterTitle').textContent === '在线第 2 话'
|
||||
return document.getElementById('chapterTitle').textContent === '在线第 1 话'
|
||||
&& image && image.naturalWidth > 0;
|
||||
})()`));
|
||||
}
|
||||
check('在线阅读器可连续切换到下一章', secondChapter);
|
||||
check('在线阅读器可连续切换到上一章', previousChapter);
|
||||
const afterOnline = await win.webContents.executeJavaScript(
|
||||
`window.api.library.list().then((result) => result.data.length)`
|
||||
);
|
||||
|
||||
@@ -368,6 +368,25 @@ test('标准构建入口固定输出目录并保留便携数据', () => {
|
||||
assert.doesNotMatch(build, /\$\{PRODUCT\}-\$\{pkg\.version\}/);
|
||||
});
|
||||
|
||||
test('所有构建与发布入口都包含在线漫画 preload', () => {
|
||||
const root = path.join(__dirname, '..', '..');
|
||||
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
||||
const portable = fs.readFileSync(path.join(root, 'build-portable.js'), 'utf8');
|
||||
const mac = fs.readFileSync(path.join(root, 'build-mac.js'), 'utf8');
|
||||
const linux = fs.readFileSync(path.join(root, 'build-linux.js'), 'utf8');
|
||||
const release = fs.readFileSync(path.join(root, 'build-release.js'), 'utf8');
|
||||
|
||||
assert.ok(pkg.build.files.includes('manga-online-preload.js'));
|
||||
for (const [name, source] of [['Windows', portable], ['macOS', mac], ['Linux', linux]]) {
|
||||
assert.match(source, /manga-online-preload\.js/, `${name} 构建漏掉在线漫画 preload`);
|
||||
}
|
||||
assert.strictEqual(
|
||||
(release.match(/resources\/app\/manga-online-preload\.js/g) || []).length,
|
||||
2,
|
||||
'Windows 与 Linux 发布件回读都必须检查在线漫画 preload'
|
||||
);
|
||||
});
|
||||
|
||||
function loadPathResolvers(platform, isPackaged) {
|
||||
return h.extractFns(
|
||||
mainFile,
|
||||
|
||||
@@ -36,10 +36,12 @@ test('在线漫画会话与窗口 sender 绑定,并只授权目录里可用的
|
||||
const created = sessions.create(11, source(), {
|
||||
mangaId: 'manga-1',
|
||||
title: '在线漫画',
|
||||
initialChapterId: 'c1',
|
||||
language: 'zh-hk',
|
||||
quality: 'data'
|
||||
});
|
||||
assert.strictEqual(created.title, '在线漫画');
|
||||
assert.strictEqual(created.initialChapterId, 'c1');
|
||||
assert.strictEqual(created.quality, 'data');
|
||||
await assert.rejects(
|
||||
Promise.resolve().then(() => sessions.meta(12, created.sessionId)),
|
||||
|
||||
@@ -272,11 +272,14 @@ test('漫画源按分类显示,MangaDex 可筛选中文章节并设置图片
|
||||
test('漫画详情提供不入库的整部在线阅读器,并通过独立 preload 懒加载图片', () => {
|
||||
const html = fs.readFileSync(path.join(__dirname, '..', 'ui', 'manga-online.html'), 'utf8');
|
||||
const script = fs.readFileSync(path.join(__dirname, '..', 'ui', 'manga-online.js'), 'utf8');
|
||||
const mangaCss = fs.readFileSync(path.join(__dirname, '..', 'ui', 'manga-online.css'), 'utf8');
|
||||
const browse = fs.readFileSync(path.join(__dirname, '..', 'ui', 'views', 'browse.js'), 'utf8');
|
||||
const preload = fs.readFileSync(path.join(__dirname, '..', '..', 'manga-online-preload.js'), 'utf8');
|
||||
|
||||
assert.match(browse, /id="onlineReadBtn">在线阅读整部漫画/);
|
||||
assert.match(browse, /window\.api\.sources\.readOnline\(state\.activeSourceId/);
|
||||
assert.match(browse, /data-chapter-read=/);
|
||||
assert.match(browse, /initialChapterId: chapter && chapter\.chapterId/);
|
||||
assert.doesNotMatch(browse.slice(browse.indexOf('async function readOnline'), browse.indexOf('async function loadChapters')), /library\.add/);
|
||||
assert.match(html, /Content-Security-Policy" content="default-src 'self'; img-src 'self' blob: data:/);
|
||||
assert.match(html, /id="chapterList"/);
|
||||
@@ -284,6 +287,8 @@ test('漫画详情提供不入库的整部在线阅读器,并通过独立 prel
|
||||
assert.match(script, /new IntersectionObserver/);
|
||||
assert.match(script, /URL\.createObjectURL\(new Blob/);
|
||||
assert.match(script, /ensureNextChapter/);
|
||||
assert.match(script, /state\.meta\.initialChapterId/);
|
||||
assert.match(mangaCss, /\.page-scroller\s*\{[^}]*overflow-anchor:\s*none/);
|
||||
assert.match(preload, /mangaOnline:image/);
|
||||
assert.doesNotMatch(preload, /library:|reader:bytes|shell:openPath/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user