Skip to content
This repository was archived by the owner on Mar 23, 2025. It is now read-only.

Commit 44ff566

Browse files
committed
Merge branch 'feature/paged-reader' into dev
2 parents 16a9d7f + 853f422 commit 44ff566

File tree

6 files changed

+186
-39
lines changed

6 files changed

+186
-39
lines changed

public/js/download.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ const search = () => {
9595

9696
try {
9797
const path = new URL(input).pathname;
98-
const match = /\/title\/([0-9]+)/.exec(path);
98+
const match = /\/(?:title|manga)\/([0-9]+)/.exec(path);
9999
int_id = parseInt(match[1]);
100100
} catch (e) {
101101
int_id = parseInt(input);

public/js/reader.js

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,68 @@ let longPages = false;
55
$(() => {
66
getPages();
77

8+
const storedMode = localStorage.getItem('mode') || 'continuous';
9+
10+
setProp('mode', storedMode);
11+
updateMode(storedMode, page);
12+
$('#mode-select').val(storedMode);
13+
814
$('#page-select').change(() => {
915
const p = parseInt($('#page-select').val());
1016
toPage(p);
1117
});
18+
19+
$('#mode-select').change(() => {
20+
const mode = $('#mode-select').val();
21+
const curIdx = parseInt($('#page-select').val());
22+
23+
updateMode(mode, curIdx);
24+
});
25+
});
26+
27+
$(window).resize(() => {
28+
const mode = getProp('mode');
29+
if (mode === 'continuous') return;
30+
31+
const wideScreen = $(window).width() > $(window).height();
32+
const propMode = wideScreen ? 'height' : 'width';
33+
setProp('mode', propMode);
1234
});
1335

36+
/**
37+
* Update the reader mode
38+
*
39+
* @function updateMode
40+
* @param {string} mode - The mode. Can be one of the followings:
41+
* {'continuous', 'paged', 'height', 'width'}
42+
* @param {number} targetPage - The one-based index of the target page
43+
*/
44+
const updateMode = (mode, targetPage) => {
45+
localStorage.setItem('mode', mode);
46+
47+
// The mode to be put into the `mode` prop. It can't be `screen`
48+
let propMode = mode;
49+
50+
if (mode === 'paged') {
51+
const wideScreen = $(window).width() > $(window).height();
52+
propMode = wideScreen ? 'height' : 'width';
53+
}
54+
55+
setProp('mode', propMode);
56+
57+
if (mode === 'continuous') {
58+
waitForPage(items.length, () => {
59+
setupScroller();
60+
});
61+
}
62+
63+
waitForPage(targetPage, () => {
64+
setTimeout(() => {
65+
toPage(targetPage);
66+
}, 100);
67+
});
68+
};
69+
1470
/**
1571
* Set an alpine.js property
1672
*
@@ -22,6 +78,17 @@ const setProp = (key, prop) => {
2278
$('#root').get(0).__x.$data[key] = prop;
2379
};
2480

81+
/**
82+
* Get an alpine.js property
83+
*
84+
* @function getProp
85+
* @param {string} key - Key of the data property
86+
* @return {*} The data property
87+
*/
88+
const getProp = (key) => {
89+
return $('#root').get(0).__x.$data[key];
90+
};
91+
2592
/**
2693
* Get dimension of the pages in the entry from the API and update the view
2794
*/
@@ -50,11 +117,6 @@ const getPages = () => {
50117

51118
setProp('items', items);
52119
setProp('loading', false);
53-
54-
waitForPage(items.length, () => {
55-
toPage(page);
56-
setupScroller();
57-
});
58120
})
59121
.catch(e => {
60122
const errMsg = `Failed to get the page dimensions. ${e}`;
@@ -71,7 +133,15 @@ const getPages = () => {
71133
* @param {number} idx - One-based index of the page
72134
*/
73135
const toPage = (idx) => {
74-
$(`#${idx}`).get(0).scrollIntoView(true);
136+
const mode = getProp('mode');
137+
if (mode === 'continuous') {
138+
$(`#${idx}`).get(0).scrollIntoView(true);
139+
} else {
140+
if (idx >= 1 && idx <= items.length) {
141+
setProp('curItem', items[idx - 1]);
142+
}
143+
}
144+
replaceHistory(idx);
75145
UIkit.modal($('#modal-sections')).hide();
76146
};
77147

@@ -137,6 +207,8 @@ const replaceHistory = (idx) => {
137207
* @function setupScroller
138208
*/
139209
const setupScroller = () => {
210+
const mode = getProp('mode');
211+
if (mode !== 'continuous') return;
140212
$('#root img').each((idx, el) => {
141213
$(el).on('inview', (event, inView) => {
142214
if (inView) {
@@ -193,3 +265,30 @@ const nextEntry = (nextUrl) => {
193265
redirect(nextUrl);
194266
});
195267
};
268+
269+
/**
270+
* Show the next or the previous page
271+
*
272+
* @function flipPage
273+
* @param {bool} isNext - Whether we are going to the next page
274+
*/
275+
const flipPage = (isNext) => {
276+
const curItem = getProp('curItem');
277+
const idx = parseInt(curItem.id);
278+
const delta = isNext ? 1 : -1;
279+
const newIdx = idx + delta;
280+
281+
toPage(newIdx);
282+
283+
if (isNext)
284+
setProp('flipAnimation', 'right');
285+
else
286+
setProp('flipAnimation', 'left');
287+
288+
setTimeout(() => {
289+
setProp('flipAnimation', null);
290+
}, 500);
291+
292+
replaceHistory(newIdx);
293+
saveProgress(newIdx);
294+
};

src/config.cr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class Config
1818
home: true
1919
property plugin_path : String = File.expand_path "~/mango/plugins",
2020
home: true
21+
property download_timeout_seconds : Int32 = 30
2122
property mangadex = Hash(String, String | Int32).new
2223

2324
@[YAML::Field(ignore: true)]

src/util/proxy.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ require "http_proxy"
55
module HTTP
66
class Client
77
private def self.exec(uri : URI, tls : TLSContext = nil)
8-
Logger.debug "Using monkey-patched HTTP::Client"
8+
Logger.debug "Setting proxy"
99
previous_def uri, tls do |client, path|
1010
client.set_proxy get_proxy uri
1111
yield client, path

src/util/web.cr

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,15 @@ macro get_sort_opt
8181
sort_opt = SortOptions.new sort_method, is_ascending
8282
end
8383
end
84+
85+
module HTTP
86+
class Client
87+
private def self.exec(uri : URI, tls : TLSContext = nil)
88+
Logger.debug "Setting read timeout"
89+
previous_def uri, tls do |client, path|
90+
client.read_timeout = Config.current.download_timeout_seconds.seconds
91+
yield client, path
92+
end
93+
end
94+
end
95+
end

src/views/reader.html.ecr

Lines changed: 66 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,67 @@
33

44
<%= render_component "head" %>
55

6-
<body>
7-
<div class="uk-section uk-section-default uk-section-small reader-bg">
6+
<body style="position:relative;">
7+
<div class="uk-section uk-section-default uk-section-small reader-bg"
8+
id="root"
9+
:style="mode === 'continuous' ? '' : 'padding:0'"
10+
x-data="{
11+
loading: true,
12+
mode: 'continuous', // can be 'continuous', 'height' or 'width'
13+
msg: 'Loading the web reader. Please wait...',
14+
alertClass: 'uk-alert-primary',
15+
items: [],
16+
curItem: {},
17+
flipAnimation: null
18+
}">
19+
820
<div class="uk-container uk-container-small">
921
<div id="alert"></div>
10-
<div id="root" x-data="{
11-
loading: true,
12-
msg: 'Loading the web reader. Please wait...',
13-
alertClass: 'uk-alert-primary',
14-
items: []
15-
}">
16-
<div x-show="loading">
17-
<div :class="alertClass" x-show="msg" uk-alert>
18-
<p x-text="msg"></p>
19-
</div>
20-
</div>
21-
<div x-show="!loading" x-cloak>
22-
<template x-for="item in items">
23-
<img
24-
uk-img
25-
class="uk-align-center"
26-
:data-src="item.url"
27-
:width="item.width"
28-
:height="item.height"
29-
:id="item.id"
30-
@click="showControl($event)"
31-
/>
32-
</template>
33-
<%- if next_entry_url -%>
34-
<button id="next-btn" class="uk-align-center uk-button uk-button-primary" @click="nextEntry('<%= next_entry_url %>')">Next Entry</button>
35-
<%- else -%>
36-
<button id="next-btn" class="uk-align-center uk-button uk-button-primary" @click="redirect('<%= exit_url %>')">Exit Reader</button>
37-
<%- end -%>
22+
<div x-show="loading">
23+
<div :class="alertClass" x-show="msg" uk-alert>
24+
<p x-text="msg"></p>
3825
</div>
3926
</div>
4027
</div>
28+
29+
<div
30+
:class="{'uk-container': true, 'uk-container-small': mode === 'continuous', 'uk-container-expand': mode !== 'continuous'}">
31+
<div x-show="!loading && mode === 'continuous'" x-cloak>
32+
<template x-for="item in items">
33+
<img
34+
uk-img
35+
class="uk-align-center"
36+
:data-src="item.url"
37+
:width="item.width"
38+
:height="item.height"
39+
:id="item.id"
40+
@click="showControl($event)"
41+
/>
42+
</template>
43+
<%- if next_entry_url -%>
44+
<button id="next-btn" class="uk-align-center uk-button uk-button-primary" @click="nextEntry('<%= next_entry_url %>')">Next Entry</button>
45+
<%- else -%>
46+
<button id="next-btn" class="uk-align-center uk-button uk-button-primary" @click="redirect('<%= exit_url %>')">Exit Reader</button>
47+
<%- end -%>
48+
</div>
49+
50+
<div x-cloak x-show="!loading && mode !== 'continuous'" class="uk-flex uk-flex-middle" style="height:100vh">
51+
52+
<img uk-img :class="{
53+
'uk-align-center': true,
54+
'uk-animation-slide-left': flipAnimation === 'left',
55+
'uk-animation-slide-right': flipAnimation === 'right'
56+
}" :data-src="curItem.url" :width="curItem.width" :height="curItem.height" :id="curItem.id" @click="showControl($event)" :style="`
57+
width:${mode === 'width' ? '100vw' : 'auto'};
58+
height:${mode === 'height' ? '100vh' : 'auto'};
59+
margin-bottom:0;
60+
`" />
61+
62+
<div style="position:absolute;z-index:1; top:0;left:0; width:30%;height:100%;" @click="flipPage(false)"></div>
63+
<div style="position:absolute;z-index:1; top:0;right:0; width:30%;height:100%;" @click="flipPage(true)"></div>
64+
</div>
65+
66+
</div>
4167
</div>
4268

4369
<div id="modal-sections" class="uk-flex-top" uk-modal>
@@ -52,7 +78,7 @@
5278
<p id="progress-label"></p>
5379
</div>
5480
<div class="uk-margin">
55-
<label class="uk-form-label" for="form-stacked-select">Jump to page</label>
81+
<label class="uk-form-label" for="page-select">Jump to page</label>
5682
<div class="uk-form-controls">
5783
<select id="page-select" class="uk-select">
5884
<%- (1..entry.pages).each do |p| -%>
@@ -61,6 +87,15 @@
6187
</select>
6288
</div>
6389
</div>
90+
<div class="uk-margin">
91+
<label class="uk-form-label" for="mode-select">Mode</label>
92+
<div class="uk-form-controls">
93+
<select id="mode-select" class="uk-select">
94+
<option value="continuous">Continuous</option>
95+
<option value="paged">Paged</option>
96+
</select>
97+
</div>
98+
</div>
6499
</div>
65100
<div class="uk-modal-footer uk-text-right">
66101
<button class="uk-button uk-button-danger" type="button" onclick="redirect('<%= exit_url %>')">Exit Reader</button>

0 commit comments

Comments
 (0)