From c9d3c35bdde4c6c619ceac2fa68acd6fe1cc9617 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Tue, 9 Jun 2020 15:48:08 +0000 Subject: [PATCH 01/27] Add robots.txt --- public/robots.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 public/robots.txt diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 00000000..1f53798b --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / From 5c26b0d6dca327807105fcf4a539b597665ccef6 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Thu, 11 Jun 2020 10:03:34 +0000 Subject: [PATCH 02/27] Handle nested titles in the recently added section --- src/library.cr | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/library.cr b/src/library.cr index 9eaf4f70..71a520af 100644 --- a/src/library.cr +++ b/src/library.cr @@ -191,6 +191,12 @@ class Title @title_ids.map { |tid| @library.get_title! tid } end + # Get all entries, including entries in nested titles + def deep_entries + return @entries if title_ids.empty? + @entries + titles.map { |t| t.deep_entries }.flatten + end + def parents ary = [] of Title tid = @parent_id @@ -535,7 +541,7 @@ class Library def get_recently_added_entries(username) # Get all entries added within the last three months - entries = titles.map { |t| t.entries } + entries = titles.map { |t| t.deep_entries } .flatten .select { |e| e.date_added > 3.months.ago } From aa269f26eebae74420725741849f919e1bc21f3d Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Thu, 11 Jun 2020 12:34:13 +0000 Subject: [PATCH 03/27] Fix incorrect breadcrumb menu order --- src/library.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library.cr b/src/library.cr index 71a520af..4ed4b58e 100644 --- a/src/library.cr +++ b/src/library.cr @@ -205,7 +205,7 @@ class Title ary << title tid = title.parent_id end - ary + ary.reverse end def size From c8be2849b9ae919a234e8373331810245d9b5956 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Thu, 11 Jun 2020 12:36:25 +0000 Subject: [PATCH 04/27] Show progress for titles and nested titles --- src/library.cr | 18 +++++++++++------- src/routes/main.cr | 1 + src/views/components/card.ecr | 6 ++---- src/views/title.ecr | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/library.cr b/src/library.cr index 4ed4b58e..de1080c1 100644 --- a/src/library.cr +++ b/src/library.cr @@ -339,14 +339,18 @@ class Title page / entry_obj.pages end + def deep_read_page_count(username) : Int32 + entries.map { |e| load_progress username, e.title }.sum + + titles.map { |t| t.deep_read_page_count username }.flatten.sum + end + + def deep_total_page_count : Int32 + entries.map { |e| e.pages }.sum + + titles.map { |t| t.deep_total_page_count }.flatten.sum + end + def load_percentage(username) - return 0.0 if @entries.empty? - read_pages = total_pages = 0 - @entries.each do |e| - read_pages += load_progress username, e.title - total_pages += e.pages - end - read_pages / total_pages + deep_read_page_count(username) / deep_total_page_count end def load_last_read(username, entry) diff --git a/src/routes/main.cr b/src/routes/main.cr index 8d2afec1..5af50767 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -56,6 +56,7 @@ class MainRouter < Router percentage = title.entries.map { |e| title.load_percentage username, e.title } + title_percentage = title.titles.map &.load_percentage username layout "title" rescue e @context.error e diff --git a/src/views/components/card.ecr b/src/views/components/card.ecr index 0eb07a5a..a761ca02 100644 --- a/src/views/components/card.ecr +++ b/src/views/components/card.ecr @@ -8,7 +8,7 @@ <% else %> <% grouped_count = 1 %> <% end %> -
id="<%= item.id %>" <% end %>> @@ -20,7 +20,7 @@
- onclick="showModal("<%= item.encoded_path %>", '<%= item.pages %>', <%= (progress.not_nil! * 100).round(1) %>, "<%= item.book.encoded_display_name %>", "<%= item.encoded_display_name %>", '<%= item.title_id %>', '<%= item.id %>')" + onclick="showModal("<%= item.encoded_path %>", '<%= item.pages %>', <%= (progress * 100).round(1) %>, "<%= item.book.encoded_display_name %>", "<%= item.encoded_display_name %>", '<%= item.title_id %>', '<%= item.id %>')" <% end %>>
@@ -28,9 +28,7 @@
- <% unless (item.is_a? Title && item.entries.size == 0) || progress.nil? %>
<%= (progress * 100).round(1) %>%
- <% end %>

"><%= item.display_name %>

