diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 57f7a4e6e..6db7b68cf 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -271,9 +271,9 @@ function FileManager:setupLayout() self.book_props = nil -- in 'self' to provide access to it in CoverBrowser local has_provider = DocumentRegistry:hasProvider(file) local has_sidecar = DocSettings:hasSidecarFile(file) + local doc_settings_or_file if has_provider or has_sidecar then self.book_props = file_manager.coverbrowser and file_manager.coverbrowser:getBookInfo(file) - local doc_settings_or_file if has_sidecar then doc_settings_or_file = DocSettings:open(file) if not self.book_props then @@ -299,7 +299,7 @@ function FileManager:setupLayout() file_manager:showOpenWithDialog(file) end, }, - filemanagerutil.genBookInformationButton(file, self.book_props, close_dialog_callback), + filemanagerutil.genBookInformationButton(doc_settings_or_file or file, self.book_props, close_dialog_callback), }) if has_provider then table.insert(buttons, { diff --git a/frontend/apps/filemanager/filemanagerbookinfo.lua b/frontend/apps/filemanager/filemanagerbookinfo.lua index c92ff222e..16f34e424 100644 --- a/frontend/apps/filemanager/filemanagerbookinfo.lua +++ b/frontend/apps/filemanager/filemanagerbookinfo.lua @@ -21,6 +21,7 @@ local lfs = require("libs/libkoreader-lfs") local util = require("util") local _ = require("gettext") local N_ = _.ngettext +local Screen = Device.screen local T = require("ffi/util").template local BookInfo = WidgetContainer:extend{ @@ -37,7 +38,7 @@ local BookInfo = WidgetContainer:extend{ prop_text = { cover = _("Cover image:"), title = _("Title:"), - authors = _("Authors:"), + authors = _("Author(s):"), series = _("Series:"), series_index = _("Series index:"), language = _("Language:"), @@ -45,6 +46,7 @@ local BookInfo = WidgetContainer:extend{ description = _("Description:"), pages = _("Pages:"), }, + rating_max = 5, } function BookInfo:init() @@ -63,11 +65,14 @@ function BookInfo:addToMainMenu(menu_items) end -- Shows book information. -function BookInfo:show(file, book_props) +function BookInfo:show(doc_settings_or_file, book_props) self.prop_updated = nil + self.summary_updated = nil local kv_pairs = {} -- File section + local has_sidecar = type(doc_settings_or_file) == "table" + local file = has_sidecar and doc_settings_or_file:readSetting("doc_path") or doc_settings_or_file local folder, filename = util.splitFilePathName(file) local __, filetype = filemanagerutil.splitFileNameType(filename) local attr = lfs.attributes(file) @@ -149,17 +154,25 @@ function BookInfo:show(file, book_props) end -- pages local is_doc = self.document and true or false - table.insert(kv_pairs, { self.prop_text["pages"], book_props["pages"] or _("N/A"), separator = is_doc }) + table.insert(kv_pairs, { self.prop_text["pages"], book_props["pages"] or _("N/A"), separator = true }) + + -- Summary section + local summary = has_sidecar and doc_settings_or_file:readSetting("summary") or {} + local rating = summary.rating or 0 + local summary_hold_callback = function() + self:editSummary(doc_settings_or_file, book_props) + end + table.insert(kv_pairs, { _("Rating:"), ("★"):rep(rating) .. ("☆"):rep(self.rating_max - rating), + hold_callback = summary_hold_callback }) + table.insert(kv_pairs, { _("Review:"), summary.note or _("N/A"), + hold_callback = summary_hold_callback, separator = is_doc }) -- Page section if is_doc then local lines_nb, words_nb = self.ui.view:getCurrentPageLineWordCounts() - if lines_nb == 0 then - lines_nb = _("N/A") - words_nb = _("N/A") - end - table.insert(kv_pairs, { _("Current page lines:"), lines_nb }) - table.insert(kv_pairs, { _("Current page words:"), words_nb }) + local text = lines_nb == 0 and _("number of lines and words not available") + or T(N_("1 line", "%1 lines", lines_nb), lines_nb) .. ", " .. T(N_("1 word", "%1 words", words_nb), words_nb) + table.insert(kv_pairs, { _("Current page:"), text }) end local KeyValuePage = require("ui/widget/keyvaluepage") @@ -175,6 +188,9 @@ function BookInfo:show(file, book_props) UIManager:broadcastEvent(Event:new("InvalidateMetadataCache", file)) UIManager:broadcastEvent(Event:new("BookMetadataChanged", self.prop_updated)) end + if self.summary_updated then -- refresh file browser, sdr folder may appear + UIManager:broadcastEvent(Event:new("BookMetadataChanged")) + end end, } UIManager:show(self.kvp_widget) @@ -295,7 +311,7 @@ end function BookInfo:onShowBookInfo() if self.document then self.ui.doc_props.pages = self.ui.doc_settings:readSetting("doc_pages") - self:show(self.document.file, self.ui.doc_props) + self:show(self.ui.doc_settings, self.ui.doc_props) end end @@ -587,6 +603,70 @@ function BookInfo:showCustomDialog(file, book_props, prop_key) UIManager:show(button_dialog) end +function BookInfo:editSummary(doc_settings_or_file, book_props) + local has_sidecar = type(doc_settings_or_file) == "table" + local summary = has_sidecar and doc_settings_or_file:readSetting("summary") or {} + local rating = summary.rating or 0 + local input_dialog + local rating_buttons_row = {} + for i = -1, self.rating_max + 2 do -- 2 empty buttons on each side + if i < 1 or i > self.rating_max then + table.insert(rating_buttons_row, { + text = "", + no_vertical_sep = true, + enabled = false, + }) + else + table.insert(rating_buttons_row, { + text = i <= rating and "★" or "☆", + no_vertical_sep = true, + callback = function() + UIManager:close(input_dialog) + local note = input_dialog:getInputText() + summary.note = note ~= "" and note or nil + summary.rating = (i == 1 and summary.rating == 1) and 0 or i + doc_settings_or_file = filemanagerutil.saveSummary(doc_settings_or_file, summary) + self.summary_updated = true + self.kvp_widget:onClose() + self:show(doc_settings_or_file, book_props) + end, + }) + end + end + input_dialog = InputDialog:new{ + title = _("Edit book review"), + input = summary.note, + text_height = Screen:scaleBySize(160), + allow_newline = true, + buttons = { + rating_buttons_row, + { + { + text = _("Cancel"), + id = "close", + callback = function() + UIManager:close(input_dialog) + end, + }, + { + text = _("Save review"), + callback = function() + UIManager:close(input_dialog) + local note = input_dialog:getInputText() + summary.note = note ~= "" and note or nil + doc_settings_or_file = filemanagerutil.saveSummary(doc_settings_or_file, summary) + self.summary_updated = true + self.kvp_widget:onClose() + self:show(doc_settings_or_file, book_props) + end, + }, + }, + }, + } + UIManager:show(input_dialog) + input_dialog:onShowKeyboard(true) +end + function BookInfo:moveBookMetadata() -- called by filemanagermenu only local file_chooser = self.ui.file_chooser diff --git a/frontend/apps/filemanager/filemanagercollection.lua b/frontend/apps/filemanager/filemanagercollection.lua index 6790a4302..a82ea969b 100644 --- a/frontend/apps/filemanager/filemanagercollection.lua +++ b/frontend/apps/filemanager/filemanagercollection.lua @@ -166,7 +166,7 @@ function FileManagerCollection:onMenuHold(item) }) table.insert(buttons, { filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback), - filemanagerutil.genBookInformationButton(file, self.book_props, close_dialog_callback), + filemanagerutil.genBookInformationButton(doc_settings_or_file, self.book_props, close_dialog_callback), }) table.insert(buttons, { filemanagerutil.genBookCoverButton(file, self.book_props, close_dialog_callback), diff --git a/frontend/apps/filemanager/filemanagerfilesearcher.lua b/frontend/apps/filemanager/filemanagerfilesearcher.lua index f94d0cbb4..626f7b8b0 100644 --- a/frontend/apps/filemanager/filemanagerfilesearcher.lua +++ b/frontend/apps/filemanager/filemanagerfilesearcher.lua @@ -290,13 +290,16 @@ function FileSearcher:showFileDialog(item) local buttons = {} if item.is_file then local is_currently_opened = self.ui.document and self.ui.document.file == file - if DocumentRegistry:hasProvider(file) or DocSettings:hasSidecarFile(file) then + local has_provider = DocumentRegistry:hasProvider(file) + local has_sidecar = DocSettings:hasSidecarFile(file) + local doc_settings_or_file = is_currently_opened and self.ui.doc_settings + or (has_sidecar and DocSettings:open(file) or file) + if has_provider or has_sidecar then bookinfo = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) - local doc_settings_or_file = is_currently_opened and self.ui.doc_settings or file table.insert(buttons, filemanagerutil.genStatusButtonsRow(doc_settings_or_file, close_dialog_callback)) table.insert(buttons, {}) -- separator table.insert(buttons, { - filemanagerutil.genResetSettingsButton(file, close_dialog_callback, is_currently_opened), + filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_callback, is_currently_opened), self.ui.collections:genAddToCollectionButton(file, close_dialog_callback, update_item_callback), }) end @@ -314,7 +317,7 @@ function FileSearcher:showFileDialog(item) FileManager:showDeleteFileDialog(file, post_delete_callback) end, }, - filemanagerutil.genBookInformationButton(file, bookinfo, close_dialog_callback), + filemanagerutil.genBookInformationButton(doc_settings_or_file, bookinfo, close_dialog_callback), }) end table.insert(buttons, { diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index abef55ea1..6875d64e5 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -219,7 +219,7 @@ function FileManagerHistory:onMenuHold(item) }) table.insert(buttons, { filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback, item.dim), - filemanagerutil.genBookInformationButton(file, self.book_props, close_dialog_callback, item.dim), + filemanagerutil.genBookInformationButton(doc_settings_or_file, self.book_props, close_dialog_callback, item.dim), }) table.insert(buttons, { filemanagerutil.genBookCoverButton(file, self.book_props, close_dialog_callback, item.dim), diff --git a/frontend/apps/filemanager/filemanagerutil.lua b/frontend/apps/filemanager/filemanagerutil.lua index 04fa0e1d6..3b912a4d1 100644 --- a/frontend/apps/filemanager/filemanagerutil.lua +++ b/frontend/apps/filemanager/filemanagerutil.lua @@ -114,19 +114,15 @@ function filemanagerutil.getStatus(file) return "new" end --- Set a document status ("reading", "complete", or "abandoned") -function filemanagerutil.setStatus(doc_settings_or_file, status) +function filemanagerutil.saveSummary(doc_settings_or_file, summary) -- In case the book doesn't have a sidecar file, this'll create it - local doc_settings - if type(doc_settings_or_file) == "table" then - doc_settings = doc_settings_or_file - else - doc_settings = DocSettings:open(doc_settings_or_file) + if type(doc_settings_or_file) ~= "table" then + doc_settings_or_file = DocSettings:open(doc_settings_or_file) end - local summary = doc_settings:readSetting("summary", {}) - summary.status = status summary.modified = os.date("%Y-%m-%d", os.time()) - doc_settings:flush() + doc_settings_or_file:saveSetting("summary", summary) + doc_settings_or_file:flush() + return doc_settings_or_file end function filemanagerutil.statusToString(status) @@ -158,7 +154,7 @@ function filemanagerutil.genStatusButtonsRow(doc_settings_or_file, caller_callba enabled = status ~= to_status, callback = function() summary.status = to_status - filemanagerutil.setStatus(doc_settings_or_file, to_status) + filemanagerutil.saveSummary(doc_settings_or_file, summary) UIManager:broadcastEvent(Event:new("DocSettingsItemsChanged", file, { summary = summary })) -- for CoverBrowser caller_callback() end, @@ -260,14 +256,14 @@ function filemanagerutil.genShowFolderButton(file, caller_callback, button_disab } end -function filemanagerutil.genBookInformationButton(file, book_props, caller_callback, button_disabled) +function filemanagerutil.genBookInformationButton(doc_settings_or_file, book_props, caller_callback, button_disabled) return { text = _("Book information"), enabled = not button_disabled, callback = function() caller_callback() local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") - FileManagerBookInfo:show(file, book_props and FileManagerBookInfo.extendProps(book_props)) + FileManagerBookInfo:show(doc_settings_or_file, book_props and FileManagerBookInfo.extendProps(book_props)) end, } end diff --git a/frontend/ui/widget/buttontable.lua b/frontend/ui/widget/buttontable.lua index 4b50795b3..bb467355c 100644 --- a/frontend/ui/widget/buttontable.lua +++ b/frontend/ui/widget/buttontable.lua @@ -115,7 +115,7 @@ function ButtonTable:init() end local button_dim = button:getSize() local vertical_sep = LineWidget:new{ - background = Blitbuffer.COLOR_GRAY, + background = btn_entry.no_vertical_sep and Blitbuffer.COLOR_WHITE or Blitbuffer.COLOR_GRAY, dimen = Geom:new{ w = self.sep_width, h = button_dim.h, diff --git a/frontend/ui/widget/menu.lua b/frontend/ui/widget/menu.lua index a5e92eb05..464c2978a 100644 --- a/frontend/ui/widget/menu.lua +++ b/frontend/ui/widget/menu.lua @@ -1476,7 +1476,7 @@ function Menu:onLeftButtonHold() -- to be overriden and implemented by the calle end function Menu:getFirstVisibleItemIndex() - return self.item_group[1].idx + return self.item_group[1] and self.item_group[1].idx or 1 end function Menu.getItemFontSize(perpage)