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

Commit 899b221

Browse files
committed
Merge branch 'dev'
2 parents 650ba98 + a317086 commit 899b221

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+823
-748
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212

1313
runs-on: ubuntu-latest
1414
container:
15-
image: crystallang/crystal:0.34.0-alpine
15+
image: crystallang/crystal:0.35.1-alpine
1616

1717
steps:
1818
- uses: actions/checkout@v2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ dist
99
mango
1010
.env
1111
*.md
12+
public/css/uikit.css

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM crystallang/crystal:0.34.0-alpine AS builder
1+
FROM crystallang/crystal:0.35.1-alpine AS builder
22

33
WORKDIR /Mango
44

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ The official docker images are available on [Dockerhub](https://hub.docker.com/r
5050
### CLI
5151

5252
```
53-
Mango - Manga Server and Web Reader. Version 0.6.1
53+
Mango - Manga Server and Web Reader. Version 0.7.0
5454
5555
Usage:
5656

gulpfile.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const gulp = require('gulp');
22
const minify = require("gulp-babel-minify");
33
const minifyCss = require('gulp-minify-css');
4+
const less = require('gulp-less');
45

56
gulp.task('minify-js', () => {
67
return gulp.src('public/js/*.js')
@@ -10,6 +11,12 @@ gulp.task('minify-js', () => {
1011
.pipe(gulp.dest('dist/js'));
1112
});
1213

14+
gulp.task('less', () => {
15+
return gulp.src('src/assets/*.less')
16+
.pipe(less())
17+
.pipe(gulp.dest('public/css'));
18+
});
19+
1320
gulp.task('minify-css', () => {
1421
return gulp.src('public/css/*.css')
1522
.pipe(minifyCss())
@@ -21,9 +28,9 @@ gulp.task('img', () => {
2128
.pipe(gulp.dest('dist/img'));
2229
});
2330

24-
gulp.task('favicon', () => {
25-
return gulp.src('public/favicon.ico')
31+
gulp.task('copy-files', () => {
32+
return gulp.src('public/*.*')
2633
.pipe(gulp.dest('dist'));
2734
});
2835

29-
gulp.task('default', gulp.parallel('minify-js', 'minify-css', 'img', 'favicon'));
36+
gulp.task('default', gulp.parallel('minify-js', gulp.series('less', 'minify-css'), 'img', 'copy-files'));

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
"devDependencies": {
99
"gulp": "^4.0.2",
1010
"gulp-babel-minify": "^0.5.1",
11-
"gulp-minify-css": "^1.2.4"
11+
"gulp-less": "^4.0.1",
12+
"gulp-minify-css": "^1.2.4",
13+
"less": "^3.11.3"
1214
},
1315
"scripts": {
1416
"uglify": "gulp"
17+
},
18+
"dependencies": {
19+
"uikit": "^3.5.4"
1520
}
1621
}

public/js/download-manager.js

Lines changed: 84 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -24,95 +24,101 @@ const loadConfig = () => {
2424
const remove = (id) => {
2525
var url = base_url + 'api/admin/mangadex/queue/delete';
2626
if (id !== undefined)
27-
url += '?' + $.param({id: id});
27+
url += '?' + $.param({
28+
id: id
29+
});
2830
console.log(url);
2931
$.ajax({
30-
type: 'POST',
31-
url: url,
32-
dataType: 'json'
33-
})
34-
.done(data => {
35-
if (!data.success && data.error) {
36-
alert('danger', `Failed to remove job from download queue. Error: ${data.error}`);
37-
return;
38-
}
39-
load();
40-
})
41-
.fail((jqXHR, status) => {
42-
alert('danger', `Failed to remove job from download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
43-
});
32+
type: 'POST',
33+
url: url,
34+
dataType: 'json'
35+
})
36+
.done(data => {
37+
if (!data.success && data.error) {
38+
alert('danger', `Failed to remove job from download queue. Error: ${data.error}`);
39+
return;
40+
}
41+
load();
42+
})
43+
.fail((jqXHR, status) => {
44+
alert('danger', `Failed to remove job from download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
45+
});
4446
};
4547
const refresh = (id) => {
4648
var url = base_url + 'api/admin/mangadex/queue/retry';
4749
if (id !== undefined)
48-
url += '?' + $.param({id: id});
50+
url += '?' + $.param({
51+
id: id
52+
});
4953
console.log(url);
5054
$.ajax({
51-
type: 'POST',
52-
url: url,
53-
dataType: 'json'
54-
})
55-
.done(data => {
56-
if (!data.success && data.error) {
57-
alert('danger', `Failed to restart download job. Error: ${data.error}`);
58-
return;
59-
}
60-
load();
61-
})
62-
.fail((jqXHR, status) => {
63-
alert('danger', `Failed to restart download job. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
64-
});
55+
type: 'POST',
56+
url: url,
57+
dataType: 'json'
58+
})
59+
.done(data => {
60+
if (!data.success && data.error) {
61+
alert('danger', `Failed to restart download job. Error: ${data.error}`);
62+
return;
63+
}
64+
load();
65+
})
66+
.fail((jqXHR, status) => {
67+
alert('danger', `Failed to restart download job. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
68+
});
6569
};
6670
const toggle = () => {
6771
$('#pause-resume-btn').attr('disabled', '');
6872
const paused = $('#pause-resume-btn').text() === 'Resume download';
6973
const action = paused ? 'resume' : 'pause';
7074
const url = `${base_url}api/admin/mangadex/queue/${action}`;
7175
$.ajax({
72-
type: 'POST',
73-
url: url,
74-
dataType: 'json'
75-
})
76-
.fail((jqXHR, status) => {
77-
alert('danger', `Failed to ${action} download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
78-
})
79-
.always(() => {
80-
load();
81-
$('#pause-resume-btn').removeAttr('disabled');
82-
});
76+
type: 'POST',
77+
url: url,
78+
dataType: 'json'
79+
})
80+
.fail((jqXHR, status) => {
81+
alert('danger', `Failed to ${action} download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
82+
})
83+
.always(() => {
84+
load();
85+
$('#pause-resume-btn').removeAttr('disabled');
86+
});
8387
};
8488
const load = () => {
8589
if (loading) return;
8690
loading = true;
8791
console.log('fetching');
8892
$.ajax({
89-
type: 'GET',
90-
url: base_url + 'api/admin/mangadex/queue',
91-
dataType: 'json'
92-
})
93-
.done(data => {
94-
if (!data.success && data.error) {
95-
alert('danger', `Failed to fetch download queue. Error: ${data.error}`);
96-
return;
97-
}
98-
console.log(data);
99-
const btnText = data.paused ? "Resume download" : "Pause download";
100-
$('#pause-resume-btn').text(btnText);
101-
$('#pause-resume-btn').removeAttr('hidden');
102-
const rows = data.jobs.map(obj => {
103-
var cls = 'uk-label ';
104-
if (obj.status === 'Completed')
105-
cls += 'uk-label-success';
106-
if (obj.status === 'Error')
107-
cls += 'uk-label-danger';
108-
if (obj.status === 'MissingPages')
109-
cls += 'uk-label-warning';
93+
type: 'GET',
94+
url: base_url + 'api/admin/mangadex/queue',
95+
dataType: 'json'
96+
})
97+
.done(data => {
98+
if (!data.success && data.error) {
99+
alert('danger', `Failed to fetch download queue. Error: ${data.error}`);
100+
return;
101+
}
102+
console.log(data);
103+
const btnText = data.paused ? "Resume download" : "Pause download";
104+
$('#pause-resume-btn').text(btnText);
105+
$('#pause-resume-btn').removeAttr('hidden');
106+
const rows = data.jobs.map(obj => {
107+
var cls = 'label ';
108+
if (obj.status === 'Pending')
109+
cls += 'label-pending';
110+
if (obj.status === 'Completed')
111+
cls += 'label-success';
112+
if (obj.status === 'Error')
113+
cls += 'label-danger';
114+
if (obj.status === 'MissingPages')
115+
cls += 'label-warning';
110116

111-
const info = obj.status_message.length > 0 ? '<span uk-icon="info"></span>' : '';
112-
const statusSpan = `<span class="${cls}">${obj.status} ${info}</span>`;
113-
const dropdown = obj.status_message.length > 0 ? `<div uk-dropdown>${obj.status_message}</div>` : '';
114-
const retryBtn = obj.status_message.length > 0 ? `<a onclick="refresh('${obj.id}')" uk-icon="refresh"></a>` : '';
115-
return `<tr id="chapter-${obj.id}">
117+
const info = obj.status_message.length > 0 ? '<span uk-icon="info"></span>' : '';
118+
const statusSpan = `<span class="${cls}">${obj.status} ${info}</span>`;
119+
const dropdown = obj.status_message.length > 0 ? `<div uk-dropdown>${obj.status_message}</div>` : '';
120+
const retryBtn = obj.status_message.length > 0 ? `<a onclick="refresh('${obj.id}')" uk-icon="refresh"></a>` : '';
121+
return `<tr id="chapter-${obj.id}">
116122
<td><a href="${baseURL}/chapter/${obj.id}">${obj.title}</a></td>
117123
<td><a href="${baseURL}/manga/${obj.manga_id}">${obj.manga_title}</a></td>
118124
<td>${obj.success_count}/${obj.pages}</td>
@@ -123,16 +129,16 @@ const load = () => {
123129
${retryBtn}
124130
</td>
125131
</tr>`;
126-
});
132+
});
127133

