Compare commits

...

8 Commits

Author SHA1 Message Date
Alex Ling 5760ad924e Bump version to v0.14.0 2020-10-18 12:22:26 +00:00
Alex Ling fff171c8c9 Bump version to v0.13.0 2020-10-18 11:39:24 +00:00
Alex Ling 44ff566a1d Merge branch 'feature/paged-reader' into dev 2020-10-15 11:52:15 +00:00
Alex Ling 853f422964 Configurable read timeout (#108) 2020-10-15 11:51:04 +00:00
Alex Ling 3bb0917374 Allow /manga/<id> URL for MangaDex 2020-10-15 11:38:22 +00:00
Alex Ling a86f0d0f34 Add paged reading mode 2020-10-09 10:09:42 +00:00
Alex Ling 16a9d7fc2e Merge pull request #110 from XavierSchiller/master
[arm64] Fix Wrong libgc.so location when building Image
2020-09-27 20:07:44 +08:00
Xavier ee2b4abc85 Fix Wrong libgc.so location when building Image.
The Repo Maintainer was using the location of libgc.so from the armhf package, however, according to:
https://debian.pkgs.org/9/debian-main-arm64/libgc-dev_7.4.2-8_arm64.deb.html and
https://packages.ubuntu.com/focal/arm64/libgc-dev/filelist
it exists under /usr/lib/aarch64-linux-gnu/
2020-09-27 14:35:43 +05:30
10 changed files with 190 additions and 43 deletions
+1 -1
View File
@@ -9,6 +9,6 @@ RUN git clone https://github.com/hkalexling/image_size.cr && cd image_size.cr &&
COPY mango-arm64v8.o . COPY mango-arm64v8.o .
RUN cc 'mango-arm64v8.o' -o 'mango' -rdynamic -lxml2 -L/image_size.cr/ext/libwebp -lwebp -L/image_size.cr/ext/stbi -lstbi /myhtml/src/ext/modest-c/lib/libmodest_static.a -L/duktape.cr/src/.build/lib -L/duktape.cr/src/.build/include -lduktape -lm `pkg-config libarchive --libs` -lz `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'` -lgmp -lsqlite3 -lyaml -lpcre -lm /usr/lib/arm-linux-gnueabihf/libgc.so -lpthread /crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/bin/../lib/crystal/lib -L/usr/bin/../lib/crystal/lib RUN cc 'mango-arm64v8.o' -o 'mango' -rdynamic -lxml2 -L/image_size.cr/ext/libwebp -lwebp -L/image_size.cr/ext/stbi -lstbi /myhtml/src/ext/modest-c/lib/libmodest_static.a -L/duktape.cr/src/.build/lib -L/duktape.cr/src/.build/include -lduktape -lm `pkg-config libarchive --libs` -lz `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'` `command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'` -lgmp -lsqlite3 -lyaml -lpcre -lm /usr/lib/aarch64-linux-gnu/libgc.so -lpthread /crystal/src/ext/libcrystal.a -levent -lrt -ldl -L/usr/bin/../lib/crystal/lib -L/usr/bin/../lib/crystal/lib
CMD ["./mango"] CMD ["./mango"]
+1 -1
View File
@@ -51,7 +51,7 @@ The official docker images are available on [Dockerhub](https://hub.docker.com/r
### CLI ### CLI
``` ```
Mango - Manga Server and Web Reader. Version 0.12.3 Mango - Manga Server and Web Reader. Version 0.14.0
Usage: Usage:
+1 -1
View File
@@ -95,7 +95,7 @@ const search = () => {
try { try {
const path = new URL(input).pathname; const path = new URL(input).pathname;
const match = /\/title\/([0-9]+)/.exec(path); const match = /\/(?:title|manga)\/([0-9]+)/.exec(path);
int_id = parseInt(match[1]); int_id = parseInt(match[1]);
} catch (e) { } catch (e) {
int_id = parseInt(input); int_id = parseInt(input);
+104 -5
View File
@@ -5,11 +5,67 @@ let longPages = false;
$(() => { $(() => {
getPages(); getPages();
const storedMode = localStorage.getItem('mode') || 'continuous';
setProp('mode', storedMode);
updateMode(storedMode, page);
$('#mode-select').val(storedMode);
$('#page-select').change(() => { $('#page-select').change(() => {
const p = parseInt($('#page-select').val()); const p = parseInt($('#page-select').val());
toPage(p); toPage(p);
}); });
$('#mode-select').change(() => {
const mode = $('#mode-select').val();
const curIdx = parseInt($('#page-select').val());
updateMode(mode, curIdx);
}); });
});
$(window).resize(() => {
const mode = getProp('mode');
if (mode === 'continuous') return;
const wideScreen = $(window).width() > $(window).height();
const propMode = wideScreen ? 'height' : 'width';
setProp('mode', propMode);
});
/**
* Update the reader mode
*
* @function updateMode
* @param {string} mode - The mode. Can be one of the followings:
* {'continuous', 'paged', 'height', 'width'}
* @param {number} targetPage - The one-based index of the target page
*/
const updateMode = (mode, targetPage) => {
localStorage.setItem('mode', mode);
// The mode to be put into the `mode` prop. It can't be `screen`
let propMode = mode;
if (mode === 'paged') {
const wideScreen = $(window).width() > $(window).height();
propMode = wideScreen ? 'height' : 'width';
}
setProp('mode', propMode);
if (mode === 'continuous') {
waitForPage(items.length, () => {
setupScroller();
});
}
waitForPage(targetPage, () => {
setTimeout(() => {
toPage(targetPage);
}, 100);
});
};
/** /**
* Set an alpine.js property * Set an alpine.js property
@@ -22,6 +78,17 @@ const setProp = (key, prop) => {
$('#root').get(0).__x.$data[key] = prop; $('#root').get(0).__x.$data[key] = prop;
}; };
/**
* Get an alpine.js property
*
* @function getProp
* @param {string} key - Key of the data property
* @return {*} The data property
*/
const getProp = (key) => {
return $('#root').get(0).__x.$data[key];
};
/** /**
* Get dimension of the pages in the entry from the API and update the view * Get dimension of the pages in the entry from the API and update the view
*/ */
@@ -50,11 +117,6 @@ const getPages = () => {
setProp('items', items); setProp('items', items);
setProp('loading', false); setProp('loading', false);
waitForPage(items.length, () => {
toPage(page);
setupScroller();
});
}) })
.catch(e => { .catch(e => {
const errMsg = `Failed to get the page dimensions. ${e}`; const errMsg = `Failed to get the page dimensions. ${e}`;
@@ -71,7 +133,15 @@ const getPages = () => {
* @param {number} idx - One-based index of the page * @param {number} idx - One-based index of the page
*/ */
const toPage = (idx) => { const toPage = (idx) => {
const mode = getProp('mode');
if (mode === 'continuous') {
$(`#${idx}`).get(0).scrollIntoView(true); $(`#${idx}`).get(0).scrollIntoView(true);
} else {
if (idx >= 1 && idx <= items.length) {
setProp('curItem', items[idx - 1]);
}
}
replaceHistory(idx);
UIkit.modal($('#modal-sections')).hide(); UIkit.modal($('#modal-sections')).hide();
}; };
@@ -137,6 +207,8 @@ const replaceHistory = (idx) => {
* @function setupScroller * @function setupScroller
*/ */
const setupScroller = () => { const setupScroller = () => {
const mode = getProp('mode');
if (mode !== 'continuous') return;
$('#root img').each((idx, el) => { $('#root img').each((idx, el) => {
$(el).on('inview', (event, inView) => { $(el).on('inview', (event, inView) => {
if (inView) { if (inView) {
@@ -193,3 +265,30 @@ const nextEntry = (nextUrl) => {
redirect(nextUrl); redirect(nextUrl);
}); });
}; };
/**
* Show the next or the previous page
*
* @function flipPage
* @param {bool} isNext - Whether we are going to the next page
*/
const flipPage = (isNext) => {
const curItem = getProp('curItem');
const idx = parseInt(curItem.id);
const delta = isNext ? 1 : -1;
const newIdx = idx + delta;
toPage(newIdx);
if (isNext)
setProp('flipAnimation', 'right');
else
setProp('flipAnimation', 'left');
setTimeout(() => {
setProp('flipAnimation', null);
}, 500);
replaceHistory(newIdx);
saveProgress(newIdx);
};
+1 -1
View File
@@ -1,5 +1,5 @@
name: mango name: mango
version: 0.12.3 version: 0.14.0
authors: authors:
- Alex Ling <hkalexling@gmail.com> - Alex Ling <hkalexling@gmail.com>
+1
View File
@@ -18,6 +18,7 @@ class Config
home: true home: true
property plugin_path : String = File.expand_path "~/mango/plugins", property plugin_path : String = File.expand_path "~/mango/plugins",
home: true home: true
property download_timeout_seconds : Int32 = 30
property mangadex = Hash(String, String | Int32).new property mangadex = Hash(String, String | Int32).new
@[YAML::Field(ignore: true)] @[YAML::Field(ignore: true)]
+1 -1
View File
@@ -7,7 +7,7 @@ require "option_parser"
require "clim" require "clim"
require "./plugin/*" require "./plugin/*"
MANGO_VERSION = "0.12.3" MANGO_VERSION = "0.14.0"
# From http://www.network-science.de/ascii/ # From http://www.network-science.de/ascii/
BANNER = %{ BANNER = %{
+1 -1
View File
@@ -5,7 +5,7 @@ require "http_proxy"
module HTTP module HTTP
class Client class Client
private def self.exec(uri : URI, tls : TLSContext = nil) private def self.exec(uri : URI, tls : TLSContext = nil)
Logger.debug "Using monkey-patched HTTP::Client" Logger.debug "Setting proxy"
previous_def uri, tls do |client, path| previous_def uri, tls do |client, path|
client.set_proxy get_proxy uri client.set_proxy get_proxy uri
yield client, path yield client, path
+12
View File
@@ -81,3 +81,15 @@ macro get_sort_opt
sort_opt = SortOptions.new sort_method, is_ascending sort_opt = SortOptions.new sort_method, is_ascending
end end
end end
module HTTP
class Client
private def self.exec(uri : URI, tls : TLSContext = nil)
Logger.debug "Setting read timeout"
previous_def uri, tls do |client, path|
client.read_timeout = Config.current.download_timeout_seconds.seconds
yield client, path
end
end
end
end
+43 -8
View File
@@ -3,22 +3,32 @@
<%= render_component "head" %> <%= render_component "head" %>
<body> <body style="position:relative;">
<div class="uk-section uk-section-default uk-section-small reader-bg"> <div class="uk-section uk-section-default uk-section-small reader-bg"
<div class="uk-container uk-container-small"> id="root"
<div id="alert"></div> :style="mode === 'continuous' ? '' : 'padding:0'"
<div id="root" x-data="{ x-data="{
loading: true, loading: true,
mode: 'continuous', // can be 'continuous', 'height' or 'width'
msg: 'Loading the web reader. Please wait...', msg: 'Loading the web reader. Please wait...',
alertClass: 'uk-alert-primary', alertClass: 'uk-alert-primary',
items: [] items: [],
curItem: {},
flipAnimation: null
}"> }">
<div class="uk-container uk-container-small">
<div id="alert"></div>
<div x-show="loading"> <div x-show="loading">
<div :class="alertClass" x-show="msg" uk-alert> <div :class="alertClass" x-show="msg" uk-alert>
<p x-text="msg"></p> <p x-text="msg"></p>
</div> </div>
</div> </div>
<div x-show="!loading" x-cloak> </div>
<div
:class="{'uk-container': true, 'uk-container-small': mode === 'continuous', 'uk-container-expand': mode !== 'continuous'}">
<div x-show="!loading && mode === 'continuous'" x-cloak>
<template x-for="item in items"> <template x-for="item in items">
<img <img
uk-img uk-img
@@ -36,7 +46,23 @@
<button id="next-btn" class="uk-align-center uk-button uk-button-primary" @click="redirect('<%= exit_url %>')">Exit Reader</button> <button id="next-btn" class="uk-align-center uk-button uk-button-primary" @click="redirect('<%= exit_url %>')">Exit Reader</button>
<%- end -%> <%- end -%>
</div> </div>
<div x-cloak x-show="!loading && mode !== 'continuous'" class="uk-flex uk-flex-middle" style="height:100vh">
<img uk-img :class="{
'uk-align-center': true,
'uk-animation-slide-left': flipAnimation === 'left',
'uk-animation-slide-right': flipAnimation === 'right'
}" :data-src="curItem.url" :width="curItem.width" :height="curItem.height" :id="curItem.id" @click="showControl($event)" :style="`
width:${mode === 'width' ? '100vw' : 'auto'};
height:${mode === 'height' ? '100vh' : 'auto'};
margin-bottom:0;
`" />
<div style="position:absolute;z-index:1; top:0;left:0; width:30%;height:100%;" @click="flipPage(false)"></div>
<div style="position:absolute;z-index:1; top:0;right:0; width:30%;height:100%;" @click="flipPage(true)"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -52,7 +78,7 @@
<p id="progress-label"></p> <p id="progress-label"></p>
</div> </div>
<div class="uk-margin"> <div class="uk-margin">
<label class="uk-form-label" for="form-stacked-select">Jump to page</label> <label class="uk-form-label" for="page-select">Jump to page</label>
<div class="uk-form-controls"> <div class="uk-form-controls">
<select id="page-select" class="uk-select"> <select id="page-select" class="uk-select">
<%- (1..entry.pages).each do |p| -%> <%- (1..entry.pages).each do |p| -%>
@@ -61,6 +87,15 @@
</select> </select>
</div> </div>
</div> </div>
<div class="uk-margin">
<label class="uk-form-label" for="mode-select">Mode</label>
<div class="uk-form-controls">
<select id="mode-select" class="uk-select">
<option value="continuous">Continuous</option>
<option value="paged">Paged</option>
</select>
</div>
</div>
</div> </div>
<div class="uk-modal-footer uk-text-right"> <div class="uk-modal-footer uk-text-right">
<button class="uk-button uk-button-danger" type="button" onclick="redirect('<%= exit_url %>')">Exit Reader</button> <button class="uk-button uk-button-danger" type="button" onclick="redirect('<%= exit_url %>')">Exit Reader</button>