Show unreadable archives in web interface (#49)

This commit is contained in:
Alex Ling 2020-07-18 13:29:03 +00:00
parent 1b244c68b8
commit bdba7bdd13
6 changed files with 96 additions and 38 deletions

View File

@ -97,3 +97,7 @@ td>.uk-dropdown {
.item .uk-card-title { .item .uk-card-title {
font-size: 1rem; font-size: 1rem;
} }
.grayscale {
filter: grayscale(100%);
}

View File

@ -1,20 +1,14 @@
class Entry class Entry
property zip_path : String, book : Title, title : String, property zip_path : String, book : Title, title : String,
size : String, pages : Int32, id : String, title_id : String, size : String, pages : Int32, id : String, title_id : String,
encoded_path : String, encoded_title : String, mtime : Time encoded_path : String, encoded_title : String, mtime : Time,
err_msg : String?
def initialize(path, @book, @title_id, storage) def initialize(@zip_path, @book, @title_id, storage)
@zip_path = path @encoded_path = URI.encode @zip_path
@encoded_path = URI.encode path @title = File.basename @zip_path, File.extname @zip_path
@title = File.basename path, File.extname path
@encoded_title = URI.encode @title @encoded_title = URI.encode @title
@size = (File.size path).humanize_bytes @size = (File.size @zip_path).humanize_bytes
file = ArchiveFile.new path
@pages = file.entries.count do |e|
SUPPORTED_IMG_TYPES.includes? \
MIME.from_filename? e.filename
end
file.close
id = storage.get_id @zip_path, false id = storage.get_id @zip_path, false
if id.nil? if id.nil?
id = random_str id = random_str
@ -26,6 +20,28 @@ class Entry
end end
@id = id @id = id
@mtime = File.info(@zip_path).modification_time @mtime = File.info(@zip_path).modification_time
unless File.readable? @zip_path
@err_msg = "File #{@zip_path} is not readable."
Logger.warn "#{@err_msg} Please make sure the " \
"file permission is configured correctly."
return
end
archive_exception = validate_archive @zip_path
unless archive_exception.nil?
@err_msg = "Archive error: #{archive_exception}"
Logger.warn "Unable to extract archive #{@zip_path}. " \
"Ignoring it. #{@err_msg}"
return
end
file = ArchiveFile.new @zip_path
@pages = file.entries.count do |e|
SUPPORTED_IMG_TYPES.includes? \
MIME.from_filename? e.filename
end
file.close
end end
def to_json(json : JSON::Builder) def to_json(json : JSON::Builder)
@ -50,6 +66,7 @@ class Entry
end end
def cover_url def cover_url
return "#{Config.current.base_url}img/icon.png" if @err_msg
url = "#{Config.current.base_url}api/page/#{@title_id}/#{@id}/1" url = "#{Config.current.base_url}api/page/#{@title_id}/#{@id}/1"
TitleInfo.new @book.dir do |info| TitleInfo.new @book.dir do |info|
info_url = info.entry_cover_url[@title]? info_url = info.entry_cover_url[@title]?
@ -61,6 +78,7 @@ class Entry
end end
def read_page(page_num) def read_page(page_num)
raise "Unreadble archive. #{@err_msg}" if @err_msg
img = nil img = nil
ArchiveFile.open @zip_path do |file| ArchiveFile.open @zip_path do |file|
page = file.entries page = file.entries

View File

@ -34,19 +34,8 @@ class Title
next next
end end
if [".zip", ".cbz", ".rar", ".cbr"].includes? File.extname path if [".zip", ".cbz", ".rar", ".cbr"].includes? File.extname path
unless File.readable? path
Logger.warn "File #{path} is not readable. Please make sure the " \
"file permission is configured correctly."
next
end
archive_exception = validate_archive path
unless archive_exception.nil?
Logger.warn "Unable to extract archive #{path}. Ignoring it. " \
"Archive error: #{archive_exception}"
next
end
entry = Entry.new path, self, @id, storage entry = Entry.new path, self, @id, storage
@entries << entry if entry.pages > 0 @entries << entry if entry.pages > 0 || entry.err_msg
end end
end end
@ -166,8 +155,9 @@ class Title
def cover_url def cover_url
url = "#{Config.current.base_url}img/icon.png" url = "#{Config.current.base_url}img/icon.png"
if @entries.size > 0 readable_entries = @entries.select &.err_msg.nil?
url = @entries[0].cover_url if readable_entries.size > 0
url = readable_entries[0].cover_url
end end
TitleInfo.new @dir do |info| TitleInfo.new @dir do |info|
info_url = info.cover_url info_url = info.cover_url

View File

@ -4,11 +4,14 @@ class ReaderRouter < Router
def initialize def initialize
get "/reader/:title/:entry" do |env| get "/reader/:title/:entry" do |env|
begin begin
username = get_username env
title = (@context.library.get_title env.params.url["title"]).not_nil! title = (@context.library.get_title env.params.url["title"]).not_nil!
entry = (title.get_entry env.params.url["entry"]).not_nil! entry = (title.get_entry env.params.url["entry"]).not_nil!
next layout "reader-error" if entry.err_msg
# load progress # load progress
username = get_username env
page = entry.load_progress username page = entry.load_progress username
# we go back 2 * `IMGS_PER_PAGE` pages. the infinite scroll # we go back 2 * `IMGS_PER_PAGE` pages. the infinite scroll
# library perloads a few pages in advance, and the user # library perloads a few pages in advance, and the user

View File

@ -15,29 +15,36 @@
<% end %>> <% end %>>
<div class="acard <div class="acard
<% if item.is_a? Entry %> <% if item.is_a? Entry && item.err_msg.nil? %>
<%= "is_entry" %> <%= "is_entry" %>
<% end %> <% end %>
" "
<% if item.is_a? Entry %> <% if item.is_a? Entry %>
data-encoded-path="<%= item.encoded_path %>" <% if item.err_msg %>
data-pages="<%= item.pages %>" onclick="location='<%= base_url %>reader/<%= item.book.id %>/<%= item.id %>'"
data-progress="<%= (progress * 100).round(1) %>" <% else %>
data-encoded-book-title="<%= item.book.encoded_display_name %>" data-encoded-path="<%= item.encoded_path %>"
data-encoded-title="<%= item.encoded_display_name %>" data-pages="<%= item.pages %>"
data-book-id="<%= item.book.id %>" data-progress="<%= (progress * 100).round(1) %>"
data-id="<%= item.id %>" data-encoded-book-title="<%= item.book.encoded_display_name %>"
data-encoded-title="<%= item.encoded_display_name %>"
data-book-id="<%= item.book.id %>"
data-id="<%= item.id %>"
<% end %>
<% else %> <% else %>
onclick="location='<%= base_url %>book/<%= item.id %>'" onclick="location='<%= base_url %>book/<%= item.id %>'"
<% end %>> <% end %>>
<div class="uk-card uk-card-default"> <div class="uk-card uk-card-default">
<div class="uk-card-media-top"> <div class="uk-card-media-top">
<img data-src="<%= item.cover_url %>" data-width data-height alt="" uk-img> <img data-src="<%= item.cover_url %>" data-width data-height alt="" uk-img
<% if item.is_a? Entry && item.err_msg %>
class="grayscale"
<% end %>>
</div> </div>
<div class="uk-card-body"> <div class="uk-card-body">
<% unless progress < 0 || progress > 100 %> <% unless progress < 0 || progress > 100 || progress.nan? %>
<div class="uk-card-badge label"><%= (progress * 100).round(1) %>%</div> <div class="uk-card-badge label"><%= (progress * 100).round(1) %>%</div>
<% end %> <% end %>
@ -51,7 +58,12 @@
<a class="uk-card-title break-word uk-margin-remove-top uk-text-meta uk-display-inline-block no-modal" data-title="<%= HTML.escape(item.book.display_name) %>" href="<%= base_url %>book/<%= item.book.id %>"><%= HTML.escape(item.book.display_name) %></a> <a class="uk-card-title break-word uk-margin-remove-top uk-text-meta uk-display-inline-block no-modal" data-title="<%= HTML.escape(item.book.display_name) %>" href="<%= base_url %>book/<%= item.book.id %>"><%= HTML.escape(item.book.display_name) %></a>
<% end %> <% end %>
<% if item.is_a? Entry %> <% if item.is_a? Entry %>
<p class="uk-text-meta"><%= item.pages %> pages</p> <% if item.err_msg %>
<p class="uk-text-meta uk-margin-remove-bottom">Error <span uk-icon="info"></span></p>
<div uk-dropdown><%= item.err_msg %></div>
<% else %>
<p class="uk-text-meta"><%= item.pages %> pages</p>
<% end %>
<% end %> <% end %>
<% if item.is_a? Title %> <% if item.is_a? Title %>
<% if grouped_count == 1 %> <% if grouped_count == 1 %>

View File

@ -0,0 +1,31 @@
<div id="modal" class="uk-flex-top" uk-modal>
<div class="uk-modal-dialog uk-margin-auto-vertical">
<button class="uk-modal-close-default" type="button" uk-close></button>
<div class="uk-modal-header">
<div>
<h3 class="uk-modal-title uk-margin-remove-top">Error</h3>
</div>
<p class="uk-text-meta uk-margin-remove-bottom"><%= entry.zip_path %></p>
<p class="uk-text-meta uk-margin-remove-top"><%= entry.err_msg %></p>
</div>
<div class="uk-modal-body">
<p uk-margin>
<% if next_entry = entry.next_entry username %>
<a class="uk-button uk-button-default" href="<%= base_url %>reader/<%= entry.book.id %>/<%= next_entry.id %>">Next Entry</a>
<% end %>
<a class="uk-button uk-button-primary" href="<%= base_url %>book/<%= entry.book.id %>">Return to Title</a>
</p>
</div>
</div>
</div>
<% content_for "script" do %>
<script>
UIkit.modal('#modal').show().then(function() {
styleModal();
});
UIkit.util.on('#modal', 'hide', function() {
location.href = "<%= base_url %>book/<%= entry.book.id %>";
});
</script>
<% end %>