128-
const tbody = `<tbody>${rows.join('')}</tbody>`;
129-
$('tbody').remove();
130-
$('table').append(tbody);
131-
})
132-
.fail((jqXHR, status) => {
133-
alert('danger', `Failed to fetch download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
134-
})
135-
.always(() => {
136-
loading = false;
137-
});
134+
const tbody = `<tbody>${rows.join('')}</tbody>`;
135+
$('tbody').remove();
136+
$('table').append(tbody);
137+
})
138+
.fail((jqXHR, status) => {
139+
alert('danger', `Failed to fetch download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`);
140+
})
141+
.always(() => {
142+
loading = false;
143+
});
138144
};

public/js/theme.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ const setTheme = themeStr => {
2222
$('.uk-card').addClass('uk-card-secondary');
2323
$('.uk-card').removeClass('uk-card-default');
2424
$('.ui-widget-content').addClass('dark');
25-
}
26-
else {
25+
} else {
2726
$('html').css('background', '');
2827
$('body').removeClass('uk-light');
2928
$('.uk-card').removeClass('uk-card-secondary');
@@ -39,5 +38,11 @@ const styleModal = () => {
3938
$('.uk-modal-footer').css('background', color);
4039
};
4140

42-
// do it before document is ready to prevent the initial flash of white
41+
// do it before document is ready to prevent the initial flash of white on
42+
// most pages
4343
setTheme(getTheme());
44+
45+
$(() => {
46+
// hack for the reader page
47+
setTheme(getTheme());
48+
});

public/js/title.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ function showModal(encodedPath, pages, percentage, encodedeTitle, encodedEntryTi
88
if (percentage === 0) {
99
$('#continue-btn').attr('hidden', '');
1010
$('#unread-btn').attr('hidden', '');
11+
} else if (percentage === 100) {
12+
$('#read-btn').attr('hidden', '');
13+
$('#continue-btn').attr('hidden', '');
1114
} else {
1215
$('#continue-btn').text('Continue from ' + percentage + '%');
1316
}
14-
if (percentage === 100) {
15-
$('#read-btn').attr('hidden', '');
16-
}
1717

1818
$('#modal-title-link').text(title);
1919
$('#modal-title-link').attr('href', `${base_url}book/${titleID}`);
@@ -35,7 +35,9 @@ function showModal(encodedPath, pages, percentage, encodedeTitle, encodedEntryTi
3535
updateProgress(titleID, entryID, 0);
3636
});
3737

38-
$('.uk-modal-title.break-word > a').attr('onclick', `edit("${entryID}")`);
38+
$('#modal-edit-btn').attr('onclick', `edit("${entryID}")`);
39+
40+
$('#modal-download-btn').attr('href', `/opds/download/${titleID}/${entryID}`);
3941

4042
UIkit.modal($('#modal')).show();
4143
styleModal();

public/robots.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
User-agent: *
2+
Disallow: /

shard.lock

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,46 @@
1-
version: 1.0
1+
version: 2.0
22
shards:
33
ameba:
4-
github: crystal-ameba/ameba
4+
git: https://github.com/crystal-ameba/ameba.git
55
version: 0.12.1
66

77
archive:
8-
github: hkalexling/archive.cr
8+
git: https://github.com/hkalexling/archive.cr.git
99
version: 0.2.0
1010

1111
baked_file_system:
12-
github: schovi/baked_file_system
12+
git: https://github.com/schovi/baked_file_system.git
1313
version: 0.9.8
1414

1515
clim:
16-
github: at-grandpa/clim
16+
git: https://github.com/at-grandpa/clim.git
1717
version: 0.12.0
1818

1919
db:
20-
github: crystal-lang/crystal-db
20+
git: https://github.com/crystal-lang/crystal-db.git
2121
version: 0.9.0
2222

2323
exception_page:
24-
github: crystal-loot/exception_page
24+
git: https://github.com/crystal-loot/exception_page.git
2525
version: 0.1.4
2626

2727
kemal:
28-
github: kemalcr/kemal
29-
version: 0.26.1
28+
git: https://github.com/kemalcr/kemal.git
29+
version: 0.26.1+git.commit.a8c0f09b858162bd13c96663febef5527b322a32
3030

3131
kemal-session:
32-
github: kemalcr/kemal-session
32+
git: https://github.com/kemalcr/kemal-session.git
3333
version: 0.12.1
3434

3535
kilt:
36-
github: jeromegn/kilt
36+
git: https://github.com/jeromegn/kilt.git
3737
version: 0.4.0
3838

3939
radix:
40-
github: luislavena/radix
40+
git: https://github.com/luislavena/radix.git
4141
version: 0.3.9
4242

4343
sqlite3:
44-
github: crystal-lang/crystal-sqlite3
44+
git: https://github.com/crystal-lang/crystal-sqlite3.git
4545
version: 0.16.0
4646

0 commit comments

Comments
 (0)