Skip to content

Commit

Permalink
Merge pull request #322 from getmango/rc/0.27.0
Browse files Browse the repository at this point in the history
v0.27.0
  • Loading branch information
hkalexling authored Jul 31, 2022
2 parents 61dc928 + 7ceb91f commit 1fb4864
Show file tree
Hide file tree
Showing 28 changed files with 679 additions and 223 deletions.
1 change: 1 addition & 0 deletions .ameba.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ Layout/LineLength:
MaxLength: 80
Excluded:
- src/routes/api.cr
- spec/plugin_spec.cr
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The official docker images are available on [Dockerhub](https://hub.docker.com/r
### CLI

```
Mango - Manga Server and Web Reader. Version 0.26.2
Mango - Manga Server and Web Reader. Version 0.27.0
Usage:
Expand Down
6 changes: 6 additions & 0 deletions public/js/plugin-download.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const component = () => {
return {
plugins: [],
subscribable: false,
info: undefined,
pid: undefined,
chapters: undefined, // undefined: not searched yet, []: empty
Expand Down Expand Up @@ -60,6 +61,7 @@ const component = () => {
.then((data) => {
if (!data.success) throw new Error(data.error);
this.info = data.info;
this.subscribable = data.subscribable;
this.pid = pid;
})
.catch((e) => {
Expand All @@ -70,6 +72,9 @@ const component = () => {
});
},
pluginChanged() {
this.manga = undefined;
this.chapters = undefined;
this.mid = undefined;
this.loadPlugin(this.pid);
localStorage.setItem("plugin", this.pid);
},
Expand Down Expand Up @@ -140,6 +145,7 @@ const component = () => {
if (!query) return;

this.manga = undefined;
this.mid = undefined;
if (this.info.version === 1) {
this.searchChapters(query);
} else {
Expand Down
41 changes: 33 additions & 8 deletions public/js/reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const readerComponent = () => {
margin: 30,
preloadLookahead: 3,
enableRightToLeft: false,
fitType: 'vert',

/**
* Initialize the component by fetching the page dimensions
Expand All @@ -29,14 +30,16 @@ const readerComponent = () => {
return {
id: i + 1,
url: `${base_url}api/page/${tid}/${eid}/${i+1}`,
width: d.width,
height: d.height,
width: d.width == 0 ? "100%" : d.width,
height: d.height == 0 ? "100%" : d.height,
};
});

const avgRatio = this.items.reduce((acc, cur) => {
// Note: for image types not supported by image_size.cr, the width and height will be 0, and so `avgRatio` will be `Infinity`.
// TODO: support more image types in image_size.cr
const avgRatio = dimensions.reduce((acc, cur) => {
return acc + cur.height / cur.width
}, 0) / this.items.length;
}, 0) / dimensions.length;

console.log(avgRatio);
this.longPages = avgRatio > 2;
Expand All @@ -58,11 +61,16 @@ const readerComponent = () => {

// Preload Images
this.preloadLookahead = +(localStorage.getItem('preloadLookahead') ?? 3);
const limit = Math.min(page + this.preloadLookahead, this.items.length + 1);
const limit = Math.min(page + this.preloadLookahead, this.items.length);
for (let idx = page + 1; idx <= limit; idx++) {
this.preloadImage(this.items[idx - 1].url);
}

const savedFitType = localStorage.getItem('fitType');
if (savedFitType) {
this.fitType = savedFitType;
$('#fit-select').val(savedFitType);
}
const savedFlipAnimation = localStorage.getItem('enableFlipAnimation');
this.enableFlipAnimation = savedFlipAnimation === null || savedFlipAnimation === 'true';

Expand Down Expand Up @@ -135,7 +143,11 @@ const readerComponent = () => {
const idx = parseInt(this.curItem.id);
const newIdx = idx + (isNext ? 1 : -1);

if (newIdx <= 0 || newIdx > this.items.length) return;
if (newIdx <= 0) return;
if (newIdx > this.items.length) {
this.showControl(idx);
return;
}

if (newIdx + this.preloadLookahead < this.items.length + 1) {
this.preloadImage(this.items[newIdx + this.preloadLookahead - 1].url);
Expand Down Expand Up @@ -253,12 +265,20 @@ const readerComponent = () => {
});
},
/**
* Shows the control modal
* Handles clicked image
*
* @param {Event} event - The triggering event
*/
showControl(event) {
clickImage(event) {
const idx = event.currentTarget.id;
this.showControl(idx);
},
/**
* Shows the control modal
*
* @param {number} idx - selected page index
*/
showControl(idx) {
this.selectedIndex = idx;
UIkit.modal($('#modal-sections')).show();
},
Expand Down Expand Up @@ -321,6 +341,11 @@ const readerComponent = () => {
this.toPage(this.selectedIndex);
},

fitChanged(){
this.fitType = $('#fit-select').val();
localStorage.setItem('fitType', this.fitType);
},

preloadLookaheadChanged() {
localStorage.setItem('preloadLookahead', this.preloadLookahead);
},
Expand Down
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: mango
version: 0.26.2
version: 0.27.0

authors:
- Alex Ling <hkalexling@gmail.com>
Expand Down
Empty file.
6 changes: 6 additions & 0 deletions spec/asset/plugins/plugin/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "test",
"title": "Test Plugin",
"placeholder": "placeholder",
"wait_seconds": 1
}
21 changes: 19 additions & 2 deletions spec/config_spec.cr
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
require "./spec_helper"

describe Config do
it "creates config if it does not exist" do
with_default_config do |_, path|
it "creates default config if it does not exist" do
with_default_config do |config, path|
File.exists?(path).should be_true
config.port.should eq 9000
end
end

it "correctly loads config" do
config = Config.load "spec/asset/test-config.yml"
config.port.should eq 3000
config.base_url.should eq "/"
end

it "correctly reads config defaults from ENV" do
ENV["LOG_LEVEL"] = "debug"
config = Config.load "spec/asset/test-config.yml"
config.log_level.should eq "debug"
config.base_url.should eq "/"
end

it "correctly handles ENV truthiness" do
ENV["CACHE_ENABLED"] = "false"
config = Config.load "spec/asset/test-config.yml"
config.cache_enabled.should be_false
config.cache_log_enabled.should be_true
config.disable_login.should be_false
end
end
70 changes: 70 additions & 0 deletions spec/plugin_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require "./spec_helper"

describe Plugin do
describe "helper functions" do
it "mango.text" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.text('<a href="https://github.com">Click Me<a>');
JS
res.should eq "Click Me"
end
end

it "mango.text returns empty string when no text" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.text('<img src="https://github.com" />');
JS
res.should eq ""
end
end

it "mango.css" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.css('<ul><li class="test">A</li><li class="test">B</li><li>C</li></ul>', 'li.test');
JS
res.should eq ["<li class=\"test\">A</li>", "<li class=\"test\">B</li>"]
end
end

it "mango.css returns empty array when no match" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.css('<ul><li class="test">A</li><li class="test">B</li><li>C</li></ul>', 'li.noclass');
JS
res.should eq [] of String
end
end

it "mango.attribute" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.attribute('<a href="https://github.com">Click Me<a>', 'href');
JS
res.should eq "https://github.com"
end
end

it "mango.attribute returns undefined when no match" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.attribute('<div />', 'href') === undefined;
JS
res.should be_true
end
end

# https://github.com/hkalexling/Mango/issues/320
it "mango.attribute handles tags in attribute values" do
with_plugin do |plugin|
res = plugin.eval <<-JS
mango.attribute('<div data-a="<img />" data-b="test" />', 'data-b');
JS
res.should eq "test"
end
end
end
end
8 changes: 8 additions & 0 deletions spec/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ require "../src/queue"
require "../src/server"
require "../src/config"
require "../src/main_fiber"
require "../src/plugin/plugin"

class State
@@hash = {} of String => String
Expand Down Expand Up @@ -54,3 +55,10 @@ def with_storage
end
end
end

def with_plugin
with_default_config do
plugin = Plugin.new "test", "spec/asset/plugins"
yield plugin
end
end
66 changes: 43 additions & 23 deletions src/config.cr
Original file line number Diff line number Diff line change
@@ -1,31 +1,51 @@
require "yaml"

class Config
private OPTIONS = {
"host" => "0.0.0.0",
"port" => 9000,
"base_url" => "/",
"session_secret" => "mango-session-secret",
"library_path" => "~/mango/library",
"library_cache_path" => "~/mango/library.yml.gz",
"db_path" => "~/mango.db",
"queue_db_path" => "~/mango/queue.db",
"scan_interval_minutes" => 5,
"thumbnail_generation_interval_hours" => 24,
"log_level" => "info",
"upload_path" => "~/mango/uploads",
"plugin_path" => "~/mango/plugins",
"download_timeout_seconds" => 30,
"cache_enabled" => true,
"cache_size_mbs" => 50,
"cache_log_enabled" => true,
"disable_login" => false,
"default_username" => "",
"auth_proxy_header_name" => "",
"plugin_update_interval_hours" => 24,
}

include YAML::Serializable

@[YAML::Field(ignore: true)]
property path = ""
property host = "0.0.0.0"
property port : Int32 = 9000
property base_url = "/"
property session_secret = "mango-session-secret"
property library_path = "~/mango/library"
property library_cache_path = "~/mango/library.yml.gz"
property db_path = "~/mango/mango.db"
property queue_db_path = "~/mango/queue.db"
property scan_interval_minutes : Int32 = 5
property thumbnail_generation_interval_hours : Int32 = 24
property log_level = "info"
property upload_path = "~/mango/uploads"
property plugin_path = "~/mango/plugins"
property download_timeout_seconds : Int32 = 30
property cache_enabled = true
property cache_size_mbs = 50
property cache_log_enabled = true
property disable_login = false
property default_username = ""
property auth_proxy_header_name = ""
property plugin_update_interval_hours : Int32 = 24
property path : String = ""

# Go through the options constant above and define them as properties.
# Allow setting the default values through environment variables.
# Overall precedence: config file > environment variable > default value
{% begin %}
{% for k, v in OPTIONS %}
{% if v.is_a? StringLiteral %}
property {{k.id}} : String = ENV[{{k.upcase}}]? || {{ v }}
{% elsif v.is_a? NumberLiteral %}
property {{k.id}} : Int32 = (ENV[{{k.upcase}}]? || {{ v.id }}).to_i
{% elsif v.is_a? BoolLiteral %}
property {{k.id}} : Bool = env_is_true? {{ k.upcase }}, {{ v.id }}
{% else %}
raise "Unknown type in config option: {{ v.class_name.id }}"
{% end %}
{% end %}
{% end %}

@@singlet : Config?

Expand All @@ -38,7 +58,7 @@ class Config
end

def self.load(path : String?)
path = "~/.config/mango/config.yml" if path.nil?
path = (ENV["CONFIG_PATH"]? || "~/.config/mango/config.yml") if path.nil?
cfg_path = File.expand_path path, home: true
if File.exists? cfg_path
config = self.from_yaml File.read cfg_path
Expand Down
Loading

0 comments on commit 1fb4864

Please sign in to comment.