<% if item.is_a? Entry %> diff --git a/src/views/title.ecr b/src/views/title.ecr index d6f70b0e..803d0233 100644 --- a/src/views/title.ecr +++ b/src/views/title.ecr @@ -33,7 +33,7 @@
<% title.titles.each_with_index do |item, i| %> - <% progress = nil %> + <% progress = title_percentage[i] %> <%= render_component "card" %> <% end %> <% title.entries.each_with_index do |item, i| %> From 9302601307c065b5a5ddef7c47613698ee59c723 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Sat, 13 Jun 2020 15:54:55 +0000 Subject: [PATCH 05/27] Move relevant methods from `Title` to `Entry` --- src/library.cr | 158 +++++++++++++++++++------------------------ src/routes/api.cr | 2 +- src/routes/main.cr | 4 +- src/routes/reader.cr | 6 +- 4 files changed, 76 insertions(+), 94 deletions(-) diff --git a/src/library.cr b/src/library.cr index de1080c1..0bec697a 100644 --- a/src/library.cr +++ b/src/library.cr @@ -17,8 +17,7 @@ end class Entry property zip_path : String, book : Title, title : String, size : String, pages : Int32, id : String, title_id : String, - encoded_path : String, encoded_title : String, mtime : Time, - date_added : Time + encoded_path : String, encoded_title : String, mtime : Time def initialize(path, @book, @title_id, storage) @zip_path = path @@ -34,7 +33,6 @@ class Entry file.close @id = storage.get_id @zip_path, false @mtime = File.info(@zip_path).modification_time - @date_added = load_date_added end def to_json(json : JSON::Builder) @@ -90,7 +88,19 @@ class Entry img end - private def load_date_added + def next_entry + idx = @book.entries.index self + return nil if idx.nil? || idx == @book.entries.size - 1 + @book.entries[idx + 1] + end + + def previous_entry + idx = @book.entries.index self + return nil if idx.nil? || idx == 0 + @book.entries[idx - 1] + end + + def date_added date_added = nil TitleInfo.new @book.dir do |info| info_da = info.date_added[@title]? @@ -103,6 +113,52 @@ class Entry end date_added.not_nil! # is it ok to set not_nil! here? end + + # For backward backward compatibility with v0.1.0, we save entry titles + # instead of IDs in info.json + def save_progress(username, page) + TitleInfo.new @book.dir do |info| + if info.progress[username]?.nil? + info.progress[username] = {@title => page} + else + info.progress[username][@title] = page + end + # save last_read timestamp + if info.last_read[username]?.nil? + info.last_read[username] = {@title => Time.utc} + else + info.last_read[username][@title] = Time.utc + end + info.save + end + end + + def load_progress(username) + progress = 0 + TitleInfo.new @book.dir do |info| + unless info.progress[username]?.nil? || + info.progress[username][@title]?.nil? + progress = info.progress[username][@title] + end + end + progress + end + + def load_percentage(username) + page = load_progress username + page / @pages + end + + def load_last_read(username) + last_read = nil + TitleInfo.new @book.dir do |info| + unless info.last_read[username]?.nil? || + info.last_read[username][@title]?.nil? + last_read = info.last_read[username][@title] + end + end + last_read + end end class Title @@ -285,7 +341,7 @@ class Title # Set the reading progress of all entries and nested libraries to 100% def read_all(username) @entries.each do |e| - save_progress username, e.title, e.pages + e.save_progress username, e.pages end titles.each do |t| t.read_all username @@ -295,52 +351,15 @@ class Title # Set the reading progress of all entries and nested libraries to 0% def unread_all(username) @entries.each do |e| - save_progress username, e.title, 0 + e.save_progress username, 0 end titles.each do |t| t.unread_all username end end - # For backward backward compatibility with v0.1.0, we save entry titles - # instead of IDs in info.json - def save_progress(username, entry, page) - TitleInfo.new @dir do |info| - if info.progress[username]?.nil? - info.progress[username] = {entry => page} - else - info.progress[username][entry] = page - end - # save last_read timestamp - if info.last_read[username]?.nil? - info.last_read[username] = {entry => Time.utc} - else - info.last_read[username][entry] = Time.utc - end - info.save - end - end - - def load_progress(username, entry) - progress = 0 - TitleInfo.new @dir do |info| - unless info.progress[username]?.nil? || - info.progress[username][entry]?.nil? - progress = info.progress[username][entry] - end - end - progress - end - - def load_percentage(username, entry) - page = load_progress username, entry - entry_obj = @entries.find { |e| e.title == entry } - return 0.0 if entry_obj.nil? - page / entry_obj.pages - end - def deep_read_page_count(username) : Int32 - entries.map { |e| load_progress username, e.title }.sum + + entries.map { |e| e.load_progress username }.sum + titles.map { |t| t.deep_read_page_count username }.flatten.sum end @@ -353,29 +372,6 @@ class Title deep_read_page_count(username) / deep_total_page_count end - def load_last_read(username, entry) - last_read = nil - TitleInfo.new @dir do |info| - unless info.last_read[username]?.nil? || - info.last_read[username][entry]?.nil? - last_read = info.last_read[username][entry] - end - end - last_read - end - - def next_entry(current_entry_obj) - idx = @entries.index current_entry_obj - return nil if idx.nil? || idx == @entries.size - 1 - @entries[idx + 1] - end - - def previous_entry(current_entry_obj) - idx = @entries.index current_entry_obj - return nil if idx.nil? || idx == 0 - @entries[idx - 1] - end - def get_continue_reading_entry(username) in_progress_entries = @entries.select do |e| load_progress(username, e.title) > 0 @@ -390,17 +386,6 @@ class Title latest_read_entry end end - - # TODO: More concise title? - def get_last_read_for_continue_reading(username, entry_obj) - last_read = load_last_read username, entry_obj.title - # grab from previous entry if current entry hasn't been started yet - if last_read.nil? - previous_entry = previous_entry(entry_obj) - return load_last_read username, previous_entry.title if previous_entry - end - last_read - end end class TitleInfo @@ -529,7 +514,7 @@ class Library continue_reading = continue_reading_entries.map { |e| { entry: e, - percentage: e.book.load_percentage(username, e.title), + percentage: e.load_percentage(username), last_read: get_relevant_last_read(username, e), } } @@ -571,7 +556,7 @@ class Library entry = ary.sort { |a, b| a.date_added <=> b.date_added }.last { entry: entry, - percentage: entry.book.load_percentage(username, entry.title), + percentage: entry.load_percentage(username), grouped_count: ary.size, } end @@ -581,26 +566,25 @@ class Library private def get_continue_reading_entry(username, title) in_progress_entries = title.entries.select do |e| - title.load_progress(username, e.title) > 0 + e.load_progress(username) > 0 end return nil if in_progress_entries.empty? latest_read_entry = in_progress_entries[-1] - if title.load_progress(username, latest_read_entry.title) == + if latest_read_entry.load_progress(username) == latest_read_entry.pages - title.next_entry latest_read_entry + latest_read_entry.next_entry else latest_read_entry end end private def get_relevant_last_read(username, entry_obj) - last_read = entry_obj.book.load_last_read username, entry_obj.title + last_read = entry_obj.load_last_read username # grab from previous entry if current entry hasn't been started yet if last_read.nil? - previous_entry = entry_obj.book.previous_entry(entry_obj) - return entry_obj.book.load_last_read username, previous_entry.title \ - if previous_entry + previous_entry = entry_obj.previous_entry + return previous_entry.load_last_read username if previous_entry end last_read end diff --git a/src/routes/api.cr b/src/routes/api.cr index 54bfb1bf..91438e2d 100644 --- a/src/routes/api.cr +++ b/src/routes/api.cr @@ -80,7 +80,7 @@ class APIRouter < Router if !entry_id.nil? entry = title.get_entry(entry_id).not_nil! raise "incorrect page value" if page < 0 || page > entry.pages - title.save_progress username, entry.title, page + entry.save_progress username, page elsif page == 0 title.unread_all username else diff --git a/src/routes/main.cr b/src/routes/main.cr index 5af50767..429b3b66 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -53,9 +53,7 @@ class MainRouter < Router begin title = (@context.library.get_title env.params.url["title"]).not_nil! username = get_username env - percentage = title.entries.map { |e| - title.load_percentage username, e.title - } + percentage = title.entries.map &.load_percentage username title_percentage = title.titles.map &.load_percentage username layout "title" rescue e diff --git a/src/routes/reader.cr b/src/routes/reader.cr index e9c32d35..d1e10135 100644 --- a/src/routes/reader.cr +++ b/src/routes/reader.cr @@ -9,7 +9,7 @@ class ReaderRouter < Router # load progress username = get_username env - page = title.load_progress username, entry.title + page = entry.load_progress username # we go back 2 * `IMGS_PER_PAGE` pages. the infinite scroll # library perloads a few pages in advance, and the user # might not have actually read them @@ -33,7 +33,7 @@ class ReaderRouter < Router # save progress username = get_username env - title.save_progress username, entry.title, page + entry.save_progress username, page pages = (page...[entry.pages + 1, page + IMGS_PER_PAGE].min) urls = pages.map { |idx| @@ -45,7 +45,7 @@ class ReaderRouter < Router next_page = page + IMGS_PER_PAGE next_url = next_entry_url = nil exit_url = "#{base_url}book/#{title.id}" - next_entry = title.next_entry entry + next_entry = entry.next_entry unless next_page > entry.pages next_url = "#{base_url}reader/#{title.id}/#{entry.id}/#{next_page}" end From 3dc9bd2264875d89de9a34393098d20a349f33c0 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 09:47:23 +0000 Subject: [PATCH 06/27] Add `finished?` helper method --- src/library.cr | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/library.cr b/src/library.cr index 0bec697a..4159696a 100644 --- a/src/library.cr +++ b/src/library.cr @@ -159,6 +159,10 @@ class Entry end last_read end + + def finished?(username) + load_progress(username) == @pages + end end class Title @@ -571,8 +575,7 @@ class Library return nil if in_progress_entries.empty? latest_read_entry = in_progress_entries[-1] - if latest_read_entry.load_progress(username) == - latest_read_entry.pages + if latest_read_entry.finished? username latest_read_entry.next_entry else latest_read_entry From e28dadc94e0a3aa63bd33c0c3948ef1c56d45fe2 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 12:05:59 +0000 Subject: [PATCH 07/27] Add `started?` and `deep_titles` helper methods --- src/library.cr | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/library.cr b/src/library.cr index 4159696a..6002e342 100644 --- a/src/library.cr +++ b/src/library.cr @@ -163,6 +163,10 @@ class Entry def finished?(username) load_progress(username) == @pages end + + def started?(username) + load_progress(username) > 0 + end end class Title @@ -257,6 +261,11 @@ class Title @entries + titles.map { |t| t.deep_entries }.flatten end + def deep_titles + return [] of Title if titles.empty? + titles + titles.map { |t| t.deep_titles }.flatten + end + def parents ary = [] of Title tid = @parent_id @@ -469,6 +478,10 @@ class Library @title_ids.map { |tid| self.get_title!(tid) } end + def deep_titles + titles + titles.map { |t| t.deep_titles }.flatten + end + def to_json(json : JSON::Builder) json.object do json.field "dir", @dir From 47edb3008b3660c2f19469bc470bae7d87567908 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 12:09:17 +0000 Subject: [PATCH 08/27] Refactor `get_recently_added_entries` --- src/library.cr | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/library.cr b/src/library.cr index 6002e342..58737ce4 100644 --- a/src/library.cr +++ b/src/library.cr @@ -546,39 +546,29 @@ class Library end def get_recently_added_entries(username) - # Get all entries added within the last three months - entries = titles.map { |t| t.deep_entries } - .flatten - .select { |e| e.date_added > 3.months.ago } - - # Group entries in a Hash by title ID - grouped_entries = {} of String => Array(Entry) - entries.each do |e| - if grouped_entries.has_key? e.title_id - grouped_entries[e.title_id].push e - else - grouped_entries[e.title_id] = [e] - end - end - - # Cast the Hash to an Array of Tuples and sort it by date_added - grouped_ary = grouped_entries.to_a.sort do |a, b| - date_added_a = a[1].map { |e| e.date_added }.max - date_added_b = b[1].map { |e| e.date_added }.max - date_added_b <=> date_added_a - end - - recently_added = grouped_ary.map do |_, ary| + # Group all recently added entries into a Array(Array(Title)). Entries + # from the same title are grouped together + grouped_entries = deep_titles + .map { |t| + t.entries.select { |e| e.date_added > 3.months.ago } + } + .select { |ary| !ary.empty? } + # Sort the array by the added date of the last added entry + .sort { |a, b| + date_added_a = a.map { |e| e.date_added }.max + date_added_b = b.map { |e| e.date_added }.max + date_added_b <=> date_added_a + }[0..11] + + grouped_entries.map do |ary| # Get the most recently added entry in the group - entry = ary.sort { |a, b| a.date_added <=> b.date_added }.last + entry = ary.max_by { |e| e.date_added } { entry: entry, percentage: entry.load_percentage(username), grouped_count: ary.size, } end - - recently_added[0..11] end private def get_continue_reading_entry(username, title) From f4c4bb536ceb26fd6cd64cfba57fa848e21c2a5f Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 12:10:31 +0000 Subject: [PATCH 09/27] Include nested entries in continue reading --- src/library.cr | 66 +++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/src/library.cr b/src/library.cr index 58737ce4..5dbf1343 100644 --- a/src/library.cr +++ b/src/library.cr @@ -521,23 +521,37 @@ class Library end def get_continue_reading_entries(username) - # map: get the continue-reading entry or nil for each Title - # select: select only entries (and ignore Nil's) from the array - # produced by map - continue_reading_entries = titles.map { |t| - get_continue_reading_entry username, t - }.select Entry - - continue_reading = continue_reading_entries.map { |e| - { - entry: e, - percentage: e.load_percentage(username), - last_read: get_relevant_last_read(username, e), + cr_entries = deep_titles + # For each Title, get the last read entry. If the user has finished + # reading this entry, get the next entry + .map { |t| + last_read_entry = t.entries.reverse_each.find do |e| + e.started? username + end + if last_read_entry && last_read_entry.finished? username + last_read_entry = last_read_entry.next_entry + end + last_read_entry + } + # Select elements with type `Entry` from the array and ignore all `Nil`s + .select(Entry) + .map { |e| + # Get the last read time of the entry. If it hasn't been started, get + # the last read time of the previous entry + last_read = e.load_last_read username + pe = e.previous_entry + if last_read.nil? && pe + last_read = pe.load_last_read username + end + { + entry: e, + percentage: e.load_percentage(username), + last_read: last_read, + } } - } # Sort by by last_read, most recent first (nils at the end) - continue_reading.sort! { |a, b| + cr_entries.sort { |a, b| next 0 if a[:last_read].nil? && b[:last_read].nil? next 1 if a[:last_read].nil? next -1 if b[:last_read].nil? @@ -570,28 +584,4 @@ class Library } end end - - private def get_continue_reading_entry(username, title) - in_progress_entries = title.entries.select do |e| - e.load_progress(username) > 0 - end - return nil if in_progress_entries.empty? - - latest_read_entry = in_progress_entries[-1] - if latest_read_entry.finished? username - latest_read_entry.next_entry - else - latest_read_entry - end - end - - private def get_relevant_last_read(username, entry_obj) - last_read = entry_obj.load_last_read username - # grab from previous entry if current entry hasn't been started yet - if last_read.nil? - previous_entry = entry_obj.previous_entry - return previous_entry.load_last_read username if previous_entry - end - last_read - end end From 4c2cf64f533eb7e5eb6d1ab15fc77a3b14462d81 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 12:34:51 +0000 Subject: [PATCH 10/27] Limit `load_progress` to `@pages` --- src/library.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library.cr b/src/library.cr index 5dbf1343..193863ba 100644 --- a/src/library.cr +++ b/src/library.cr @@ -141,7 +141,7 @@ class Entry progress = info.progress[username][@title] end end - progress + [progress, @pages].min end def load_percentage(username) From dc084aff7c25ff84569941e49c1188fd5cdb4fbe Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 12:35:44 +0000 Subject: [PATCH 11/27] Support webp (#69, nice) --- src/library.cr | 6 ++++-- src/routes/api.cr | 2 +- src/views/title.ecr | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/library.cr b/src/library.cr index 193863ba..e850173f 100644 --- a/src/library.cr +++ b/src/library.cr @@ -4,6 +4,8 @@ require "uri" require "./util" require "./archive" +SUPPORTED_IMG_TYPES = ["image/jpeg", "image/png", "image/webp"] + struct Image property data : Bytes property mime : String @@ -27,7 +29,7 @@ class Entry @size = (File.size path).humanize_bytes file = ArchiveFile.new path @pages = file.entries.count do |e| - ["image/jpeg", "image/png"].includes? \ + SUPPORTED_IMG_TYPES.includes? \ MIME.from_filename? e.filename end file.close @@ -72,7 +74,7 @@ class Entry ArchiveFile.open @zip_path do |file| page = file.entries .select { |e| - ["image/jpeg", "image/png"].includes? \ + SUPPORTED_IMG_TYPES.includes? \ MIME.from_filename? e.filename } .sort { |a, b| diff --git a/src/routes/api.cr b/src/routes/api.cr index 91438e2d..4911c1bd 100644 --- a/src/routes/api.cr +++ b/src/routes/api.cr @@ -224,7 +224,7 @@ class APIRouter < Router entry_id = env.params.query["entry"]? title = @context.library.get_title(title_id).not_nil! - unless ["image/jpeg", "image/png"].includes? \ + unless SUPPORTED_IMG_TYPES.includes? \ MIME.from_filename? filename raise "The uploaded image must be either JPEG or PNG" end diff --git a/src/views/title.ecr b/src/views/title.ecr index 803d0233..ec201a64 100644 --- a/src/views/title.ecr +++ b/src/views/title.ecr @@ -72,7 +72,7 @@ Upload a cover image by dropping it here or
- + "> selecting one
From 674da55bde86cbe7706fb21642bd3f9dacf44b0b Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 12:54:42 +0000 Subject: [PATCH 12/27] Add entry download button (#45) --- public/js/title.js | 4 +++- src/views/components/entry-modal.ecr | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/public/js/title.js b/public/js/title.js index d23cf8f7..95d69f99 100644 --- a/public/js/title.js +++ b/public/js/title.js @@ -35,7 +35,9 @@ function showModal(encodedPath, pages, percentage, encodedeTitle, encodedEntryTi updateProgress(titleID, entryID, 0); }); - $('.uk-modal-title.break-word > a').attr('onclick', `edit("${entryID}")`); + $('#modal-edit-btn').attr('onclick', `edit("${entryID}")`); + + $('#modal-download-btn').attr('href', `/opds/download/${titleID}/${entryID}`); UIkit.modal($('#modal')).show(); styleModal(); diff --git a/src/views/components/entry-modal.ecr b/src/views/components/entry-modal.ecr index c064f4cf..2019e9fa 100644 --- a/src/views/components/entry-modal.ecr +++ b/src/views/components/entry-modal.ecr @@ -10,9 +10,10 @@ <% unless page == "home" %>   <% if is_admin %> - + <% end %> <% end %> +

From 06d6311080290118eabc442df07a50023c6b6379 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 14:32:37 +0000 Subject: [PATCH 13/27] Display book percentage in "recently added" --- src/library.cr | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/library.cr b/src/library.cr index e850173f..cc2efccb 100644 --- a/src/library.cr +++ b/src/library.cr @@ -579,9 +579,14 @@ class Library grouped_entries.map do |ary| # Get the most recently added entry in the group entry = ary.max_by { |e| e.date_added } + if ary.size > 1 + percentage = entry.book.load_percentage username + else + percentage = entry.load_percentage username + end { entry: entry, - percentage: entry.load_percentage(username), + percentage: percentage, grouped_count: ary.size, } end From d2f973525014850b76cad636d85ef81436e6d315 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 14:53:16 +0000 Subject: [PATCH 14/27] Add space between entry title and button in modal --- src/views/components/entry-modal.ecr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/components/entry-modal.ecr b/src/views/components/entry-modal.ecr index 2019e9fa..73379602 100644 --- a/src/views/components/entry-modal.ecr +++ b/src/views/components/entry-modal.ecr @@ -7,8 +7,8 @@

<% end %>

- <% unless page == "home" %>   + <% unless page == "home" %> <% if is_admin %> <% end %> From b70fad13a7e7b869c35e8554fab8611e6290062d Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Mon, 15 Jun 2020 14:54:28 +0000 Subject: [PATCH 15/27] Restrict "recently added" from 3 months to 1 --- src/library.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library.cr b/src/library.cr index cc2efccb..3f11ba47 100644 --- a/src/library.cr +++ b/src/library.cr @@ -566,7 +566,7 @@ class Library # from the same title are grouped together grouped_entries = deep_titles .map { |t| - t.entries.select { |e| e.date_added > 3.months.ago } + t.entries.select { |e| e.date_added > 1.months.ago } } .select { |ary| !ary.empty? } # Sort the array by the added date of the last added entry From ef0e3fd346cf1829405e1bcf64d8a3e1344d408a Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Tue, 16 Jun 2020 05:15:39 +0000 Subject: [PATCH 16/27] Add color to labels in dark mode (#70) --- .gitignore | 1 + gulpfile.js | 9 +- package.json | 7 +- public/js/download-manager.js | 162 ++++++++++++++++++---------------- src/assets/uikit.less | 33 +++++++ src/views/components/head.ecr | 2 +- 6 files changed, 133 insertions(+), 81 deletions(-) create mode 100644 src/assets/uikit.less diff --git a/.gitignore b/.gitignore index 3a07fc7a..17d66475 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist mango .env *.md +public/css/uikit.css diff --git a/gulpfile.js b/gulpfile.js index dc6f33d9..b3fc62ab 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,6 +1,7 @@ const gulp = require('gulp'); const minify = require("gulp-babel-minify"); const minifyCss = require('gulp-minify-css'); +const less = require('gulp-less'); gulp.task('minify-js', () => { return gulp.src('public/js/*.js') @@ -10,6 +11,12 @@ gulp.task('minify-js', () => { .pipe(gulp.dest('dist/js')); }); +gulp.task('less', () => { + return gulp.src('src/assets/*.less') + .pipe(less()) + .pipe(gulp.dest('public/css')); +}); + gulp.task('minify-css', () => { return gulp.src('public/css/*.css') .pipe(minifyCss()) @@ -26,4 +33,4 @@ gulp.task('favicon', () => { .pipe(gulp.dest('dist')); }); -gulp.task('default', gulp.parallel('minify-js', 'minify-css', 'img', 'favicon')); +gulp.task('default', gulp.parallel('minify-js', gulp.series('less', 'minify-css'), 'img', 'favicon')); diff --git a/package.json b/package.json index dd815a69..98f01b4b 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,14 @@ "devDependencies": { "gulp": "^4.0.2", "gulp-babel-minify": "^0.5.1", - "gulp-minify-css": "^1.2.4" + "gulp-less": "^4.0.1", + "gulp-minify-css": "^1.2.4", + "less": "^3.11.3" }, "scripts": { "uglify": "gulp" + }, + "dependencies": { + "uikit": "^3.5.4" } } diff --git a/public/js/download-manager.js b/public/js/download-manager.js index 4b3f40a8..9ab407eb 100644 --- a/public/js/download-manager.js +++ b/public/js/download-manager.js @@ -24,44 +24,48 @@ const loadConfig = () => { const remove = (id) => { var url = base_url + 'api/admin/mangadex/queue/delete'; if (id !== undefined) - url += '?' + $.param({id: id}); + url += '?' + $.param({ + id: id + }); console.log(url); $.ajax({ - type: 'POST', - url: url, - dataType: 'json' - }) - .done(data => { - if (!data.success && data.error) { - alert('danger', `Failed to remove job from download queue. Error: ${data.error}`); - return; - } - load(); - }) - .fail((jqXHR, status) => { - alert('danger', `Failed to remove job from download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`); - }); + type: 'POST', + url: url, + dataType: 'json' + }) + .done(data => { + if (!data.success && data.error) { + alert('danger', `Failed to remove job from download queue. Error: ${data.error}`); + return; + } + load(); + }) + .fail((jqXHR, status) => { + alert('danger', `Failed to remove job from download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`); + }); }; const refresh = (id) => { var url = base_url + 'api/admin/mangadex/queue/retry'; if (id !== undefined) - url += '?' + $.param({id: id}); + url += '?' + $.param({ + id: id + }); console.log(url); $.ajax({ - type: 'POST', - url: url, - dataType: 'json' - }) - .done(data => { - if (!data.success && data.error) { - alert('danger', `Failed to restart download job. Error: ${data.error}`); - return; - } - load(); - }) - .fail((jqXHR, status) => { - alert('danger', `Failed to restart download job. Error: [${jqXHR.status}] ${jqXHR.statusText}`); - }); + type: 'POST', + url: url, + dataType: 'json' + }) + .done(data => { + if (!data.success && data.error) { + alert('danger', `Failed to restart download job. Error: ${data.error}`); + return; + } + load(); + }) + .fail((jqXHR, status) => { + alert('danger', `Failed to restart download job. Error: [${jqXHR.status}] ${jqXHR.statusText}`); + }); }; const toggle = () => { $('#pause-resume-btn').attr('disabled', ''); @@ -69,50 +73,52 @@ const toggle = () => { const action = paused ? 'resume' : 'pause'; const url = `${base_url}api/admin/mangadex/queue/${action}`; $.ajax({ - type: 'POST', - url: url, - dataType: 'json' - }) - .fail((jqXHR, status) => { - alert('danger', `Failed to ${action} download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`); - }) - .always(() => { - load(); - $('#pause-resume-btn').removeAttr('disabled'); - }); + type: 'POST', + url: url, + dataType: 'json' + }) + .fail((jqXHR, status) => { + alert('danger', `Failed to ${action} download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`); + }) + .always(() => { + load(); + $('#pause-resume-btn').removeAttr('disabled'); + }); }; const load = () => { if (loading) return; loading = true; console.log('fetching'); $.ajax({ - type: 'GET', - url: base_url + 'api/admin/mangadex/queue', - dataType: 'json' - }) - .done(data => { - if (!data.success && data.error) { - alert('danger', `Failed to fetch download queue. Error: ${data.error}`); - return; - } - console.log(data); - const btnText = data.paused ? "Resume download" : "Pause download"; - $('#pause-resume-btn').text(btnText); - $('#pause-resume-btn').removeAttr('hidden'); - const rows = data.jobs.map(obj => { - var cls = 'uk-label '; - if (obj.status === 'Completed') - cls += 'uk-label-success'; - if (obj.status === 'Error') - cls += 'uk-label-danger'; - if (obj.status === 'MissingPages') - cls += 'uk-label-warning'; + type: 'GET', + url: base_url + 'api/admin/mangadex/queue', + dataType: 'json' + }) + .done(data => { + if (!data.success && data.error) { + alert('danger', `Failed to fetch download queue. Error: ${data.error}`); + return; + } + console.log(data); + const btnText = data.paused ? "Resume download" : "Pause download"; + $('#pause-resume-btn').text(btnText); + $('#pause-resume-btn').removeAttr('hidden'); + const rows = data.jobs.map(obj => { + var cls = 'label '; + if (obj.status === 'Pending') + cls += 'label-pending'; + if (obj.status === 'Completed') + cls += 'label-success'; + if (obj.status === 'Error') + cls += 'label-danger'; + if (obj.status === 'MissingPages') + cls += 'label-warning'; - const info = obj.status_message.length > 0 ? '' : ''; - const statusSpan = `${obj.status} ${info}`; - const dropdown = obj.status_message.length > 0 ? `
${obj.status_message}
` : ''; - const retryBtn = obj.status_message.length > 0 ? `` : ''; - return ` + const info = obj.status_message.length > 0 ? '' : ''; + const statusSpan = `${obj.status} ${info}`; + const dropdown = obj.status_message.length > 0 ? `
${obj.status_message}
` : ''; + const retryBtn = obj.status_message.length > 0 ? `` : ''; + return ` ${obj.title} ${obj.manga_title} ${obj.success_count}/${obj.pages} @@ -123,16 +129,16 @@ const load = () => { ${retryBtn} `; - }); + }); - const tbody = `${rows.join('')}`; - $('tbody').remove(); - $('table').append(tbody); - }) - .fail((jqXHR, status) => { - alert('danger', `Failed to fetch download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`); - }) - .always(() => { - loading = false; - }); + const tbody = `${rows.join('')}`; + $('tbody').remove(); + $('table').append(tbody); + }) + .fail((jqXHR, status) => { + alert('danger', `Failed to fetch download queue. Error: [${jqXHR.status}] ${jqXHR.statusText}`); + }) + .always(() => { + loading = false; + }); }; diff --git a/src/assets/uikit.less b/src/assets/uikit.less new file mode 100644 index 00000000..3482a965 --- /dev/null +++ b/src/assets/uikit.less @@ -0,0 +1,33 @@ +@import "node_modules/uikit/src/less/uikit.theme.less"; + +.label { + display: inline-block; + padding: @label-padding-vertical @label-padding-horizontal; + background: @label-background; + line-height: @label-line-height; + font-size: @label-font-size; + color: @label-color; + vertical-align: middle; + white-space: nowrap; + .hook-label; +} + +.label-success { + background-color: @label-success-background; + color: @label-success-color; +} + +.label-warning { + background-color: @label-warning-background; + color: @label-warning-color; +} + +.label-danger { + background-color: @label-danger-background; + color: @label-danger-color; +} + +.label-pending { + background-color: @global-secondary-background; + color: @global-inverse-color; +} diff --git a/src/views/components/head.ecr b/src/views/components/head.ecr index cbcbc07b..399b9077 100644 --- a/src/views/components/head.ecr +++ b/src/views/components/head.ecr @@ -4,7 +4,7 @@ Mango - + From 4af5258602fe5aa4cbcd04eef6559ba68036d184 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Tue, 16 Jun 2020 05:26:07 +0000 Subject: [PATCH 17/27] Show Mango version on the admin page (#71) --- src/views/admin.ecr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/views/admin.ecr b/src/views/admin.ecr index 9700fe8b..0d831816 100644 --- a/src/views/admin.ecr +++ b/src/views/admin.ecr @@ -11,8 +11,9 @@
+

Version: v<%= MANGO_VERSION %>

Log Out <% content_for "script" do %> -<% end %> \ No newline at end of file +<% end %> From 0e7be6392d795975a6b6d49038908cf9f15dd188 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Tue, 16 Jun 2020 06:04:43 +0000 Subject: [PATCH 18/27] Fix incorrect modal colors on the reader page --- public/js/theme.js | 11 ++++++++--- src/views/reader.ecr | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/public/js/theme.js b/public/js/theme.js index 1ac121b8..efdd16cf 100644 --- a/public/js/theme.js +++ b/public/js/theme.js @@ -22,8 +22,7 @@ const setTheme = themeStr => { $('.uk-card').addClass('uk-card-secondary'); $('.uk-card').removeClass('uk-card-default'); $('.ui-widget-content').addClass('dark'); - } - else { + } else { $('html').css('background', ''); $('body').removeClass('uk-light'); $('.uk-card').removeClass('uk-card-secondary'); @@ -39,5 +38,11 @@ const styleModal = () => { $('.uk-modal-footer').css('background', color); }; -// do it before document is ready to prevent the initial flash of white +// do it before document is ready to prevent the initial flash of white on +// most pages setTheme(getTheme()); + +$(() => { + // hack for the reader page + setTheme(getTheme()); +}); diff --git a/src/views/reader.ecr b/src/views/reader.ecr index d62513c1..9e9c0e46 100644 --- a/src/views/reader.ecr +++ b/src/views/reader.ecr @@ -4,7 +4,6 @@ <%= render_component "head" %> -
<%- urls.each_with_index do |url, i| -%> From ca8d9efcfd945ad4a3e865f6dd887e5f83175195 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Tue, 16 Jun 2020 06:05:54 +0000 Subject: [PATCH 19/27] Show entry display name and path in reader modal (#71) --- src/views/reader.ecr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/views/reader.ecr b/src/views/reader.ecr index 9e9c0e46..86a53501 100644 --- a/src/views/reader.ecr +++ b/src/views/reader.ecr @@ -26,7 +26,8 @@
-

Options

+

<%= entry.display_name %>

+

<%= entry.zip_path %>

From 00fcc881eeb6d36f12d90e3d1ce448d97f506f6b Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Tue, 16 Jun 2020 06:15:58 +0000 Subject: [PATCH 20/27] Start from page 1 if the entry has been completed (#71) --- public/js/title.js | 6 +++--- src/routes/reader.cr | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/public/js/title.js b/public/js/title.js index 95d69f99..62119230 100644 --- a/public/js/title.js +++ b/public/js/title.js @@ -8,12 +8,12 @@ function showModal(encodedPath, pages, percentage, encodedeTitle, encodedEntryTi if (percentage === 0) { $('#continue-btn').attr('hidden', ''); $('#unread-btn').attr('hidden', ''); + } else if (percentage === 100) { + $('#read-btn').attr('hidden', ''); + $('#continue-btn').attr('hidden', ''); } else { $('#continue-btn').text('Continue from ' + percentage + '%'); } - if (percentage === 100) { - $('#read-btn').attr('hidden', ''); - } $('#modal-title-link').text(title); $('#modal-title-link').attr('href', `${base_url}book/${titleID}`); diff --git a/src/routes/reader.cr b/src/routes/reader.cr index d1e10135..c52e6e2f 100644 --- a/src/routes/reader.cr +++ b/src/routes/reader.cr @@ -15,6 +15,9 @@ class ReaderRouter < Router # might not have actually read them page = [page - 2 * IMGS_PER_PAGE, 1].max + # start from page 1 if the user has finished reading the entry + page = 1 if entry.finished? username + redirect env, "/reader/#{title.id}/#{entry.id}/#{page}" rescue e @context.error e From 0e4d67cf297fb216e64a515178bf8b5bd5e7e0ba Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Wed, 17 Jun 2020 16:16:35 +0000 Subject: [PATCH 21/27] Hide the progress badge with incorrect value --- src/views/components/card.ecr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/components/card.ecr b/src/views/components/card.ecr index a761ca02..193c5e2c 100644 --- a/src/views/components/card.ecr +++ b/src/views/components/card.ecr @@ -28,7 +28,9 @@
+ <% unless progress < 0 || progress > 100 %>
<%= (progress * 100).round(1) %>%
+ <% end %>

"><%= item.display_name %>

<% if item.is_a? Entry %> From 0768e2177b921c31d27bf1141b98417ae0b5c168 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Wed, 17 Jun 2020 16:17:29 +0000 Subject: [PATCH 22/27] Bring back original behavior for recently added (#37 https://github.com/hkalexling/Mango/issues/37#issuecomment-644748066) --- src/library.cr | 58 +++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/library.cr b/src/library.cr index 3f11ba47..8236ed60 100644 --- a/src/library.cr +++ b/src/library.cr @@ -561,34 +561,38 @@ class Library }[0..11] end + alias RA = NamedTuple( + entry: Entry, + percentage: Float64, + grouped_count: Int32) + def get_recently_added_entries(username) - # Group all recently added entries into a Array(Array(Title)). Entries - # from the same title are grouped together - grouped_entries = deep_titles - .map { |t| - t.entries.select { |e| e.date_added > 1.months.ago } - } - .select { |ary| !ary.empty? } - # Sort the array by the added date of the last added entry - .sort { |a, b| - date_added_a = a.map { |e| e.date_added }.max - date_added_b = b.map { |e| e.date_added }.max - date_added_b <=> date_added_a - }[0..11] - - grouped_entries.map do |ary| - # Get the most recently added entry in the group - entry = ary.max_by { |e| e.date_added } - if ary.size > 1 - percentage = entry.book.load_percentage username - else - percentage = entry.load_percentage username + recently_added = [] of RA + + titles.map { |t| t.deep_entries } + .flatten + .select { |e| e.date_added > 1.month.ago } + .sort { |a, b| b.date_added <=> a.date_added } + .each do |e| + last = recently_added.last? + if last && e.title_id == last[:entry].title_id + # A NamedTuple is immutable, so we have to cast it to a Hash first + last_hash = last.to_h + count = last_hash[:grouped_count].as(Int32) + last_hash[:grouped_count] = count + 1 + # Setting the percentage to a negative value will hide the + # percentage badge on the card + last_hash[:percentage] = -1.0 + recently_added[recently_added.size - 1] = RA.from last_hash + else + recently_added << { + entry: e, + percentage: e.load_percentage(username), + grouped_count: 1, + } + end end - { - entry: entry, - percentage: percentage, - grouped_count: ary.size, - } - end + + recently_added[0..11] end end From 841d5051cb7b3fd2dcabc070362564c6a24b37dd Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Thu, 18 Jun 2020 15:09:18 +0000 Subject: [PATCH 23/27] Copy robots.txt to dist/ in gulpfile --- gulpfile.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index b3fc62ab..6d8502ab 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -28,9 +28,9 @@ gulp.task('img', () => { .pipe(gulp.dest('dist/img')); }); -gulp.task('favicon', () => { - return gulp.src('public/favicon.ico') +gulp.task('copy-files', () => { + return gulp.src('public/*.*') .pipe(gulp.dest('dist')); }); -gulp.task('default', gulp.parallel('minify-js', gulp.series('less', 'minify-css'), 'img', 'favicon')); +gulp.task('default', gulp.parallel('minify-js', gulp.series('less', 'minify-css'), 'img', 'copy-files')); From 96f98f6c784cfec900c08178459aa44bef5c10ca Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Fri, 19 Jun 2020 11:34:03 +0000 Subject: [PATCH 24/27] Rename and format ECR files --- src/routes/main.cr | 2 +- src/routes/opds.cr | 4 +- src/routes/reader.cr | 2 +- src/util.cr | 6 +- src/views/{admin.ecr => admin.html.ecr} | 2 +- src/views/components/card.ecr | 49 ------------- src/views/components/card.html.ecr | 50 +++++++++++++ .../{entry-modal.ecr => entry-modal.html.ecr} | 16 ++-- .../components/{head.ecr => head.html.ecr} | 0 .../{sort-form.ecr => sort-form.html.ecr} | 4 +- ...-manager.ecr => download-manager.html.ecr} | 14 ++-- src/views/{download.ecr => download.html.ecr} | 16 ++-- src/views/home.ecr | 69 ------------------ src/views/home.html.ecr | 73 +++++++++++++++++++ src/views/layout.ecr | 68 ----------------- src/views/layout.html.ecr | 68 +++++++++++++++++ src/views/{library.ecr => library.html.ecr} | 12 +-- src/views/login.ecr | 36 --------- src/views/login.html.ecr | 36 +++++++++ src/views/message.ecr | 1 - src/views/message.html.ecr | 1 + src/views/opds/{index.ecr => index.xml.ecr} | 10 +-- src/views/opds/title.ecr | 38 ---------- src/views/opds/title.xml.ecr | 38 ++++++++++ src/views/reader.ecr | 62 ---------------- src/views/reader.html.ecr | 62 ++++++++++++++++ src/views/{title.ecr => title.html.ecr} | 28 +++---- src/views/user-edit.ecr | 46 ------------ src/views/user-edit.html.ecr | 46 ++++++++++++ src/views/user.ecr | 31 -------- src/views/user.html.ecr | 31 ++++++++ 31 files changed, 463 insertions(+), 458 deletions(-) rename src/views/{admin.ecr => admin.html.ecr} (92%) delete mode 100644 src/views/components/card.ecr create mode 100644 src/views/components/card.html.ecr rename src/views/components/{entry-modal.ecr => entry-modal.html.ecr} (61%) rename src/views/components/{head.ecr => head.html.ecr} (100%) rename src/views/components/{sort-form.ecr => sort-form.html.ecr} (56%) rename src/views/{download-manager.ecr => download-manager.html.ecr} (74%) rename src/views/{download.ecr => download.html.ecr} (88%) delete mode 100644 src/views/home.ecr create mode 100644 src/views/home.html.ecr delete mode 100644 src/views/layout.ecr create mode 100644 src/views/layout.html.ecr rename src/views/{library.ecr => library.html.ecr} (69%) delete mode 100644 src/views/login.ecr create mode 100644 src/views/login.html.ecr delete mode 100644 src/views/message.ecr create mode 100644 src/views/message.html.ecr rename src/views/opds/{index.ecr => index.xml.ecr} (67%) delete mode 100644 src/views/opds/title.ecr create mode 100644 src/views/opds/title.xml.ecr delete mode 100644 src/views/reader.ecr create mode 100644 src/views/reader.html.ecr rename src/views/{title.ecr => title.html.ecr} (75%) delete mode 100644 src/views/user-edit.ecr create mode 100644 src/views/user-edit.html.ecr delete mode 100644 src/views/user.ecr create mode 100644 src/views/user.html.ecr diff --git a/src/routes/main.cr b/src/routes/main.cr index 429b3b66..6f28032b 100644 --- a/src/routes/main.cr +++ b/src/routes/main.cr @@ -4,7 +4,7 @@ class MainRouter < Router def initialize get "/login" do |env| base_url = Config.current.base_url - render "src/views/login.ecr" + render "src/views/login.html.ecr" end get "/logout" do |env| diff --git a/src/routes/opds.cr b/src/routes/opds.cr index 648bcac0..567931e1 100644 --- a/src/routes/opds.cr +++ b/src/routes/opds.cr @@ -4,13 +4,13 @@ class OPDSRouter < Router def initialize get "/opds" do |env| titles = @context.library.titles - render_xml "src/views/opds/index.ecr" + render_xml "src/views/opds/index.xml.ecr" end get "/opds/book/:title_id" do |env| begin title = @context.library.get_title(env.params.url["title_id"]).not_nil! - render_xml "src/views/opds/title.ecr" + render_xml "src/views/opds/title.xml.ecr" rescue e @context.error e env.response.status_code = 404 diff --git a/src/routes/reader.cr b/src/routes/reader.cr index c52e6e2f..4e3bc061 100644 --- a/src/routes/reader.cr +++ b/src/routes/reader.cr @@ -56,7 +56,7 @@ class ReaderRouter < Router next_entry_url = "#{base_url}reader/#{title.id}/#{next_entry.id}" end - render "src/views/reader.ecr" + render "src/views/reader.html.ecr" rescue e @context.error e env.response.status_code = 404 diff --git a/src/util.cr b/src/util.cr index 921f281c..c9dfa2bd 100644 --- a/src/util.cr +++ b/src/util.cr @@ -16,11 +16,11 @@ macro layout(name) is_admin = @context.storage.verify_admin token end page = {{name}} - render "src/views/#{{{name}}}.ecr", "src/views/layout.ecr" + render "src/views/#{{{name}}}.html.ecr", "src/views/layout.html.ecr" rescue e message = e.to_s @context.error message - render "src/views/message.ecr", "src/views/layout.ecr" + render "src/views/message.html.ecr", "src/views/layout.html.ecr" end end @@ -139,7 +139,7 @@ macro render_xml(path) end macro render_component(filename) - render "src/views/components/#{{{filename}}}.ecr" + render "src/views/components/#{{{filename}}}.html.ecr" end # Works in all Unix systems. Follows https://github.com/crystal-lang/crystal/ diff --git a/src/views/admin.ecr b/src/views/admin.html.ecr similarity index 92% rename from src/views/admin.ecr rename to src/views/admin.html.ecr index 0d831816..b3e2d969 100644 --- a/src/views/admin.ecr +++ b/src/views/admin.html.ecr @@ -15,5 +15,5 @@ Log Out <% content_for "script" do %> - + <% end %> diff --git a/src/views/components/card.ecr b/src/views/components/card.ecr deleted file mode 100644 index 193c5e2c..00000000 --- a/src/views/components/card.ecr +++ /dev/null @@ -1,49 +0,0 @@ -<% if item.is_a? NamedTuple(entry: Entry, percentage: Float64, grouped_count: Int32) %> -<% grouped_count = item[:grouped_count] %> -<% if grouped_count == 1 %> -<% item = item[:entry] %> -<% else %> -<% item = item[:entry].book %> -<% end %> -<% else %> -<% grouped_count = 1 %> -<% end %> - diff --git a/src/views/components/card.html.ecr b/src/views/components/card.html.ecr new file mode 100644 index 00000000..88ddd5fa --- /dev/null +++ b/src/views/components/card.html.ecr @@ -0,0 +1,50 @@ +<% if item.is_a? NamedTuple(entry: Entry, percentage: Float64, grouped_count: Int32) %> + <% grouped_count = item[:grouped_count] %> + <% if grouped_count == 1 %> + <% item = item[:entry] %> + <% else %> + <% item = item[:entry].book %> + <% end %> +<% else %> + <% grouped_count = 1 %> +<% end %> + + diff --git a/src/views/components/entry-modal.ecr b/src/views/components/entry-modal.html.ecr similarity index 61% rename from src/views/components/entry-modal.ecr rename to src/views/components/entry-modal.html.ecr index 73379602..672e5c3a 100644 --- a/src/views/components/entry-modal.ecr +++ b/src/views/components/entry-modal.html.ecr @@ -4,14 +4,14 @@
<% if page == "home" %> -

+

<% end %>

  <% unless page == "home" %> - <% if is_admin %> - - <% end %> + <% if is_admin %> + + <% end %> <% end %>

@@ -22,13 +22,13 @@

Read

- From beginning - + From beginning +

Progress

- - + +

diff --git a/src/views/components/head.ecr b/src/views/components/head.html.ecr similarity index 100% rename from src/views/components/head.ecr rename to src/views/components/head.html.ecr diff --git a/src/views/components/sort-form.ecr b/src/views/components/sort-form.html.ecr similarity index 56% rename from src/views/components/sort-form.ecr rename to src/views/components/sort-form.html.ecr index 6036a15a..93148d93 100644 --- a/src/views/components/sort-form.ecr +++ b/src/views/components/sort-form.html.ecr @@ -1,8 +1,8 @@
diff --git a/src/views/download-manager.ecr b/src/views/download-manager.html.ecr similarity index 74% rename from src/views/download-manager.ecr rename to src/views/download-manager.html.ecr index e1884380..03720109 100644 --- a/src/views/download-manager.ecr +++ b/src/views/download-manager.html.ecr @@ -23,10 +23,10 @@ <% content_for "script" do %> - - - - -<% end %> \ No newline at end of file + + + + +<% end %> diff --git a/src/views/download.ecr b/src/views/download.html.ecr similarity index 88% rename from src/views/download.ecr rename to src/views/download.html.ecr index d11c8645..402c137b 100644 --- a/src/views/download.ecr +++ b/src/views/download.html.ecr @@ -73,11 +73,11 @@ <% content_for "script" do %> - - - - - -<% end %> \ No newline at end of file + + + + + +<% end %> diff --git a/src/views/home.ecr b/src/views/home.ecr deleted file mode 100644 index 04f1bb8c..00000000 --- a/src/views/home.ecr +++ /dev/null @@ -1,69 +0,0 @@ -<%- if new_user && empty_library -%> - -
- -

Add your first manga

-

We can't find any files yet. Add some to your library and they'll appear here.

-
-
Current library path
-
<%= Config.current.library_path %>
-
Want to change your library path?
-
Update config.yml located at: <%= Config.current.path %>
-
Can't see your files yet?
-
You must wait <%= Config.current.scan_interval %> minutes for the library scan to complete - <% if is_admin %>, or manually re-scan from Admin<% end %>.
-
-
- -<%- elsif new_user && empty_library == false -%> - -
- -

Read your first manga

-

Once you start reading, Mango will remember where you left off - and show your entries here.

- View library -
- -<%- elsif new_user == false && empty_library == false -%> - -<%- if continue_reading.empty? && recently_added.empty? -%> -
- -

A self-hosted manga server and reader

- View library -
-<%- end -%> - -<%- unless continue_reading.empty? -%> -

Continue Reading

-
- <%- continue_reading.each do |cr| -%> - <% item = cr[:entry] %> - <% progress = cr[:percentage] %> - <%= render_component "card" %> - <%- end -%> -
-<%- end -%> - -<%- unless recently_added.empty? -%> -

Recently Added

-
- <%- recently_added.each do |ra| -%> - <% item = ra %> - <% progress = ra[:percentage] %> - <%= render_component "card" %> - <%- end -%> -
-<%- end -%> - -<%= render_component "entry-modal" %> - -<%- end -%> - -<% content_for "script" do %> - - - - -<% end %> diff --git a/src/views/home.html.ecr b/src/views/home.html.ecr new file mode 100644 index 00000000..cb0f53eb --- /dev/null +++ b/src/views/home.html.ecr @@ -0,0 +1,73 @@ +<%- if new_user && empty_library -%> + +
+ +

Add your first manga

+

We can't find any files yet. Add some to your library and they'll appear here.

+
+
Current library path
+
<%= Config.current.library_path %>
+
Want to change your library path?
+
Update config.yml located at: <%= Config.current.path %>
+
Can't see your files yet?
+
+ You must wait <%= Config.current.scan_interval %> minutes for the library scan to complete + <% if is_admin %> + , or manually re-scan from Admin + <% end %>. +
+
+
+ +<%- elsif new_user && empty_library == false -%> + +
+ +

Read your first manga

+

Once you start reading, Mango will remember where you left off + and show your entries here.

+ View library +
+ +<%- elsif new_user == false && empty_library == false -%> + + <%- if continue_reading.empty? && recently_added.empty? -%> +
+ +

A self-hosted manga server and reader

+ View library +
+ <%- end -%> + + <%- unless continue_reading.empty? -%> +

Continue Reading

+
+ <%- continue_reading.each do |cr| -%> + <% item = cr[:entry] %> + <% progress = cr[:percentage] %> + <%= render_component "card" %> + <%- end -%> +
+ <%- end -%> + + <%- unless recently_added.empty? -%> +

Recently Added

+
+ <%- recently_added.each do |ra| -%> + <% item = ra %> + <% progress = ra[:percentage] %> + <%= render_component "card" %> + <%- end -%> +
+ <%- end -%> + + <%= render_component "entry-modal" %> + +<%- end -%> + +<% content_for "script" do %> + + + + +<% end %> diff --git a/src/views/layout.ecr b/src/views/layout.ecr deleted file mode 100644 index 8242be55..00000000 --- a/src/views/layout.ecr +++ /dev/null @@ -1,68 +0,0 @@ - - - -<%= render_component "head" %> - - -
-
-
-
- -
-
-
-
-
-
-
-
-
-
- - -
-
- -
-
-
-
-
-
-
-
- <%= content %> -
-
- - - - - <%= yield_content "script" %> - - - diff --git a/src/views/layout.html.ecr b/src/views/layout.html.ecr new file mode 100644 index 00000000..2800ddc9 --- /dev/null +++ b/src/views/layout.html.ecr @@ -0,0 +1,68 @@ + + + + <%= render_component "head" %> + + +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+ <%= content %> +
+
+ + + + + <%= yield_content "script" %> + + + diff --git a/src/views/library.ecr b/src/views/library.html.ecr similarity index 69% rename from src/views/library.ecr rename to src/views/library.html.ecr index afbbec5a..2550f1e2 100644 --- a/src/views/library.ecr +++ b/src/views/library.html.ecr @@ -18,14 +18,14 @@
<% titles.each_with_index do |item, i| %> - <% progress = percentage[i] %> - <%= render_component "card" %> + <% progress = percentage[i] %> + <%= render_component "card" %> <% end %>
<% content_for "script" do %> - - - - + + + + <% end %> diff --git a/src/views/login.ecr b/src/views/login.ecr deleted file mode 100644 index 264395b9..00000000 --- a/src/views/login.ecr +++ /dev/null @@ -1,36 +0,0 @@ - - - -<%= render_component "head" %> - - -
-
-
-
-
-
-

Log In

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - - - - diff --git a/src/views/login.html.ecr b/src/views/login.html.ecr new file mode 100644 index 00000000..1bc122ad --- /dev/null +++ b/src/views/login.html.ecr @@ -0,0 +1,36 @@ + + + + <%= render_component "head" %> + + +
+
+
+
+
+
+

Log In

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + diff --git a/src/views/message.ecr b/src/views/message.ecr deleted file mode 100644 index 75467514..00000000 --- a/src/views/message.ecr +++ /dev/null @@ -1 +0,0 @@ -

<%= message %>

\ No newline at end of file diff --git a/src/views/message.html.ecr b/src/views/message.html.ecr new file mode 100644 index 00000000..1a5b8d85 --- /dev/null +++ b/src/views/message.html.ecr @@ -0,0 +1 @@ +

<%= message %>

diff --git a/src/views/opds/index.ecr b/src/views/opds/index.xml.ecr similarity index 67% rename from src/views/opds/index.ecr rename to src/views/opds/index.xml.ecr index 16fe193c..2d84b63f 100644 --- a/src/views/opds/index.ecr +++ b/src/views/opds/index.xml.ecr @@ -13,10 +13,10 @@ <% titles.each do |t| %> - - <%= t.display_name %> - urn:mango:<%= t.id %> - - + + <%= t.display_name %> + urn:mango:<%= t.id %> + + <% end %> diff --git a/src/views/opds/title.ecr b/src/views/opds/title.ecr deleted file mode 100644 index 476bb8de..00000000 --- a/src/views/opds/title.ecr +++ /dev/null @@ -1,38 +0,0 @@ - - - urn:mango:<%= title.id %> - - - - - <%= title.display_name %> - - - Mango - https://github.com/hkalexling/Mango - - - <% title.titles.each do |t| %> - - <%= t.display_name %> - urn:mango:<%= t.id %> - - - <% end %> - - <% title.entries.each do |e| %> - - <%= e.display_name %> - urn:mango:<%= e.id %> - - - - - - - - - - <% end %> - - diff --git a/src/views/opds/title.xml.ecr b/src/views/opds/title.xml.ecr new file mode 100644 index 00000000..80eadfa2 --- /dev/null +++ b/src/views/opds/title.xml.ecr @@ -0,0 +1,38 @@ + + + urn:mango:<%= title.id %> + + + + + <%= title.display_name %> + + + Mango + https://github.com/hkalexling/Mango + + + <% title.titles.each do |t| %> + + <%= t.display_name %> + urn:mango:<%= t.id %> + + + <% end %> + + <% title.entries.each do |e| %> + + <%= e.display_name %> + urn:mango:<%= e.id %> + + + + + + + + + + <% end %> + + diff --git a/src/views/reader.ecr b/src/views/reader.ecr deleted file mode 100644 index 86a53501..00000000 --- a/src/views/reader.ecr +++ /dev/null @@ -1,62 +0,0 @@ - - - -<%= render_component "head" %> - - -
-
- <%- urls.each_with_index do |url, i| -%> - - <%- end -%> - <%- if next_url -%> - - <%- end -%> -
- <%- if next_entry_url -%> - - <%- else -%> - - <%- end -%> -
- - - - - - - - - - - - - diff --git a/src/views/reader.html.ecr b/src/views/reader.html.ecr new file mode 100644 index 00000000..f7911630 --- /dev/null +++ b/src/views/reader.html.ecr @@ -0,0 +1,62 @@ + + + + <%= render_component "head" %> + + +
+
+ <%- urls.each_with_index do |url, i| -%> + + <%- end -%> + <%- if next_url -%> + + <%- end -%> +
+ <%- if next_entry_url -%> + + <%- else -%> + + <%- end -%> +
+ + + + + + + + + + + + + diff --git a/src/views/title.ecr b/src/views/title.html.ecr similarity index 75% rename from src/views/title.ecr rename to src/views/title.html.ecr index ec201a64..b926a5a4 100644 --- a/src/views/title.ecr +++ b/src/views/title.html.ecr @@ -2,14 +2,14 @@

<%= title.display_name %>   <% if is_admin %> - + <% end %>

@@ -33,12 +33,12 @@
<% title.titles.each_with_index do |item, i| %> - <% progress = title_percentage[i] %> - <%= render_component "card" %> + <% progress = title_percentage[i] %> + <%= render_component "card" %> <% end %> <% title.entries.each_with_index do |item, i| %> - <% progress = percentage[i] %> - <%= render_component "card" %> + <% progress = percentage[i] %> + <%= render_component "card" %> <% end %>
@@ -85,8 +85,8 @@
@@ -94,10 +94,10 @@
<% content_for "script" do %> - - - - - - + + + + + + <% end %> diff --git a/src/views/user-edit.ecr b/src/views/user-edit.ecr deleted file mode 100644 index 9b354d2c..00000000 --- a/src/views/user-edit.ecr +++ /dev/null @@ -1,46 +0,0 @@ -
- -
- - value=<%= username %> <%- end -%>> -
- <%- if new_user -%> -
- - -
- <%- end -%> -
- - checked <%- end -%>> -
- - <%- if !new_user -%> -
- - -
- <%- end -%> - -
- - -
- -<% content_for "script" do %> - - - -<% end %> \ No newline at end of file diff --git a/src/views/user-edit.html.ecr b/src/views/user-edit.html.ecr new file mode 100644 index 00000000..22916de0 --- /dev/null +++ b/src/views/user-edit.html.ecr @@ -0,0 +1,46 @@ +
+ +
+ + value=<%= username %> <%- end -%>> +
+ <%- if new_user -%> +
+ + +
+ <%- end -%> +
+ + checked <%- end -%>> +
+ + <%- unless new_user -%> +
+ + +
+ <%- end -%> + +
+ + +
+ +<% content_for "script" do %> + + + +<% end %> diff --git a/src/views/user.ecr b/src/views/user.ecr deleted file mode 100644 index 3887d2ae..00000000 --- a/src/views/user.ecr +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - <%- users.each do |u| -%> - - - - - - <%- end -%> - -
UsernameAdmin AccessActions
<%= u[0] %><%= u[1] %> - - <%- if u[0] != username %> - - <%- end %> -
- -New User - - -<% content_for "script" do %> - - -<% end %> \ No newline at end of file diff --git a/src/views/user.html.ecr b/src/views/user.html.ecr new file mode 100644 index 00000000..c65dbb72 --- /dev/null +++ b/src/views/user.html.ecr @@ -0,0 +1,31 @@ + + + + + + + + + + <%- users.each do |u| -%> + + + + + + <%- end -%> + +
UsernameAdmin AccessActions
<%= u[0] %><%= u[1] %> + + <%- if u[0] != username %> + + <%- end %> +
+ +New User + + +<% content_for "script" do %> + + +<% end %> From 62af879bfa89a95f7acb9a3dcb426854a6c792bd Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Sat, 20 Jun 2020 09:09:13 +0000 Subject: [PATCH 25/27] Upgrade Crystal to 0.35.1 --- .github/workflows/build.yml | 2 +- Dockerfile | 2 +- shard.lock | 26 +++++++++++++------------- shard.yml | 3 ++- src/archive.cr | 22 +++++++++++----------- src/logger.cr | 10 ++++++---- src/mangadex/downloader.cr | 6 +++--- 7 files changed, 37 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37d86c64..00f716f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest container: - image: crystallang/crystal:0.34.0-alpine + image: crystallang/crystal:0.35.1-alpine steps: - uses: actions/checkout@v2 diff --git a/Dockerfile b/Dockerfile index 6ce10b20..bcbb0116 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM crystallang/crystal:0.34.0-alpine AS builder +FROM crystallang/crystal:0.35.1-alpine AS builder WORKDIR /Mango diff --git a/shard.lock b/shard.lock index 2d95a6fe..dc0322a6 100644 --- a/shard.lock +++ b/shard.lock @@ -1,46 +1,46 @@ -version: 1.0 +version: 2.0 shards: ameba: - github: crystal-ameba/ameba + git: https://github.com/crystal-ameba/ameba.git version: 0.12.1 archive: - github: hkalexling/archive.cr + git: https://github.com/hkalexling/archive.cr.git version: 0.2.0 baked_file_system: - github: schovi/baked_file_system + git: https://github.com/schovi/baked_file_system.git version: 0.9.8 clim: - github: at-grandpa/clim + git: https://github.com/at-grandpa/clim.git version: 0.12.0 db: - github: crystal-lang/crystal-db + git: https://github.com/crystal-lang/crystal-db.git version: 0.9.0 exception_page: - github: crystal-loot/exception_page + git: https://github.com/crystal-loot/exception_page.git version: 0.1.4 kemal: - github: kemalcr/kemal - version: 0.26.1 + git: https://github.com/kemalcr/kemal.git + version: 0.26.1+git.commit.a8c0f09b858162bd13c96663febef5527b322a32 kemal-session: - github: kemalcr/kemal-session + git: https://github.com/kemalcr/kemal-session.git version: 0.12.1 kilt: - github: jeromegn/kilt + git: https://github.com/jeromegn/kilt.git version: 0.4.0 radix: - github: luislavena/radix + git: https://github.com/luislavena/radix.git version: 0.3.9 sqlite3: - github: crystal-lang/crystal-sqlite3 + git: https://github.com/crystal-lang/crystal-sqlite3.git version: 0.16.0 diff --git a/shard.yml b/shard.yml index b9e2975c..ca74f980 100644 --- a/shard.yml +++ b/shard.yml @@ -8,13 +8,14 @@ targets: mango: main: src/mango.cr -crystal: 0.34.0 +crystal: 0.35.0 license: MIT dependencies: kemal: github: kemalcr/kemal + commit: a8c0f09b858162bd13c96663febef5527b322a32 kemal-session: github: kemalcr/kemal-session sqlite3: diff --git a/src/archive.cr b/src/archive.cr index 29dedfba..98423d1b 100644 --- a/src/archive.cr +++ b/src/archive.cr @@ -1,13 +1,13 @@ -require "zip" +require "compress/zip" require "archive" -# A unified class to handle all supported archive formats. It uses the ::Zip -# module in crystal standard library if the target file is a zip archive. -# Otherwise it uses `archive.cr`. +# A unified class to handle all supported archive formats. It uses the +# Compress::Zip module in crystal standard library if the target file is a +# zip archive. Otherwise it uses `archive.cr`. class ArchiveFile def initialize(@filename : String) if [".cbz", ".zip"].includes? File.extname filename - @archive_file = Zip::File.new filename + @archive_file = Compress::Zip::File.new filename else @archive_file = Archive::File.new filename end @@ -20,16 +20,16 @@ class ArchiveFile end def close - if @archive_file.is_a? Zip::File - @archive_file.as(Zip::File).close + if @archive_file.is_a? Compress::Zip::File + @archive_file.as(Compress::Zip::File).close end end # Lists all file entries def entries - ary = [] of Zip::File::Entry | Archive::Entry + ary = [] of Compress::Zip::File::Entry | Archive::Entry @archive_file.entries.map do |e| - if (e.is_a? Zip::File::Entry && e.file?) || + if (e.is_a? Compress::Zip::File::Entry && e.file?) || (e.is_a? Archive::Entry && e.info.file?) ary.push e end @@ -37,8 +37,8 @@ class ArchiveFile ary end - def read_entry(e : Zip::File::Entry | Archive::Entry) : Bytes? - if e.is_a? Zip::File::Entry + def read_entry(e : Compress::Zip::File::Entry | Archive::Entry) : Bytes? + if e.is_a? Compress::Zip::File::Entry data = nil e.open do |io| slice = Bytes.new e.uncompressed_size diff --git a/src/logger.cr b/src/logger.cr index 8c049ed0..b1d02a55 100644 --- a/src/logger.cr +++ b/src/logger.cr @@ -31,9 +31,9 @@ class Logger {% end %} @log = Log.for("") - @backend = Log::IOBackend.new - @backend.formatter = ->(entry : Log::Entry, io : IO) do + + format_proc = ->(entry : Log::Entry, io : IO) do color = :default {% begin %} case entry.severity.label.to_s().downcase @@ -50,12 +50,14 @@ class Logger io << entry.message end - Log.builder.bind "*", @@severity, @backend + @backend.formatter = Log::Formatter.new &format_proc + Log.setup @@severity, @backend end # Ignores @@severity and always log msg def log(msg) - @backend.write Log::Entry.new "", Log::Severity::None, msg, nil + @backend.write Log::Entry.new "", Log::Severity::None, msg, + Log::Metadata.empty, nil end def self.log(msg) diff --git a/src/mangadex/downloader.cr b/src/mangadex/downloader.cr index 6a62e591..ba49de39 100644 --- a/src/mangadex/downloader.cr +++ b/src/mangadex/downloader.cr @@ -1,13 +1,13 @@ require "./api" require "sqlite3" -require "zip" +require "compress/zip" module MangaDex class PageJob property success = false property url : String property filename : String - property writer : Zip::Writer + property writer : Compress::Zip::Writer property tries_remaning : Int32 def initialize(@url, @filename, @writer, @tries_remaning) @@ -324,7 +324,7 @@ module MangaDex # Find the number of digits needed to store the number of pages len = Math.log10(chapter.pages.size).to_i + 1 - writer = Zip::Writer.new zip_path + writer = Compress::Zip::Writer.new zip_path # Create a buffered channel. It works as an FIFO queue channel = Channel(PageJob).new chapter.pages.size spawn do From b83313b231d3f5043000d8688d696672b71a04e3 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Sat, 20 Jun 2020 09:36:30 +0000 Subject: [PATCH 26/27] Set recently added group range to 1 day --- src/library.cr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library.cr b/src/library.cr index 8236ed60..6fdff2dc 100644 --- a/src/library.cr +++ b/src/library.cr @@ -575,7 +575,8 @@ class Library .sort { |a, b| b.date_added <=> a.date_added } .each do |e| last = recently_added.last? - if last && e.title_id == last[:entry].title_id + if last && e.title_id == last[:entry].title_id && + (e.date_added - last[:entry].date_added).duration < 1.day # A NamedTuple is immutable, so we have to cast it to a Hash first last_hash = last.to_h count = last_hash[:grouped_count].as(Int32) From a317086f81cd7f91c63999de17b1b5fa605008f2 Mon Sep 17 00:00:00 2001 From: Alex Ling Date: Sat, 20 Jun 2020 13:27:44 +0000 Subject: [PATCH 27/27] Bump version to v0.7.0 --- README.md | 2 +- shard.yml | 2 +- src/mango.cr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3ed6b9ea..893078b2 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ The official docker images are available on [Dockerhub](https://hub.docker.com/r ### CLI ``` - Mango - Manga Server and Web Reader. Version 0.6.1 + Mango - Manga Server and Web Reader. Version 0.7.0 Usage: diff --git a/shard.yml b/shard.yml index ca74f980..c8ed636c 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: mango -version: 0.6.1 +version: 0.7.0 authors: - Alex Ling diff --git a/src/mango.cr b/src/mango.cr index d0484c99..ab814c0a 100644 --- a/src/mango.cr +++ b/src/mango.cr @@ -4,7 +4,7 @@ require "./mangadex/*" require "option_parser" require "clim" -MANGO_VERSION = "0.6.1" +MANGO_VERSION = "0.7.0" macro common_option option "-c PATH", "--config=PATH", type: String,