diff --git a/frontend/apps/filemanager/filemanagercollection.lua b/frontend/apps/filemanager/filemanagercollection.lua index d065199c5..398e33766 100644 --- a/frontend/apps/filemanager/filemanagercollection.lua +++ b/frontend/apps/filemanager/filemanagercollection.lua @@ -105,10 +105,16 @@ function FileManagerCollection:updateItemTable(show_last_item, item_table) local collection_name = self:getCollectionTitle(self.coll_menu.collection_name) local title = T("%1 (%2)", collection_name, #item_table) local subtitle = "" - if self.match_table ~= nil then + if self.match_table then subtitle = {} - for prop, value in pairs(self.match_table.props) do - table.insert(subtitle, self.ui.bookinfo.prop_text[prop] .. " " .. value) + if self.match_table.status then + local status_string = BookList.getBookStatusString(self.match_table.status, true) + table.insert(subtitle, "\u{0000}" .. status_string) -- sorted first + end + if self.match_table.props then + for prop, value in pairs(self.match_table.props) do + table.insert(subtitle, T("%1 %2", self.ui.bookinfo.prop_text[prop], value)) + end end if #subtitle == 1 then subtitle = subtitle[1] @@ -122,13 +128,20 @@ function FileManagerCollection:updateItemTable(show_last_item, item_table) end function FileManagerCollection:isItemMatch(item) - if self.match_table ~= nil then - local doc_props = self.ui.bookinfo:getDocProps(item.file, nil, true) - for prop, value in pairs(self.match_table.props) do - if (doc_props[prop] or self.empty_prop) ~= value then + if self.match_table then + if self.match_table.status then + if self.match_table.status ~= BookList.getBookStatus(item.file) then return false end end + if self.match_table.props then + local doc_props = self.ui.bookinfo:getDocProps(item.file, nil, true) + for prop, value in pairs(self.match_table.props) do + if (doc_props[prop] or self.empty_prop) ~= value then + return false + end + end + end end return true end @@ -250,6 +263,17 @@ end function FileManagerCollection:showCollDialog() local coll_not_empty = #self.coll_menu.item_table > 0 local coll_dialog + local function genFilterByStatusButton(button_status) + return { + text = BookList.getBookStatusString(button_status), + enabled = coll_not_empty, + callback = function() + UIManager:close(coll_dialog) + util.tableSetValue(self, button_status, "match_table", "status") + self:updateItemTable() + end, + } + end local function genFilterByMetadataButton(button_text, button_prop) return { text = button_text, @@ -260,12 +284,18 @@ function FileManagerCollection:showCollDialog() for idx, item in ipairs(self.coll_menu.item_table) do local doc_prop = self.ui.bookinfo:getDocProps(item.file, nil, true)[button_prop] if doc_prop == nil then - doc_prop = self.empty_prop + doc_prop = { self.empty_prop } + elseif button_prop == "series" then + doc_prop = { doc_prop } elseif button_prop == "language" then - doc_prop = doc_prop:lower() + doc_prop = { doc_prop:lower() } + else -- "authors", "keywords" + doc_prop = util.splitToArray(doc_prop, "\n") + end + for _, prop in ipairs(doc_prop) do + prop_values[prop] = prop_values[prop] or {} + table.insert(prop_values[prop], idx) end - prop_values[doc_prop] = prop_values[doc_prop] or {} - table.insert(prop_values[doc_prop], idx) end self:showPropValueList(button_prop, prop_values) end, @@ -281,6 +311,14 @@ function FileManagerCollection:showCollDialog() end, }}, {}, -- separator + { + genFilterByStatusButton("new"), + genFilterByStatusButton("reading"), + }, + { + genFilterByStatusButton("abandoned"), + genFilterByStatusButton("complete"), + }, { genFilterByMetadataButton(_("Filter by authors"), "authors"), genFilterByMetadataButton(_("Filter by series"), "series"), diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index e49773504..c7a5e8bdb 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -11,22 +11,12 @@ local Utf8Proc = require("ffi/utf8proc") local filemanagerutil = require("apps/filemanager/filemanagerutil") local util = require("util") local _ = require("gettext") -local C_ = _.pgettext local T = require("ffi/util").template local FileManagerHistory = WidgetContainer:extend{ hist_menu_title = _("History"), } -local filter_text = { - all = C_("Book status filter", "All"), - reading = C_("Book status filter", "Reading"), - abandoned = C_("Book status filter", "On hold"), - complete = C_("Book status filter", "Finished"), - deleted = C_("Book status filter", "Deleted"), - new = C_("Book status filter", "New"), -} - function FileManagerHistory:init() self.ui.menu:registerToMainMenu(self) end @@ -48,10 +38,7 @@ function FileManagerHistory:fetchStatuses(count) elseif v.file == (self.ui.document and self.ui.document.file) then -- currently opened file status = self.ui.doc_settings:readSetting("summary").status else - status = filemanagerutil.getStatus(v.file) - end - if not filter_text[status] then - status = "reading" + status = BookList.getBookStatus(v.file) end if count then self.count[status] = self.count[status] + 1 @@ -80,15 +67,26 @@ function FileManagerHistory:updateItemTable() self.count[v.status] = self.count[v.status] + 1 end end + local title = T("%1 (%2)", self.hist_menu_title, #item_table) local subtitle = "" if self.search_string then - subtitle = T(_("Search results (%1)"), #item_table) + subtitle = T(_("Query: %1"), self.search_string) elseif self.selected_collections then - subtitle = T(_("Filtered by collections (%1)"), #item_table) + local collections = {} + for collection in pairs(self.selected_collections) do + table.insert(collections, self.ui.collections:getCollectionTitle(collection)) + end + if #collections == 1 then + collections = collections[1] + else + table.sort(collections) + collections = table.concat(collections, ", ") + end + subtitle = T(_("Collections: %1"), collections) elseif self.filter ~= "all" then - subtitle = T(_("Status: %1 (%2)"), filter_text[self.filter]:lower(), #item_table) + subtitle = BookList.getBookStatusString(self.filter, true) end - self.hist_menu:switchItemTable(nil, item_table, -1, nil, subtitle) + self.hist_menu:switchItemTable(title, item_table, -1, nil, subtitle) end function FileManagerHistory:isItemMatch(item) @@ -237,7 +235,6 @@ end function FileManagerHistory:onShowHist(search_info) self.hist_menu = BookList:new{ - title = self.hist_menu_title, title_bar_left_icon = "appbar.menu", onLeftButtonTap = function() self:showHistDialog() end, onMenuChoice = self.onMenuChoice, @@ -246,6 +243,18 @@ function FileManagerHistory:onShowHist(search_info) _manager = self, _recreate_func = function() self:onShowHist(search_info) end, } + self.hist_menu.close_callback = function() + if self.files_updated then -- refresh Filemanager list of files + if self.ui.file_chooser then + self.ui.file_chooser:refreshPath() + end + self.files_updated = nil + end + self.statuses_fetched = nil + UIManager:close(self.hist_menu) + self.hist_menu = nil + G_reader_settings:saveSetting("history_filter", self.filter) + end if search_info then self.search_string = search_info.search_string @@ -260,18 +269,6 @@ function FileManagerHistory:onShowHist(search_info) self:fetchStatuses(false) end self:updateItemTable() - self.hist_menu.close_callback = function() - if self.files_updated then -- refresh Filemanager list of files - if self.ui.file_chooser then - self.ui.file_chooser:refreshPath() - end - self.files_updated = nil - end - self.statuses_fetched = nil - UIManager:close(self.hist_menu) - self.hist_menu = nil - G_reader_settings:saveSetting("history_filter", self.filter) - end UIManager:show(self.hist_menu, "flashui") return true end @@ -285,7 +282,7 @@ function FileManagerHistory:showHistDialog() local buttons = {} local function genFilterButton(filter) return { - text = T(_("%1 (%2)"), filter_text[filter], self.count[filter]), + text = T(_("%1 (%2)"), BookList.getBookStatusString(filter), self.count[filter]), callback = function() UIManager:close(hist_dialog) self.filter = filter diff --git a/frontend/apps/filemanager/filemanagerutil.lua b/frontend/apps/filemanager/filemanagerutil.lua index 8533a3501..b9cfc67fb 100644 --- a/frontend/apps/filemanager/filemanagerutil.lua +++ b/frontend/apps/filemanager/filemanagerutil.lua @@ -52,22 +52,15 @@ function filemanagerutil.splitFileNameType(filepath) end function filemanagerutil.getRandomFile(dir, match_func) - if not dir:match("/$") then - dir = dir .. "/" - end local files = {} - local ok, iter, dir_obj = pcall(lfs.dir, dir) - if ok then - for entry in iter, dir_obj do - local file = dir .. entry - if lfs.attributes(file, "mode") == "file" and match_func(file) then - table.insert(files, entry) - end - end - if #files > 0 then - math.randomseed(os.time()) - return dir .. files[math.random(#files)] + util.findFiles(dir, function(file) + if match_func(file) then + table.insert(files, file) end + end, false) + if #files > 0 then + math.randomseed(os.time()) + return files[math.random(#files)] end end @@ -104,12 +97,6 @@ function filemanagerutil.resetDocumentSettings(file) end end --- Get a document status ("new", "reading", "complete", or "abandoned") -function filemanagerutil.getStatus(file) - local book_info = BookList.getBookInfo(file) - return book_info.been_opened and book_info.status or "new" -end - function filemanagerutil.saveSummary(doc_settings_or_file, summary) -- In case the book doesn't have a sidecar file, this'll create it if type(doc_settings_or_file) ~= "table" then @@ -121,17 +108,6 @@ function filemanagerutil.saveSummary(doc_settings_or_file, summary) return doc_settings_or_file end -function filemanagerutil.statusToString(status) - local status_to_text = { - new = _("Unread"), - reading = _("Reading"), - abandoned = _("On hold"), - complete = _("Finished"), - } - - return status_to_text[status] -end - -- Generate all book status file dialog buttons in a row function filemanagerutil.genStatusButtonsRow(doc_settings_or_file, caller_callback) local file, summary, status @@ -142,11 +118,11 @@ function filemanagerutil.genStatusButtonsRow(doc_settings_or_file, caller_callba else file = doc_settings_or_file summary = {} - status = filemanagerutil.getStatus(file) + status = BookList.getBookStatus(file) end local function genStatusButton(to_status) return { - text = filemanagerutil.statusToString(to_status) .. (status == to_status and " ✓" or ""), + text = BookList.getBookStatusString(to_status) .. (status == to_status and " ✓" or ""), enabled = status ~= to_status, callback = function() summary.status = to_status diff --git a/frontend/ui/widget/booklist.lua b/frontend/ui/widget/booklist.lua index 34b5ce51e..d8dc4a069 100644 --- a/frontend/ui/widget/booklist.lua +++ b/frontend/ui/widget/booklist.lua @@ -1,5 +1,8 @@ local DocSettings = require("docsettings") local Menu = require("ui/widget/menu") +local ffiUtil = require("ffi/util") +local _ = require("gettext") +local T = ffiUtil.template local BookList = Menu:extend{ covers_fullscreen = true, -- hint for UIManager:_repaint() @@ -91,4 +94,21 @@ function BookList.getDocSettings(file) return doc_settings end +function BookList.getBookStatus(file) + local book_info = BookList.getBookInfo(file) + return book_info.been_opened and book_info.status or "new" +end + +function BookList.getBookStatusString(status, with_prefix) + local status_string = ({ + new = _("New"), -- no sidecar file + reading = _("Reading"), -- doc_settings.summary.status + abandoned = _("On hold"), -- doc_settings.summary.status + complete = _("Finished"), -- doc_settings.summary.status + deleted = _("Deleted"), + all = _("All"), + })[status] + return with_prefix and T(_("Status: %1"), status_string:lower()) or status_string +end + return BookList diff --git a/frontend/ui/widget/filechooser.lua b/frontend/ui/widget/filechooser.lua index 904634b22..fb2036c37 100644 --- a/frontend/ui/widget/filechooser.lua +++ b/frontend/ui/widget/filechooser.lua @@ -264,7 +264,7 @@ function FileChooser:show_file(filename, fullpath) if filename:match(pattern) then return false end end if not self.show_unsupported and self.file_filter ~= nil and not self.file_filter(filename) then return false end - if not FileChooser.show_finished and fullpath ~= nil and filemanagerutil.getStatus(fullpath) == "complete" then return false end + if not FileChooser.show_finished and fullpath ~= nil and BookList.getBookStatus(fullpath) == "complete" then return false end return true end @@ -615,7 +615,7 @@ function FileChooser:getNextFile(curr_file) if is_curr_file_found then local next_file = item_table[i+1] if next_file and next_file.is_file and DocumentRegistry:hasProvider(next_file.path) - and filemanagerutil.getStatus(next_file.path) ~= "complete" then + and BookList.getBookStatus(next_file.path) ~= "complete" then return next_file.path end end diff --git a/plugins/calibre.koplugin/search.lua b/plugins/calibre.koplugin/search.lua index cb9d3719c..1331a97db 100644 --- a/plugins/calibre.koplugin/search.lua +++ b/plugins/calibre.koplugin/search.lua @@ -8,7 +8,6 @@ local ConfirmBox = require("ui/widget/confirmbox") local DataStorage = require("datastorage") local Device = require("device") local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") -local filemanagerutil = require("apps/filemanager/filemanagerutil") local InputDialog = require("ui/widget/inputdialog") local InfoMessage = require("ui/widget/infomessage") local Persist = require("persist") @@ -275,9 +274,9 @@ function CalibreSearch:onMenuHold(item) if not item.info or item.info:len() <= 0 then return end local thumbnail = FileManagerBookInfo:getCoverImage(nil, item.path) local thumbwidth = math.min(300, Screen:getWidth()/3) - local status = filemanagerutil.getStatus(item.path) + local status_string = BookList.getBookStatusString(BookList.getBookStatus(item.path), true) UIManager:show(InfoMessage:new{ - text = item.info .. "\nStatus: " .. filemanagerutil.statusToString(status), + text = item.info .. "\n" .. status_string, image = thumbnail, image_width = thumbwidth, image_height = thumbwidth/2*3