Skip to content

Commit 3797a4f

Browse files
committed
1 parent ab7c075 commit 3797a4f

3 files changed

Lines changed: 130 additions & 103 deletions

File tree

src/index.ts

Lines changed: 1 addition & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { InitOptions, LoadImgFn } from 'main';
22

33
import { downloadImgHeaders } from 'components/Manga';
44
import {
5-
debounce,
65
fileType,
76
isUrl,
87
log,
@@ -951,108 +950,8 @@ try {
951950

952951
default: {
953952
// #[Tachidesk](https://github.com/Suwayomi/Tachidesk-Sorayomi)
954-
if (
955-
document.querySelector(
956-
`head > meta[content="A manga reader that runs tachiyomi's extensions"]`,
957-
)
958-
) {
959-
const jump = (mangaId: number, chapterId: number) => {
960-
location.pathname = `/manga/${mangaId}/chapter/${chapterId}`;
961-
};
962-
963-
const getChapters = async (mangaId: number, chapterId: number) => {
964-
type ChapterDataRes = {
965-
data: {
966-
chapters: { nodes: { pageCount: number }[] };
967-
manga: { chapters: { totalCount: number } };
968-
};
969-
};
970-
const res = await request<ChapterDataRes>('/api/graphql', {
971-
method: 'POST',
972-
data: JSON.stringify({
973-
operationName: 'GET_CHAPTERS',
974-
query: `query GET_CHAPTERS($mangaId: Int!, $chapterId: Int!) {
975-
chapters(condition: {
976-
mangaId: $mangaId, sourceOrder: $chapterId}
977-
) { nodes { pageCount } }
978-
manga(id: $mangaId) { chapters { totalCount } }
979-
}`,
980-
variables: { mangaId, chapterId },
981-
}),
982-
responseType: 'json',
983-
});
984-
// 可能因为 Tachidesk 是在点开指定话数后才去获取数据的
985-
// 所以如果有时候会拿不到数据需要等一下
986-
if (res.response.data.chapters.nodes[0].pageCount <= 0) {
987-
await sleep(200);
988-
return getChapters(mangaId, chapterId);
989-
}
990-
return res.response.data;
991-
};
992-
993-
options = {
994-
name: 'Tachidesk',
995-
SPA: {
996-
isMangaPage: () =>
997-
/\/manga\/\d+\/chapter\/\d+/.test(location.pathname),
998-
},
999-
async getImgList({ setState }) {
1000-
const [, , mangaId, , chapterId] = location.pathname
1001-
.split('/')
1002-
.map(Number);
1003-
const data = await getChapters(mangaId, chapterId);
1004-
const [{ pageCount }] = data.chapters.nodes;
1005-
const chapterCount = data.manga.chapters.totalCount;
1006-
1007-
setState('manga', {
1008-
onPrev:
1009-
chapterId > 0 ? () => jump(mangaId, chapterId - 1) : undefined,
1010-
onNext:
1011-
chapterId < chapterCount
1012-
? () => jump(mangaId, chapterId + 1)
1013-
: undefined,
1014-
});
1015-
1016-
return range(
1017-
pageCount,
1018-
(i) => `/api/v1/manga/${mangaId}/chapter/${chapterId}/page/${i}`,
1019-
);
1020-
},
1021-
// 跟随阅读进度滚动页面,避免确保能触发 Tachidesk 的进度记录
1022-
onShowImgsChange: debounce((showImgs, imgList) => {
1023-
const lastImgUrl = imgList[[...showImgs].at(-1)!].src;
1024-
querySelector(`img[src$="${lastImgUrl}"]`)?.scrollIntoView({
1025-
behavior: 'instant',
1026-
block: 'end',
1027-
});
1028-
}, 500),
1029-
};
1030-
}
1031-
1032953
// #[LANraragi](https://github.com/Difegue/LANraragi)
1033-
const LANraragiNode = document.querySelector(
1034-
'.ip > a[href="https://github.com/Difegue/LANraragi"]',
1035-
);
1036-
if (LANraragiNode && LANraragiNode.textContent.trim() === 'LANraragi.') {
1037-
if (location.pathname !== '/reader') break;
1038-
1039-
const id = new URLSearchParams(location.search).get('id');
1040-
if (!id) {
1041-
toast.error(t('site.changed_load_failed'));
1042-
break;
1043-
}
1044-
1045-
options = {
1046-
name: 'LANraragi',
1047-
async getImgList() {
1048-
const res = await request<{ pages: string[] }>(
1049-
`/api/archives/${id}/files`,
1050-
{ responseType: 'json' },
1051-
);
1052-
return res.response.pages;
1053-
},
1054-
};
1055-
}
954+
inject('site/selfhosted');
1056955

1057956
if (!options) {
1058957
(async () => {

src/site/selfhosted.tsx

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { clamp, debounce, querySelector, range, sleep, wait } from 'helper';
2+
import { request } from 'request';
3+
4+
import type { InitOptions } from '../userscript/main';
5+
import { setState } from 'components/Manga';
6+
7+
declare let options: InitOptions; // oxlint-disable-line no-unused-vars
8+
9+
// Tachidesk
10+
11+
if (
12+
document.querySelector(
13+
`head > meta[content="A manga reader that runs tachiyomi's extensions"]`,
14+
)
15+
) {
16+
const jump = (mangaId: number, chapterId: number) => {
17+
location.pathname = `/manga/${mangaId}/chapter/${chapterId}`;
18+
};
19+
20+
const getChapters = async (mangaId: number, chapterId: number) => {
21+
type ChapterDataRes = {
22+
data: {
23+
chapters: { nodes: { pageCount: number }[] };
24+
manga: { chapters: { totalCount: number } };
25+
};
26+
};
27+
const res = await request<ChapterDataRes>('/api/graphql', {
28+
method: 'POST',
29+
data: JSON.stringify({
30+
operationName: 'GET_CHAPTERS',
31+
query: `query GET_CHAPTERS($mangaId: Int!, $chapterId: Int!) {
32+
chapters(condition: {
33+
mangaId: $mangaId, sourceOrder: $chapterId}
34+
) { nodes { pageCount } }
35+
manga(id: $mangaId) { chapters { totalCount } }
36+
}`,
37+
variables: { mangaId, chapterId },
38+
}),
39+
responseType: 'json',
40+
});
41+
// 可能因为 Tachidesk 是在点开指定话数后才去获取数据的
42+
// 所以如果有时候会拿不到数据需要等一下
43+
if (res.response.data.chapters.nodes[0].pageCount <= 0) {
44+
await sleep(200);
45+
return getChapters(mangaId, chapterId);
46+
}
47+
return res.response.data;
48+
};
49+
50+
options = {
51+
name: 'Tachidesk',
52+
SPA: {
53+
isMangaPage: () => /\/manga\/\d+\/chapter\/\d+/.test(location.pathname),
54+
},
55+
async getImgList({ setState }) {
56+
const [, , mangaId, , chapterId] = location.pathname
57+
.split('/')
58+
.map(Number);
59+
const data = await getChapters(mangaId, chapterId);
60+
const [{ pageCount }] = data.chapters.nodes;
61+
const chapterCount = data.manga.chapters.totalCount;
62+
63+
setState('manga', {
64+
onPrev: chapterId > 0 ? () => jump(mangaId, chapterId - 1) : undefined,
65+
onNext:
66+
chapterId < chapterCount
67+
? () => jump(mangaId, chapterId + 1)
68+
: undefined,
69+
});
70+
71+
return range(
72+
pageCount,
73+
(i) => `/api/v1/manga/${mangaId}/chapter/${chapterId}/page/${i}`,
74+
);
75+
},
76+
// 跟随阅读进度滚动页面,避免确保能触发 Tachidesk 的进度记录
77+
onShowImgsChange: debounce((showImgs, imgList) => {
78+
const lastImgUrl = imgList[[...showImgs].at(-1)!].src;
79+
querySelector(`img[src$="${lastImgUrl}"]`)?.scrollIntoView({
80+
behavior: 'instant',
81+
block: 'end',
82+
});
83+
}, 500),
84+
};
85+
}
86+
87+
// LANraragi
88+
89+
declare let Reader:
90+
| {
91+
id: string;
92+
pages: string[];
93+
currentPage: number;
94+
maxPage: number;
95+
updateProgress: () => void;
96+
}
97+
| undefined;
98+
99+
if (
100+
location.pathname === '/reader' &&
101+
document
102+
.querySelector('.ip > a[href="https://github.com/Difegue/LANraragi"]')
103+
?.textContent.trim() === 'LANraragi.'
104+
) {
105+
let initFlag = true;
106+
107+
options = {
108+
name: 'LANraragi',
109+
getImgList: () => wait(() => Reader?.pages),
110+
onShowImgsChange: debounce((showImgs, imgList) => {
111+
if (!Reader) return;
112+
113+
// 在刚打开时跳到 LANraragi 记录的进度
114+
if (imgList.length > 0 && initFlag) {
115+
initFlag = false;
116+
setState((state) => {
117+
state.activePageIndex = state.pageList.findIndex((page) =>
118+
page.includes(Reader.currentPage),
119+
);
120+
});
121+
}
122+
123+
// 同步更新阅读进度
124+
Reader.currentPage = clamp(0, [...showImgs].at(-1)!, Reader.maxPage);
125+
Reader.updateProgress();
126+
}, 200),
127+
};
128+
}

src/userscript/main/universal.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const universal = async ({
5757

5858
setState('comicMap', '', { getImgList: () => getImgList(mainContext) });
5959

60-
setState('manga', 'onShowImgsChange', onShowImgsChange);
60+
setState('manga', { onShowImgsChange });
6161
if (onExit)
6262
setState('manga', {
6363
onExit: (isEnd?: boolean) => {

0 commit comments

Comments
 (0)