Collections: filter by book status (#13099)

This commit is contained in:
hius07
2025-01-25 10:49:35 +02:00
committed by GitHub
parent d98639f341
commit 42de1fb96e
6 changed files with 111 additions and 81 deletions

View File

@@ -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"),

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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