Skip to content

Commit e1d253f

Browse files
committed
Refacto Mangademon Tweaks
1 parent de210bc commit e1d253f

2 files changed

Lines changed: 158 additions & 82 deletions

File tree

user.js/[MangaDemon] Tweaks.user.js

Lines changed: 155 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -7,66 +7,130 @@
77
// @license GPL-3.0 License
88
// @tag kevingrillet
99
// @tag mangademon.com
10-
// @version 0.5.5
10+
// @version 1.0
1111

1212
// @homepageURL https://github.com/kevingrillet/Userscripts/
1313
// @supportURL https://github.com/kevingrillet/Userscripts/issues
1414
// @downloadURL https://raw.githubusercontent.com/kevingrillet/Userscripts/main/user.js/[MangaDemon]%20Tweaks.user.js
1515
// @updateURL https://raw.githubusercontent.com/kevingrillet/Userscripts/main/user.js/[MangaDemon]%20Tweaks.user.js
1616

17+
// @match https://ciorti.online/*
1718
// @match https://comicdemons.com/*
1819
// @match https://demoncomics.org/*
20+
// @match https://demonicscans.org/*
1921
// @match https://demonreader.org/*
2022
// @match https://demontoon.com/*
2123
// @match https://manga-demon.org/*
2224
// @match https://mgdemon.org/*
2325
// @icon https://www.google.com/s2/favicons?sz=64&domain=demoncomics.org
24-
// @grant none
26+
// @grant GM_registerMenuCommand
2527
// @run-at document-end
2628
// ==/UserScript==
2729

