From 2e7a9101781577d3178e04583903dcdad24374a5 Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Fri, 28 Jun 2019 04:46:16 +0200 Subject: [PATCH] Some BookStatus QoL tweaks (#5100) * Make the cover thumbnail respect the cover's AR in the widget * Add a "Mark as read/unread" button in the FM's longpress menu. * Make sure the cover_info cache is wiped if necessary (sidecar purge/BookInfo cache clear). --- frontend/ui/widget/bookstatuswidget.lua | 31 +++++++- frontend/ui/widget/button.lua | 6 ++ frontend/ui/widget/buttontable.lua | 1 + frontend/util.lua | 10 +++ plugins/coverbrowser.koplugin/covermenu.lua | 79 ++++++++++++++++++++- 5 files changed, 122 insertions(+), 5 deletions(-) diff --git a/frontend/ui/widget/bookstatuswidget.lua b/frontend/ui/widget/bookstatuswidget.lua index e9176ab59..d48bc6b9e 100644 --- a/frontend/ui/widget/bookstatuswidget.lua +++ b/frontend/ui/widget/bookstatuswidget.lua @@ -17,6 +17,7 @@ local LeftContainer = require("ui/widget/container/leftcontainer") local LineWidget = require("ui/widget/linewidget") local OverlapGroup = require("ui/widget/overlapgroup") local ProgressWidget = require("ui/widget/progresswidget") +local RenderImage = require("ui/renderimage") local Size = require("ui/size") local TextBoxWidget = require("ui/widget/textboxwidget") local TextWidget = require("ui/widget/textwidget") @@ -56,12 +57,27 @@ local BookStatusWidget = InputContainer:new{ function BookStatusWidget:init() if self.settings then - self.summary = self.settings:readSetting("summary") or { + -- What a blank, full summary table should look like + local new_summary = { rating = nil, note = nil, status = "", modified = "", } + local summary = self.settings:readSetting("summary") + -- Check if the summary table we get is a full one, or a minimal one from CoverMenu... + if summary then + if summary.modified then + -- Complete, use it as-is + self.summary = summary + else + -- Incomplete, fill it up + self.summary = new_summary + util.tableMerge(self.summary, summary) + end + else + self.summary = new_summary + end end self.total_pages = self.view.document:getPageCount() stats_book = self:getStats() @@ -343,10 +359,19 @@ function BookStatusWidget:genBookInfoGroup() } -- thumbnail if self.thumbnail then + -- Much like BookInfoManager, honor AR here + local cbb_w, cbb_h = self.thumbnail:getWidth(), self.thumbnail:getHeight() + if cbb_w > img_width or cbb_h > img_height then + local scale_factor = math.min(img_width / cbb_w, img_height / cbb_h) + cbb_w = math.min(math.floor(cbb_w * scale_factor)+1, img_width) + cbb_h = math.min(math.floor(cbb_h * scale_factor)+1, img_height) + self.thumbnail = RenderImage:scaleBlitBuffer(self.thumbnail, cbb_w, cbb_h, true) + end + table.insert(book_info_group, ImageWidget:new{ image = self.thumbnail, - width = img_width, - height = img_height, + width = cbb_w, + height = cbb_h, }) -- dereference thumbnail since we let imagewidget manages its lifecycle self.thumbnail = nil diff --git a/frontend/ui/widget/button.lua b/frontend/ui/widget/button.lua index 9c1d67377..8e0755f55 100644 --- a/frontend/ui/widget/button.lua +++ b/frontend/ui/widget/button.lua @@ -31,6 +31,7 @@ local _ = require("gettext") local Button = InputContainer:new{ text = nil, -- mandatory + text_func = nil, icon = nil, preselect = false, callback = nil, @@ -48,6 +49,11 @@ local Button = InputContainer:new{ } function Button:init() + -- Prefer an optional text_func over text + if self.text_func and type(self.text_func) == "function" then + self.text = self.text_func() + end + if self.text then self.label_widget = TextWidget:new{ text = self.text, diff --git a/frontend/ui/widget/buttontable.lua b/frontend/ui/widget/buttontable.lua index 700a5a60a..2896da69e 100644 --- a/frontend/ui/widget/buttontable.lua +++ b/frontend/ui/widget/buttontable.lua @@ -51,6 +51,7 @@ function ButtonTable:init() local btn_entry = row[j] local button = Button:new{ text = btn_entry.text, + text_func = btn_entry.text_func, enabled = btn_entry.enabled, callback = btn_entry.callback, hold_callback = btn_entry.hold_callback, diff --git a/frontend/util.lua b/frontend/util.lua index a441784dd..8e13305f8 100644 --- a/frontend/util.lua +++ b/frontend/util.lua @@ -184,6 +184,16 @@ function util.arrayAppend(t1, t2) end end +-- Merge t2 into t1, overwriting existing elements if they already exist +-- Probably not safe with nested tables (c.f., https://stackoverflow.com/q/1283388) +---- @param t1 Lua table +---- @param t2 Lua table +function util.tableMerge(t1, t2) + for k, v in pairs(t2) do + t1[k] = v + end +end + --[[-- Gets last index of string in character diff --git a/plugins/coverbrowser.koplugin/covermenu.lua b/plugins/coverbrowser.koplugin/covermenu.lua index 19ea0533a..100fcafde 100644 --- a/plugins/coverbrowser.koplugin/covermenu.lua +++ b/plugins/coverbrowser.koplugin/covermenu.lua @@ -1,4 +1,5 @@ local DocumentRegistry = require("document/documentregistry") +local DocSettings = require("docsettings") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local ImageViewer = require("ui/widget/imageviewer") local InfoMessage = require("ui/widget/infomessage") @@ -224,7 +225,77 @@ function CoverMenu:updateItems(select_number) UIManager:close(self.file_dialog) end + -- Fudge the "Purge .sdr" button ([1][3]) callback to also trash the cover_info_cache + local orig_purge_callback = orig_buttons[1][3].callback + orig_buttons[1][3].callback = function() + -- Wipe the cache + if self.cover_info_cache[file] then + self.cover_info_cache[file] = nil + end + -- And then purge the sidecar folder as expected + orig_purge_callback() + end + -- Add some new buttons to original buttons set + table.insert(orig_buttons, { + { -- Mark the book as read/unread + text_func = function() + -- If the book has a cache entry, it means it has a sidecar file, and it *may* have the info we need. + local status + if self.cover_info_cache[file] then + local _, _, c_status = unpack(self.cover_info_cache[file]) + status = c_status + end + -- NOTE: status may still be nil if the BookStatus widget was never opened in this book. + -- For our purposes, we assume this means reading or on hold, which is just fine. + -- NOTE: This also means we assume "on hold" means reading, meaning it'll be flipped to "finished", + -- which I'm personally okay with, too. + -- c.f., BookStatusWidget:generateSwitchGroup for the three possible constant values. + return status == "complete" and _("Mark as reading") or _("Mark as read") + end, + enabled = true, + callback = function() + local status + if self.cover_info_cache[file] then + local c_pages, c_percent_finished, c_status = unpack(self.cover_info_cache[file]) + status = c_status == "complete" and "reading" or "complete" + -- Update the cache, even if it had a nil status before + self.cover_info_cache[file] = {c_pages, c_percent_finished, status} + else + -- We assumed earlier an empty status meant "reading", so, flip that to "complete" + status = "complete" + end + + -- In case the book doesn't have a sidecar file, this'll create it + local docinfo = DocSettings:open(file) + if docinfo.data.summary and docinfo.data.summary.status then + -- Book already had the full BookStatus table in its sidecar, easy peasy! + docinfo.data.summary.status = status + else + -- No BookStatus table, create a minimal one... + if docinfo.data.summary then + -- Err, a summary table with no status entry? Should never happen... + local summary = { status = status } + -- Append the status entry to the existing summary... + require("util").tableMerge(docinfo.data.summary, summary) + else + -- No summary table at all, create a minimal one + local summary = { status = status } + docinfo:saveSetting("summary", summary) + end + end + docinfo:flush() + + UIManager:close(self.file_dialog) + self:updateItems() + end, + }, + }) + + -- Move the "Convert" button ([4][2]) to the left of the "Mark as..." button [5][1] we've just added + table.insert(orig_buttons[5], 1, table.remove(orig_buttons[4], 2)) + + -- Keep on adding new buttons table.insert(orig_buttons, { { -- Allow user to view real size cover in ImageViewer text = _("View full size cover"), @@ -262,8 +333,8 @@ function CoverMenu:updateItems(select_number) title = bookinfo.title, text = description, } - UIManager:show(textviewer) UIManager:close(self.file_dialog) + UIManager:show(textviewer) end, }, }) @@ -296,6 +367,10 @@ function CoverMenu:updateItems(select_number) text = _("Refresh cached book information"), enabled = bookinfo and true or false, callback = function() + -- Wipe the cache + if self.cover_info_cache[file] then + self.cover_info_cache[file] = nil + end BookInfoManager:deleteBookInfo(file) UIManager:close(self.file_dialog) self:updateItems() @@ -391,8 +466,8 @@ function CoverMenu:onHistoryMenuHold(item) title = bookinfo.title, text = description, } - UIManager:show(textviewer) UIManager:close(self.histfile_dialog) + UIManager:show(textviewer) end, }, })