mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
Collections: filter by book status (#13099)
This commit is contained in:
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user