Skip to content

Commit 8829d2e

Browse files
authored
Merge pull request #173 from hkalexling/rc/0.21.0
2 parents 3c3549a + eec6ec6 commit 8829d2e

31 files changed

+672
-272
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ The official docker images are available on [Dockerhub](https://hub.docker.com/r
5252
### CLI
5353

5454
```
55-
Mango - Manga Server and Web Reader. Version 0.20.2
55+
Mango - Manga Server and Web Reader. Version 0.21.0
5656
5757
Usage:
5858
@@ -93,7 +93,7 @@ default_username: ""
9393
auth_proxy_header_name: ""
9494
mangadex:
9595
base_url: https://mangadex.org
96-
api_url: https://mangadex.org/api/v2
96+
api_url: https://api.mangadex.org/v2
9797
download_wait_seconds: 5
9898
download_retries: 4
9999
download_queue_db_path: ~/mango/queue.db

migration/md_account.11.cr

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class CreateMangaDexAccount < MG::Base
2+
def up : String
3+
<<-SQL
4+
CREATE TABLE md_account (
5+
username TEXT NOT NULL PRIMARY KEY,
6+
token TEXT NOT NULL,
7+
expire INTEGER NOT NULL,
8+
FOREIGN KEY (username) REFERENCES users (username)
9+
ON UPDATE CASCADE
10+
ON DELETE CASCADE
11+
);
12+
SQL
13+
end
14+
15+
def down : String
16+
<<-SQL
17+
DROP TABLE md_account;
18+
SQL
19+
end
20+
end

public/css/mango.less

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@
3434
.uk-card-body {
3535
padding: 20px;
3636
.uk-card-title {
37-
max-height: 3em;
3837
font-size: 1rem;
3938
}
39+
.uk-card-title:not(.free-height) {
40+
max-height: 3em;
41+
}
4042
}
4143
}
4244

public/css/uikit.less

+19
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,22 @@
4343
@internal-list-bullet-image: "../img/list-bullet.svg";
4444
@internal-accordion-open-image: "../img/accordion-open.svg";
4545
@internal-accordion-close-image: "../img/accordion-close.svg";
46+
47+
.hook-card-default() {
48+
.uk-light & {
49+
background: @card-secondary-background;
50+
color: @card-secondary-color;
51+
}
52+
}
53+
54+
.hook-card-default-title() {
55+
.uk-light & {
56+
color: @card-secondary-title-color;
57+
}
58+
}
59+
60+
.hook-card-default-hover() {
61+
.uk-light & {
62+
background-color: @card-secondary-hover-background;
63+
}
64+
}

public/js/common.js

-4
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,10 @@ const setTheme = (theme) => {
117117
if (theme === 'dark') {
118118
$('html').css('background', 'rgb(20, 20, 20)');
119119
$('body').addClass('uk-light');
120-
$('.uk-card').addClass('uk-card-secondary');
121-
$('.uk-card').removeClass('uk-card-default');
122120
$('.ui-widget-content').addClass('dark');
123121
} else {
124122
$('html').css('background', '');
125123
$('body').removeClass('uk-light');
126-
$('.uk-card').removeClass('uk-card-secondary');
127-
$('.uk-card').addClass('uk-card-default');
128124
$('.ui-widget-content').removeClass('dark');
129125
}
130126
};

public/js/download.js

+75-21
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ const downloadComponent = () => {
33
chaptersLimit: 1000,
44
loading: false,
55
addingToDownload: false,
6+
searchAvailable: false,
67
searchInput: '',
78
data: {},
89
chapters: [],
10+
mangaAry: undefined, // undefined: not searching; []: searched but no result
11+
candidateManga: {},
912
langChoice: 'All',
1013
groupChoice: 'All',
1114
chapterRange: '',
@@ -48,7 +51,21 @@ const downloadComponent = () => {
4851
childList: true,
4952
subtree: true
5053
});
54+
55+
$.getJSON(`${base_url}api/admin/mangadex/expires`)
56+
.done((data) => {
57+
if (data.error) {
58+
alert('danger', 'Failed to check MangaDex integration status. Error: ' + data.error);
59+
return;
60+
}
61+
if (data.expires && data.expires > Math.floor(Date.now() / 1000))
62+
this.searchAvailable = true;
63+
})
64+
.fail((jqXHR, status) => {
65+
alert('danger', `Failed to check MangaDex integration status. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
66+
})
5167
},
68+
5269
filtersUpdated() {
5370
if (!this.data.chapters)
5471
this.chapters = [];
@@ -90,10 +107,11 @@ const downloadComponent = () => {
90107
console.log('filtered chapters:', _chapters);
91108
this.chapters = _chapters;
92109
},
110+
93111
search() {
94112
if (this.loading || this.searchInput === '') return;
95-
this.loading = true;
96113
this.data = {};
114+
this.mangaAry = undefined;
97115

98116
var int_id = -1;
99117
try {
@@ -103,29 +121,54 @@ const downloadComponent = () => {
103121
} catch (e) {
104122
int_id = parseInt(this.searchInput);
105123
}
106-
if (int_id <= 0 || isNaN(int_id)) {
107-
alert('danger', 'Please make sure you are using a valid manga ID or manga URL from Mangadex.');
108-
this.loading = false;
109-
return;
110-
}
111124

112-
$.getJSON(`${base_url}api/admin/mangadex/manga/${int_id}`)
113-
.done((data) => {
114-
if (data.error) {
115-
alert('danger', 'Failed to get manga info. Error: ' + data.error);
116-
return;
117-
}
125+
if (!isNaN(int_id) && int_id > 0) {
126+
// The input is a positive integer. We treat it as an ID.
127+
this.loading = true;
128+
$.getJSON(`${base_url}api/admin/mangadex/manga/${int_id}`)
129+
.done((data) => {
130+
if (data.error) {
131+
alert('danger', 'Failed to get manga info. Error: ' + data.error);
132+
return;
133+
}
118134

119-
this.data = data;
120-
this.chapters = data.chapters;
121-
})
122-
.fail((jqXHR, status) => {
123-
alert('danger', `Failed to get manga info. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
124-
})
125-
.always(() => {
126-
this.loading = false;
127-
});
135+
this.data = data;
136+
this.chapters = data.chapters;
137+
this.mangaAry = undefined;
138+
})
139+
.fail((jqXHR, status) => {
140+
alert('danger', `Failed to get manga info. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
141+
})
142+
.always(() => {
143+
this.loading = false;
144+
});
145+
} else {
146+
if (!this.searchAvailable) {
147+
alert('danger', 'Please make sure you are using a valid manga ID or manga URL from Mangadex. If you are trying to search MangaDex with a search term, please log in to MangaDex first by going to "Admin -> Connect to MangaDex".');
148+
return;
149+
}
150+
151+
// Search as a search term
152+
this.loading = true;
153+
$.getJSON(`${base_url}api/admin/mangadex/search?${$.param({
154+
query: this.searchInput
155+
})}`)
156+
.done((data) => {
157+
if (data.error) {
158+
alert('danger', `Failed to search MangaDex. Error: ${data.error}`);
159+
return;
160+
}
128161

162+
this.mangaAry = data.manga;
163+
this.data = {};
164+
})
165+
.fail((jqXHR, status) => {
166+
alert('danger', `Failed to search MangaDex. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
167+
})
168+
.always(() => {
169+
this.loading = false;
170+
});
171+
}
129172
},
130173

131174
parseRange(str) {
@@ -228,6 +271,17 @@ const downloadComponent = () => {
228271
this.addingToDownload = false;
229272
});
230273
});
274+
},
275+
276+
chooseManga(manga) {
277+
this.candidateManga = manga;
278+
UIkit.modal($('#modal').get(0)).show();
279+
},
280+
281+
confirmManga(id) {
282+
UIkit.modal($('#modal').get(0)).hide();
283+
this.searchInput = id;
284+
this.search();
231285
}
232286
};
233287
};

public/js/mangadex.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const component = () => {
2+
return {
3+
username: '',
4+
password: '',
5+
expires: undefined,
6+
loading: true,
7+
loggingIn: false,
8+
9+
init() {
10+
this.loading = true;
11+
$.ajax({
12+
type: 'GET',
13+
url: `${base_url}api/admin/mangadex/expires`,
14+
contentType: "application/json",
15+
})
16+
.done(data => {
17+
console.log(data);
18+
if (data.error) {
19+
alert('danger', `Failed to retrieve MangaDex token status. Error: ${data.error}`);
20+
return;
21+
}
22+
this.expires = data.expires;
23+
this.loading = false;
24+
})
25+
.fail((jqXHR, status) => {
26+
alert('danger', `Failed to retrieve MangaDex token status. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
27+
});
28+
},
29+
login() {
30+
if (!(this.username && this.password)) return;
31+
this.loggingIn = true;
32+
$.ajax({
33+
type: 'POST',
34+
url: `${base_url}api/admin/mangadex/login`,
35+
contentType: "application/json",
36+
dataType: 'json',
37+
data: JSON.stringify({
38+
username: this.username,
39+
password: this.password
40+
})
41+
})
42+
.done(data => {
43+
console.log(data);
44+
if (data.error) {
45+
alert('danger', `Failed to log in. Error: ${data.error}`);
46+
return;
47+
}
48+
this.expires = data.expires;
49+
})
50+
.fail((jqXHR, status) => {
51+
alert('danger', `Failed to log in. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
52+
})
53+
.always(() => {
54+
this.loggingIn = false;
55+
});
56+
},
57+
get expired() {
58+
return this.expires && moment().diff(moment.unix(this.expires)) > 0;
59+
}
60+
};
61+
};

public/js/reader.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const readerComponent = () => {
99
flipAnimation: null,
1010
longPages: false,
1111
lastSavedPage: page,
12+
selectedIndex: 0, // 0: not selected; 1: the first page
1213

1314
/**
1415
* Initialize the component by fetching the page dimensions
@@ -221,10 +222,7 @@ const readerComponent = () => {
221222
*/
222223
showControl(event) {
223224
const idx = event.currentTarget.id;
224-
const pageCount = this.items.length;
225-
const progressText = `Progress: ${idx}/${pageCount} (${(idx/pageCount * 100).toFixed(1)}%)`;
226-
$('#progress-label').text(progressText);
227-
$('#page-select').val(idx);
225+
this.selectedIndex = idx;
228226
UIkit.modal($('#modal-sections')).show();
229227
},
230228
/**
@@ -263,19 +261,22 @@ const readerComponent = () => {
263261
});
264262
},
265263
/**
266-
* Exits the reader, and optionally sets the reading progress tp 100%
264+
* Exits the reader, and sets the reading progress tp 100%
267265
*
268266
* @param {string} exitUrl - The Exit URL
269-
* @param {boolean} [markCompleted] - Whether we should mark the
270-
* reading progress to 100%
271267
*/
272-
exitReader(exitUrl, markCompleted = false) {
273-
if (!markCompleted) {
274-
return this.redirect(exitUrl);
275-
}
268+
exitReader(exitUrl) {
276269
this.saveProgress(this.items.length, () => {
277270
this.redirect(exitUrl);
278271
});
272+
},
273+
274+
/**
275+
* Handles the `change` event for the entry selector
276+
*/
277+
entryChanged() {
278+
const id = $('#entry-select').val();
279+
this.redirect(`${base_url}reader/${tid}/${id}`);
279280
}
280281
};
281282
}

shard.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ shards:
5050

5151
koa:
5252
git: https://github.com/hkalexling/koa.git
53-
version: 0.5.0
53+
version: 0.7.0
5454

5555
mangadex:
5656
git: https://github.com/hkalexling/mangadex.git
57-
version: 0.5.0+git.commit.323110c56c2d5134ce4162b27a9b24ec34137fcb
57+
version: 0.8.0+git.commit.24e6fb51afd043721139355854e305b43bf98c43
5858

5959
mg:
6060
git: https://github.com/hkalexling/mg.git

shard.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: mango
2-
version: 0.20.2
2+
version: 0.21.0
33

44
authors:
55
- Alex Ling <[email protected]>

0 commit comments

Comments
 (0)