Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

History: search #11084

Merged
merged 7 commits into from Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions frontend/apps/filemanager/filemanagerbookinfo.lua
Expand Up @@ -15,6 +15,7 @@ local InputDialog = require("ui/widget/inputdialog")
local TextViewer = require("ui/widget/textviewer")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local Utf8Proc = require("ffi/utf8proc")
local filemanagerutil = require("apps/filemanager/filemanagerutil")
local lfs = require("libs/libkoreader-lfs")
local util = require("util")
Expand Down Expand Up @@ -266,6 +267,25 @@ function BookInfo.getDocProps(file, book_props, no_open_document)
return BookInfo.extendProps(book_props, file)
end

function BookInfo:findInProps(book_props, keywords, case_sensitive)
for _, key in ipairs(self.props) do
local prop = book_props[key]
if prop then
if key == "series_index" then
prop = tostring(prop)
elseif key == "description" then
prop = util.htmlToPlainTextIfHtml(prop)
end
if not case_sensitive then
prop = Utf8Proc.lowercase(util.fixUtf8(prop, "?"))
end
if prop:find(keywords) then
return true
end
end
end
end

-- Shows book information for currently opened document.
function BookInfo:onShowBookInfo()
if self.document then
Expand Down
21 changes: 3 additions & 18 deletions frontend/apps/filemanager/filemanagerfilesearcher.lua
Expand Up @@ -5,7 +5,6 @@ local ConfirmBox = require("ui/widget/confirmbox")
local DocSettings = require("docsettings")
local DocumentRegistry = require("document/documentregistry")
local FileChooser = require("ui/widget/filechooser")
local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo")
local InfoMessage = require("ui/widget/infomessage")
local InputDialog = require("ui/widget/inputdialog")
local Menu = require("ui/widget/menu")
Expand Down Expand Up @@ -192,24 +191,10 @@ function FileSearcher:isFileMatch(filename, fullpath, keywords, is_file)
end
if self.include_metadata and is_file and DocumentRegistry:hasProvider(fullpath) then
local book_props = self.ui.coverbrowser:getBookInfo(fullpath) or
FileManagerBookInfo.getDocProps(fullpath, nil, true) -- do not open the document
self.ui.bookinfo.getDocProps(fullpath, nil, true) -- do not open the document
if next(book_props) ~= nil then
for _, key in ipairs(FileManagerBookInfo.props) do
local prop = book_props[key]
if prop and prop ~= "" then
if key == "series_index" then
prop = tostring(prop)
end
if not self.case_sensitive then
prop = Utf8Proc.lowercase(util.fixUtf8(prop, "?"))
end
if key == "description" then
prop = util.htmlToPlainTextIfHtml(prop)
end
if string.find(prop, keywords) then
return true
end
end
if self.ui.bookinfo:findInProps(book_props, keywords, self.case_sensitive) then
return true
end
else
self.no_metadata_count = self.no_metadata_count + 1
Expand Down
133 changes: 119 additions & 14 deletions frontend/apps/filemanager/filemanagerhistory.lua
@@ -1,11 +1,15 @@
local BD = require("ui/bidi")
local ButtonDialog = require("ui/widget/buttondialog")
local CheckButton = require("ui/widget/checkbutton")
local ConfirmBox = require("ui/widget/confirmbox")
local InputDialog = require("ui/widget/inputdialog")
local Menu = require("ui/widget/menu")
local UIManager = require("ui/uimanager")
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local Screen = require("device").screen
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
Expand All @@ -15,12 +19,12 @@ local FileManagerHistory = WidgetContainer:extend{
}

local filter_text = {
all = C_("Book status filter", "All"),
reading = C_("Book status filter", "Reading"),
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"),
complete = C_("Book status filter", "Finished"),
deleted = C_("Book status filter", "Deleted"),
new = C_("Book status filter", "New"),
}

function FileManagerHistory:init()
Expand Down Expand Up @@ -64,7 +68,7 @@ function FileManagerHistory:updateItemTable()
reading = 0, abandoned = 0, complete = 0, deleted = 0, new = 0, }
local item_table = {}
for _, v in ipairs(require("readhistory").hist) do
if self.filter == "all" or v.status == self.filter then
if self:isItemMatch(v) then
if self.is_frozen and v.status == "complete" then
v.mandatory_dim = true
end
Expand All @@ -75,18 +79,50 @@ function FileManagerHistory:updateItemTable()
end
end
local title = self.hist_menu_title
if self.filter ~= "all" then
title = title .. " (" .. filter_text[self.filter] .. ": " .. self.count[self.filter] .. ")"
local filter_title
if self.filter_text then
filter_title = _("search results")
elseif self.filter ~= "all" then
filter_title = filter_text[self.filter]:lower()
end
if filter_title then
title = title .. T(" (%1: %2)", filter_title, #item_table)
end
self.hist_menu:switchItemTable(title, item_table, select_number)
end

function FileManagerHistory:isItemMatch(item)
if self.filter_text then
local filename = self.case_sensitive and item.text or Utf8Proc.lowercase(util.fixUtf8(item.text, "?"))
if not filename:find(self.filter_text) then
local book_props
if self.ui.coverbrowser then
book_props = self.ui.coverbrowser:getBookInfo(item.file)
end
if not book_props then
book_props = self.ui.bookinfo.getDocProps(item.file, nil, true) -- do not open the document
end
if not self.ui.bookinfo:findInProps(book_props, self.filter_text, self.case_sensitive) then
return false
end
end
end
return self.filter == "all" or item.status == self.filter
end

function FileManagerHistory:onSetDimensions(dimen)
self.dimen = dimen
end

function FileManagerHistory:onMenuChoice(item)
require("apps/reader/readerui"):showReader(item.file)
if self.ui.document then
if self.ui.document.file ~= item.file then
self.ui:switchDocument(item.file)
end
else
local ReaderUI = require("apps/reader/readerui")
ReaderUI:showReader(item.file)
end
end

function FileManagerHistory:onMenuHold(item)
Expand Down Expand Up @@ -153,7 +189,7 @@ function FileManagerHistory:onMenuHold(item)
})