2830
(function () {
2931
'use strict';
3032

33+
// Configuration constants
34+
const CONFIG = {
35+
AUTO_NEXT_SPEED: 0.5 * 1000, // 0.5s
36+
AUTO_NEXT_BOOKMARK_SPEED: 1 * 1000, // 1s
37+
SCROLL_SPEED: 1000 / 60, // ~16.67ms (60fps)
38+
SCROLL_VALUE: 48, // pixels per scroll
39+
PRERENDER_TYPE: 'prerender', // or 'prefetch'
40+
ENABLE_REL: true, // enable/disable rel attribute
41+
};
42+
43+
const KEYS = {
44+
PREVIOUS: ['ArrowLeft', 'KeyA', 'KeyQ'],
45+
SCROLL_UP: ['ArrowUp', 'KeyW', 'KeyZ'],
46+
NEXT: ['ArrowRight', 'KeyD'],
47+
SCROLL_DOWN: ['ArrowDown', 'KeyS'],
48+
};
49+
50+
const SELECTORS = {
51+
BOOKMARKS_CONTAINER: '#bookmarks-container',
52+
BUTTON_NEXT: '.nextchap',
53+
BUTTON_PREVIOUS: '.prevchap',
54+
CHAPTER_TITLE: 'h1',
55+
PROGRESS_BAR: '#my_progress_bar',
56+
UPDATES_CHECK: '.updates-check-available span',
57+
};
58+
3159
/** BOOKMARK SECTION */
3260
function sortBookmarks() {
61+
const container = document.querySelector(SELECTORS.BOOKMARKS_CONTAINER);
62+
if (!container) {
63+
console.warn('[MangaDemon Tweaks] Bookmarks container not found');
64+
return;
65+
}
66+
67+
function extractChapterNumber(text) {
68+
return Number(text?.replace(/[^0-9.-]+/g, '') || 0);
69+
}
70+
3371
function sortFunc(a, b) {
34-
let aCard = a.querySelectorAll('.chapternumber'),
35-
bCard = b.querySelectorAll('.chapternumber');
36-
37-
let aVal = Number(aCard[1].innerText.replace('Last Chapter ', '')) - Number(aCard[0].innerText.replace('Last Chapter Read ', '')),
38-
bVal = Number(bCard[1].innerText.replace('Last Chapter ', '')) - Number(bCard[0].innerText.replace('Last Chapter Read ', ''));
39-
40-
if (aVal !== 0 && bVal !== 0 && aVal !== bVal) {
41-
return aVal - bVal;
42-
} else if (aVal === 0 && bVal !== 0) {
43-
return 1;
44-
} else if (aVal !== 0 && bVal === 0) {
45-
return -1;
46-
}
47-
let aTitle = a.querySelector('.novel-title').innerText,
48-
bTitle = b.querySelector('.novel-title').innerText;
72+
const aCard = a.querySelectorAll(SELECTORS.UPDATES_CHECK);
73+
const bCard = b.querySelectorAll(SELECTORS.UPDATES_CHECK);
74+
75+
const aVal = extractChapterNumber(aCard[1]?.innerText) - extractChapterNumber(aCard[0]?.innerText);
76+
const bVal = extractChapterNumber(bCard[1]?.innerText) - extractChapterNumber(bCard[0]?.innerText);
77+
78+
if (aVal !== 0 && bVal !== 0 && aVal !== bVal) return aVal - bVal;
79+
if (aVal === 0 && bVal !== 0) return 1;
80+
if (aVal !== 0 && bVal === 0) return -1;
81+
82+
const aTitle = a.querySelector(SELECTORS.CHAPTER_TITLE)?.innerText || '';
83+
const bTitle = b.querySelector(SELECTORS.CHAPTER_TITLE)?.innerText || '';
4984
return aTitle.localeCompare(bTitle);
5085
}
5186

52-
let elUl = document.querySelector(':scope .latestupdates ul');
53-
54-
Array.from(elUl.getElementsByTagName('li'))
55-
.sort((a, b) => sortFunc(a, b))
56-
.forEach((elLi) => elUl.appendChild(elLi));
87+
const items = Array.from(container.getElementsByTagName('li'));
88+
items.sort(sortFunc).forEach((item) => container.appendChild(item));
5789
}
5890

5991
/** CHAPTEUR SECTION */
60-
var autoNextSpeed = 0.5 * 1000, // .5 s
61-
autoNextBookmarkSpeed = 1 * 1000, // +1 s
62-
buttonNext = document.querySelector('.nextchap'),
63-
buttonPrevious = document.querySelector('.prevchap'),
64-
doRel = true, // does rel is added on scroll
65-
head = document.head,
66-
rel = 'prerender', // prerender/prefetch;
67-
scrollInterval,
68-
scrollSpeed = 1000 / 60, // 1/60 s
69-
scrollValue = 48; // px;
92+
const NAVIGATION = {
93+
next: document.querySelector(SELECTORS.BUTTON_NEXT),
94+
previous: document.querySelector(SELECTORS.BUTTON_PREVIOUS),
95+
};
96+
97+
let scrollInterval;
98+
99+
function _get_window_height() {
100+
return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0;
101+
}
102+
103+
function _get_window_Yscroll() {
104+
return window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0;
105+
}
106+
function _get_doc_height() {
107+
return Math.max(
108+
document.body.scrollHeight || 0,
109+
document.documentElement.scrollHeight || 0,
110+
document.body.offsetHeight || 0,
111+
document.documentElement.offsetHeight || 0,
112+
document.body.clientHeight || 0,
113+
document.documentElement.clientHeight || 0
114+
);
115+
}
116+
117+
function _get_scroll_percentage() {
118+
try {
119+
const windowScroll = _get_window_Yscroll();
120+
const windowHeight = _get_window_height();
121+
const docHeight = _get_doc_height();
122+
123+
if (docHeight === 0) {
124+
console.warn('[MangaDemon Tweaks] Invalid document height');
125+
return 0;
126+
}
127+
128+
return ((windowScroll + windowHeight) / docHeight) * 100;
129+
} catch (error) {
130+
console.error('[MangaDemon Tweaks] Error calculating scroll percentage:', error);
131+
return 0;
132+
}
133+
}
70134

71135
function addProgressBar() {
72136
let elDiv = document.body.appendChild(document.createElement('div'));
@@ -103,20 +167,16 @@
103167
}`);
104168

105169
let processScroll = () => {
106-
let docElem = document.documentElement,
107-
docBody = document.body,
108-
scrollTop = docElem.scrollTop || docBody.scrollTop,
109-
scrollBottom = (docElem.scrollHeight || docBody.scrollHeight) - window.innerHeight,
110-
scrollPercent = (scrollTop / scrollBottom) * 100 + '%';
111-
document.getElementById('my_progress_bar').style.setProperty('--scrollAmount', scrollPercent);
112-
document.getElementById('my_progress_bar').innerHTML = Math.round((scrollTop / scrollBottom) * 100) + '%';
170+
let scrollPercent = _get_scroll_percentage() - 1;
171+
document.getElementById(SELECTORS.PROGRESS_BAR).style.setProperty('--scrollAmount', scrollPercent + '%');
172+
document.getElementById(SELECTORS.PROGRESS_BAR).innerHTML = Math.round(scrollPercent) + '%';
113173
};
114174

115175
document.addEventListener('scroll', processScroll);
116176
}
117177

118178
function addStyles(css) {
119-
let style = head.appendChild(document.createElement('style'));
179+
let style = document.head.appendChild(document.createElement('style'));
120180
style.type = 'text/css';
121181
style.innerHTML = css;
122182
}
@@ -126,42 +186,42 @@
126186
if (Math.round(window.innerHeight + window.scrollY) >= document.body.offsetHeight - 10) {
127187
setTimeout(function () {
128188
if (Math.round(window.innerHeight + window.scrollY) >= document.body.offsetHeight - 10) {
129-
if (buttonNext && buttonNext !== undefined) {
189+
if (NAVIGATION.next && NAVIGATION.next !== undefined) {
130190
goNext();
131191
} else {
132192
setTimeout(function () {
133193
goBookmark();
134-
}, autoNextBookmarkSpeed); // wait 4 secs
194+
}, CONFIG.AUTO_NEXT_BOOKMARK_SPEED); // wait 4 secs
135195
}
136196
}
137-
}, autoNextSpeed); // wait 1 secs
197+
}, CONFIG.AUTO_NEXT_SPEED); // wait 1 secs
138198
}
139199
}
140200

141201
function goBookmark() {
142-
window.location.href = window.location.origin + '/following.php';
202+
window.location.href = window.location.origin + '/bookmarks.php';
143203
}
144204
function goNext() {
145-
if (buttonNext) {
146-
buttonNext.click();
205+
if (NAVIGATION.next?.href) {
206+
window.location.href = NAVIGATION.next.href;
147207
}
148208
}
149209
function goPrevious() {
150-
if (buttonPrevious) {
151-
buttonPrevious.click();
210+
if (NAVIGATION.previous?.href) {
211+
window.location.href = NAVIGATION.previous.href;
152212
}
153213
}
154214

155215
function prerender(force) {
156-
if (!doRel) return;
216+
if (!CONFIG.ENABLE_REL) return;
157217
force = force || false;
158-
if (buttonNext && buttonNext !== undefined) {
159-
if (buttonNext.rel === 'nofollow') {
218+
if (NAVIGATION.next && NAVIGATION.next !== undefined) {
219+
if (NAVIGATION.next.rel === 'nofollow') {
160220
if (force || Math.round(window.innerHeight + window.scrollY) >= document.body.offsetHeight * 0.75) {
161-
let link = head.appendChild(document.createElement('link'));
162-
link.setAttribute('rel', rel);
163-
link.setAttribute('href', buttonNext.href);
164-
buttonNext.setAttribute('rel', rel);
221+
let link = document.head.appendChild(document.createElement('link'));
222+
link.setAttribute('rel', CONFIG.PRERENDER_TYPE);
223+
link.setAttribute('href', NAVIGATION.next.href);
224+
NAVIGATION.next.setAttribute('rel', CONFIG.PRERENDER_TYPE);
165225
console.debug('Prerender added.');
166226
}
167227
}
@@ -170,47 +230,62 @@
170230
function startScrolling(value) {
171231
scrollInterval = setInterval(function () {
172232
window.scrollBy(0, value);
173-
}, scrollSpeed);
233+
}, CONFIG.SCROLL_SPEED);
174234
}
175235
function stopScrolling() {
176236
clearInterval(scrollInterval);
177237
scrollInterval = null;
178238
}
179239

240+
function handleKeyDown(event) {
241+
if (event.ctrlKey || event.code === 'MetaLeft' || event.code === 'MetaRight') {
242+
return;
243+
}
244+
245+
if (KEYS.PREVIOUS.includes(event.code)) {
246+
goPrevious();
247+
} else if (KEYS.SCROLL_UP.includes(event.code)) {
248+
stopScrolling();
249+
startScrolling(-CONFIG.SCROLL_VALUE);
250+
} else if (KEYS.NEXT.includes(event.code)) {
251+
goNext();
252+
} else if (KEYS.SCROLL_DOWN.includes(event.code)) {
253+
stopScrolling();
254+
startScrolling(CONFIG.SCROLL_VALUE);
255+
}
256+
}
257+
258+
function handleKeyUp(event) {
259+
if (KEYS.SCROLL_UP.includes(event.code) || KEYS.SCROLL_DOWN.includes(event.code)) {
260+
stopScrolling();
261+
}
262+
}
263+
264+
const PAGE_TYPE = {
265+
isBookmarkPage: () => window.location.href.includes('/bookmarks.php'),
266+
isChapterPage: () => window.location.href.includes('/title/') && window.location.href.includes('/chapter/'),
267+
};
268+
180269
/** MAIN SECTION */
181270
window.addEventListener('load', function () {
182-
if (window.location.href.indexOf('/following.php') > -1) {
271+
if (PAGE_TYPE.isBookmarkPage()) {
183272
sortBookmarks();
184-
} else if (window.location.href.indexOf('/manga/') > -1 && window.location.href.indexOf('/chapter/') > -1) {
273+
} else if (PAGE_TYPE.isChapterPage()) {
185274
addProgressBar();
186275

187276
window.onscroll = function () {
188277
autoNext();
189278
prerender();
190279
};
191280

192-
document.addEventListener('keydown', (event) => {
193-
if (event.ctrlKey || event.code === 'MetaLeft' || event.code === 'MetaRight') {
194-
return;
195-
}
196-
if (event.code === 'ArrowLeft' || event.code === 'KeyA' || event.code === 'KeyQ') {
197-
goPrevious();
198-
} else if (event.code === 'ArrowUp' || event.code === 'KeyW' || event.code === 'KeyZ') {
199-
stopScrolling();
200-
startScrolling(-scrollValue);
201-
} else if (event.code === 'ArrowRight' || event.code === 'KeyD') {
202-
goNext();
203-
} else if (event.code === 'ArrowDown' || event.code === 'KeyS') {
204-
stopScrolling();
205-
startScrolling(scrollValue);
206-
}
207-
});
208-
209-
document.addEventListener('keyup', (event) => {
210-
if (event.code === 'ArrowUp' || event.code === 'KeyW' || event.code === 'KeyZ' || event.code === 'ArrowDown' || event.code === 'KeyS') {
211-
stopScrolling();
212-
}
213-
});
281+
document.addEventListener('keydown', handleKeyDown);
282+
document.addEventListener('keyup', handleKeyUp);
214283
}
215284
});
285+
286+
if (PAGE_TYPE.isBookmarkPage()) {
287+
GM_registerMenuCommand('Sort bookmarks', function () {
288+
sortBookmarks();
289+
});
290+
}
216291
})();

user.js/[MangaDemon] Tweaks v2.user.js renamed to user.js/deprecated/[MangaDemon] Tweaks v2.user.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
// @license GPL-3.0 License
88
// @tag kevingrillet
99
// @tag mangademon.com
10+
// @tag deprecated
1011
// @version 0.0.3
1112

1213
// @homepageURL https://github.com/kevingrillet/Userscripts/
1314
// @supportURL https://github.com/kevingrillet/Userscripts/issues
14-
// @downloadURL https://raw.githubusercontent.com/kevingrillet/Userscripts/main/user.js/[MangaDemon]%20Tweaks%20v2.user.js
15-
// @updateURL https://raw.githubusercontent.com/kevingrillet/Userscripts/main/user.js/[MangaDemon]%20Tweaks%20v2.user.js
15+
// @downloadURL https://raw.githubusercontent.com/kevingrillet/Userscripts/main/user.js/deprecated/[MangaDemon]%20Tweaks%20v2.user.js
16+
// @updateURL https://raw.githubusercontent.com/kevingrillet/Userscripts/main/user.js/deprecated/[MangaDemon]%20Tweaks%20v2.user.js
1617

1718
// @match https://demonicscans.org/*
1819
// @match https://ciorti.online/*

0 commit comments

Comments
 (0)