self.histfile_dialog = ButtonDialog:new{
title = BD.filename(item.text:match("([^/]+)$")),
title = BD.filename(item.text),
title_align = "center",
buttons = buttons,
}
Expand All @@ -178,7 +214,7 @@ function FileManagerHistory:MenuSetRotationModeHandler(rotation)
return true
end

function FileManagerHistory:onShowHist()
function FileManagerHistory:onShowHist(match_table)
self.hist_menu = Menu:new{
ui = self.ui,
covers_fullscreen = true, -- hint for UIManager:_repaint()
Expand All @@ -192,6 +228,12 @@ function FileManagerHistory:onShowHist()
_manager = self,
}

if match_table then
self.filter_text = match_table.filter_text
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole thing was a bit hard to review because of the choice of these variable names.
You choose self.filter_text because we already have a self.filter (not fond of "filter" when reading it, but ok, might be just my French influence).
Or may be its just "text" that reads usually as something we will display, not that we will search. You use "keywords" elsewhere, may be filter_keywords would sound better and consistent (even if keywords sounds like its multiple keywords and not a single string).
You pass them in a match_table (again, no real need to put "table" in its name:)), that you could have named filter_table or filtering_info.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new search inherits from old

local keywords = self.search_value
if keywords ~= "*" then -- one * to show all files

and
local match_table = {
search_str = search_str,
bookmark = check_button_bookmark.checked,
highlight = check_button_highlight.checked,
note = check_button_note.checked,
case_sensitive = check_button_case.checked,
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can polish them all for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you feel (you're the code owner of all this :) and if it doesn't bug anybody else, fine with me.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't had a chance to read it yet. You could always name it filter_str(ing) if I understand the complaint correctly?

self.case_sensitive = match_table.case_sensitive
else
self.filter_text = nil
end
self.filter = G_reader_settings:readSetting("history_filter", "all")
self.is_frozen = G_reader_settings:isTrue("history_freeze_finished_books")
if self.filter ~= "all" or self.is_frozen then
Expand All @@ -200,14 +242,14 @@ function FileManagerHistory:onShowHist()
self:updateItemTable()
self.hist_menu.close_callback = function()
if self.files_updated then -- refresh Filemanager list of files
local FileManager = require("apps/filemanager/filemanager")
if FileManager.instance then
FileManager.instance:onRefresh()
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)
Expand All @@ -227,6 +269,9 @@ function FileManagerHistory:showHistDialog()
callback = function()
UIManager:close(hist_dialog)
self.filter = filter
if filter == "all" then -- reset all filters
self.filter_text = nil
end
self:updateItemTable()
end,
}
Expand All @@ -241,6 +286,15 @@ function FileManagerHistory:showHistDialog()
genFilterButton("abandoned"),
genFilterButton("complete"),
})
table.insert(buttons, {
{
text = _("Search in filename and book metadata"),
callback = function()
UIManager:close(hist_dialog)
self:onSearchHistory()
end,
},
})
if self.count.deleted > 0 then
table.insert(buttons, {}) -- separator
table.insert(buttons, {
Expand Down Expand Up @@ -269,6 +323,57 @@ function FileManagerHistory:showHistDialog()
UIManager:show(hist_dialog)
end

function FileManagerHistory:onSearchHistory()
local search_dialog, check_button_case
search_dialog = InputDialog:new{
title = _("Enter text to search history for"),
input = self.filter_text,
buttons = {
{
{
text = _("Cancel"),
id = "close",
callback = function()
UIManager:close(search_dialog)
end,
},
{
text = _("Search"),
is_enter_default = true,
callback = function()
local search_value = search_dialog:getInputText()
if search_value ~= "" then
UIManager:close(search_dialog)
self.filter_text = self.case_sensitive and search_value or search_value:lower()
if self.hist_menu then -- called from History
self:updateItemTable()
else -- called by Dispatcher
local match_table = {
filter_text = self.filter_text,
case_sensitive = self.case_sensitive,
}
self:onShowHist(match_table)
end
end
end,
},
},
},
}
check_button_case = CheckButton:new{
text = _("Case sensitive"),
checked = self.case_sensitive,
parent = search_dialog,
callback = function()
self.case_sensitive = check_button_case.checked
end,
}
search_dialog:addWidget(check_button_case)
UIManager:show(search_dialog)
search_dialog:onShowKeyboard()
return true
end

function FileManagerHistory:onBookMetadataChanged()
if self.hist_menu then
self.hist_menu:updateItems()
Expand Down
2 changes: 2 additions & 0 deletions frontend/dispatcher.lua
Expand Up @@ -52,6 +52,7 @@ local settingsList = {
reading_progress = {category="none", event="ShowReaderProgress", title=_("Reading progress"), general=true},
open_previous_document = {category="none", event="OpenLastDoc", title=_("Open previous document"), general=true},
history = {category="none", event="ShowHist", title=_("History"), general=true},
history_search = {category="none", event="SearchHistory", title=_("History search"), general=true},
favorites = {category="none", event="ShowColl", arg="favorites", title=_("Favorites"), general=true},
filemanager = {category="none", event="Home", title=_("File browser"), general=true, separator=true},
----
Expand Down Expand Up @@ -266,6 +267,7 @@ local dispatcher_menu_order = {
"reading_progress",
"open_previous_document",
"history",
"history_search",
"favorites",
"filemanager",
----
Expand Down