mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
FileSearcher honor filemanagers sorting order (#7978)
This commit is contained in:
@@ -1101,7 +1101,7 @@ function FileManager:getSortingMenuTable()
|
||||
local fm = self
|
||||
local collates = {
|
||||
strcoll = {_("filename"), _("Sort by filename")},
|
||||
numeric = {_("numeric"), _("Sort by filename (natural sorting)")},
|
||||
natural = {_("natural"), _("Sort by filename (natural sorting)")},
|
||||
strcoll_mixed = {_("name mixed"), _("Sort by name – mixed files and folders")},
|
||||
access = {_("date read"), _("Sort by last read date")},
|
||||
change = {_("date added"), _("Sort by date added")},
|
||||
@@ -1137,7 +1137,7 @@ function FileManager:getSortingMenuTable()
|
||||
end,
|
||||
sub_item_table = {
|
||||
set_collate_table("strcoll"),
|
||||
set_collate_table("numeric"),
|
||||
set_collate_table("natural"),
|
||||
set_collate_table("strcoll_mixed"),
|
||||
set_collate_table("access"),
|
||||
set_collate_table("change"),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
local CheckButton = require("ui/widget/checkbutton")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local DocumentRegistry = require("document/documentregistry")
|
||||
local FileChooser = require("ui/widget/filechooser")
|
||||
local Font = require("ui/font")
|
||||
local HorizontalGroup = require("ui/widget/horizontalgroup")
|
||||
local HorizontalSpan = require("ui/widget/horizontalspan")
|
||||
@@ -45,7 +46,10 @@ function FileSearcher:readDir()
|
||||
local fullpath = d.."/"..f
|
||||
local attributes = lfs.attributes(fullpath) or {}
|
||||
-- Don't traverse hidden folders if we're not showing them
|
||||
if attributes.mode == "directory" and f ~= "." and f ~= ".." and (G_reader_settings:isTrue("show_hidden") or not util.stringStartsWith(f, ".")) then
|
||||
if attributes.mode == "directory" and f ~= "." and f ~= ".."
|
||||
and (G_reader_settings:isTrue("show_hidden") or not util.stringStartsWith(f, "."))
|
||||
and FileChooser:show_dir(f)
|
||||
then
|
||||
table.insert(new_dirs, fullpath)
|
||||
table.insert(self.files, {
|
||||
name = f,
|
||||
@@ -56,7 +60,10 @@ function FileSearcher:readDir()
|
||||
end,
|
||||
})
|
||||
-- Always ignore macOS resource forks, too.
|
||||
elseif attributes.mode == "file" and not util.stringStartsWith(f, "._") and (show_unsupported or DocumentRegistry:hasProvider(fullpath)) then
|
||||
elseif attributes.mode == "file" and not util.stringStartsWith(f, "._")
|
||||
and (show_unsupported or DocumentRegistry:hasProvider(fullpath))
|
||||
and FileChooser:show_file(f)
|
||||
then
|
||||
table.insert(self.files, {
|
||||
name = f,
|
||||
text = f,
|
||||
@@ -79,7 +86,7 @@ function FileSearcher:setSearchResults()
|
||||
self.results = self.files
|
||||
else
|
||||
if not self.case_sensitive then
|
||||
keywords = Utf8Proc.lowercase(keywords)
|
||||
keywords = Utf8Proc.lowercase(util.fixUtf8(keywords, "?"))
|
||||
end
|
||||
-- replace '.' with '%.'
|
||||
keywords = keywords:gsub("%.","%%%.")
|
||||
@@ -89,11 +96,11 @@ function FileSearcher:setSearchResults()
|
||||
keywords = keywords:gsub("%?","%.")
|
||||
for __,f in pairs(self.files) do
|
||||
if self.case_sensitive then
|
||||
if string.find(f.name, keywords) and string.sub(f.name,-4) ~= ".sdr" then
|
||||
if string.find(f.name, keywords) then
|
||||
table.insert(self.results, f)
|
||||
end
|
||||
else
|
||||
if string.find(Utf8Proc.lowercase(f.name), keywords) and string.sub(f.name,-4) ~= ".sdr" then
|
||||
if string.find(Utf8Proc.lowercase(util.fixUtf8(f.name, "?")), keywords) then
|
||||
table.insert(self.results, f)
|
||||
end
|
||||
end
|
||||
@@ -128,7 +135,6 @@ function FileSearcher:onShowFileSearch()
|
||||
{
|
||||
{
|
||||
text = _("Cancel"),
|
||||
enabled = true,
|
||||
callback = function()
|
||||
self.search_dialog:onClose()
|
||||
UIManager:close(self.search_dialog)
|
||||
@@ -146,7 +152,6 @@ function FileSearcher:onShowFileSearch()
|
||||
},
|
||||
{
|
||||
text = _("Current folder"),
|
||||
enabled = true,
|
||||
is_enter_default = true,
|
||||
callback = function()
|
||||
self.search_value = self.search_dialog:getInputText()
|
||||
@@ -207,7 +212,12 @@ function FileSearcher:showSearchResults()
|
||||
self.search_menu.close_callback = function()
|
||||
UIManager:close(menu_container)
|
||||
end
|
||||
table.sort(self.results, function(v1,v2) return v1.text < v2.text end)
|
||||
|
||||
local collate = G_reader_settings:readSetting("collate") or "strcoll"
|
||||
local reverse_collate = G_reader_settings:isTrue("reverse_collate")
|
||||
local sorting = FileChooser:getSortingFunction(collate, reverse_collate)
|
||||
|
||||
table.sort(self.results, sorting)
|
||||
self.search_menu:switchItemTable(_("Search results"), self.results)
|
||||
UIManager:show(menu_container)
|
||||
end
|
||||
|
||||
@@ -665,6 +665,8 @@ To:
|
||||
Wildcards for one '?' or more '*' characters can be used.
|
||||
A search for '*' will show all files.
|
||||
|
||||
The sorting order is the same as in filemanager.
|
||||
|
||||
Tap a book in the search results to open it.]]),
|
||||
callback = function()
|
||||
self.ui:handleEvent(Event:new("ShowFileSearch"))
|
||||
|
||||
@@ -7,7 +7,7 @@ local lfs = require("libs/libkoreader-lfs")
|
||||
local logger = require("logger")
|
||||
|
||||
-- Date at which the last migration snippet was added
|
||||
local CURRENT_MIGRATION_DATE = 20210629
|
||||
local CURRENT_MIGRATION_DATE = 20210715
|
||||
|
||||
-- Retrieve the date of the previous migration, if any
|
||||
local last_migration_date = G_reader_settings:readSetting("last_migration_date", 0)
|
||||
@@ -275,5 +275,16 @@ if last_migration_date < 20210629 then
|
||||
end
|
||||
end
|
||||
|
||||
-- 20210715, Rename `numeric` to `natural`, https://github.com/koreader/koreader/pull/7978
|
||||
if last_migration_date < 20210715 then
|
||||
logger.info("Performing one-time migration for 20210715")
|
||||
if G_reader_settings:has("collate") then
|
||||
local collate = G_reader_settings:readSetting("collate")
|
||||
if collate == "numeric" then
|
||||
G_reader_settings:saveSetting("collate", "natural")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- We're done, store the current migration date
|
||||
G_reader_settings:saveSetting("last_migration_date", CURRENT_MIGRATION_DATE)
|
||||
|
||||
@@ -74,22 +74,22 @@ local FileChooser = Menu:extend{
|
||||
-- from readable /storage/emulated/0/ - so we know it contains "0/")
|
||||
local unreadable_dir_content = {}
|
||||
|
||||
function FileChooser:show_dir(dirname)
|
||||
for _, pattern in ipairs(self.exclude_dirs) do
|
||||
if dirname:match(pattern) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function FileChooser:show_file(filename)
|
||||
for _, pattern in ipairs(self.exclude_files) do
|
||||
if filename:match(pattern) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function FileChooser:init()
|
||||
self.width = Screen:getWidth()
|
||||
-- Standard dir exclusion list
|
||||
self.show_dir = function(dirname)
|
||||
for _, pattern in ipairs(self.exclude_dirs) do
|
||||
if dirname:match(pattern) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
-- Standard file exclusion list
|
||||
self.show_file = function(filename)
|
||||
for _, pattern in ipairs(self.exclude_files) do
|
||||
if filename:match(pattern) then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
self.list = function(path, dirs, files, count_only)
|
||||
-- lfs.dir directory without permission will give error
|
||||
local ok, iter, dir_obj = pcall(lfs.dir, path)
|
||||
@@ -99,8 +99,8 @@ function FileChooser:init()
|
||||
if count_only then
|
||||
if ((not self.show_hidden and not util.stringStartsWith(f, "."))
|
||||
or (self.show_hidden and f ~= "." and f ~= ".." and not util.stringStartsWith(f, "._")))
|
||||
and self.show_dir(f)
|
||||
and self.show_file(f)
|
||||
and self:show_dir(f)
|
||||
and self:show_file(f)
|
||||
then
|
||||
table.insert(dirs, true)
|
||||
end
|
||||
@@ -109,7 +109,7 @@ function FileChooser:init()
|
||||
local attributes = lfs.attributes(filename)
|
||||
if attributes ~= nil then
|
||||
if attributes.mode == "directory" and f ~= "." and f ~= ".." then
|
||||
if self.show_dir(f) then
|
||||
if self:show_dir(f) then
|
||||
table.insert(dirs, {name = f,
|
||||
suffix = getFileNameSuffix(f),
|
||||
fullpath = filename,
|
||||
@@ -117,7 +117,7 @@ function FileChooser:init()
|
||||
end
|
||||
-- Always ignore macOS resource forks.
|
||||
elseif attributes.mode == "file" and not util.stringStartsWith(f, "._") then
|
||||
if self.show_file(f) then
|
||||
if self:show_file(f) then
|
||||
if self.file_filter == nil or self.file_filter(filename) or self.show_unsupported then
|
||||
local percent_finished = 0
|
||||
if self.collate == "percent_unopened_first" or self.collate == "percent_unopened_last" then
|
||||
@@ -166,27 +166,21 @@ function FileChooser:init()
|
||||
Menu.init(self) -- call parent's init()
|
||||
end
|
||||
|
||||
function FileChooser:genItemTableFromPath(path)
|
||||
local dirs = {}
|
||||
local files = {}
|
||||
local up_folder_arrow = BD.mirroredUILayout() and BD.ltr("../ ⬆") or "⬆ ../"
|
||||
|
||||
self.list(path, dirs, files)
|
||||
|
||||
function FileChooser:getSortingFunction(collate, reverse_collate)
|
||||
local sorting
|
||||
if self.collate == "strcoll" then
|
||||
if collate == "strcoll" then
|
||||
sorting = function(a, b)
|
||||
return ffiUtil.strcoll(a.name, b.name)
|
||||
end
|
||||
elseif self.collate == "access" then
|
||||
elseif collate == "access" then
|
||||
sorting = function(a, b)
|
||||
return a.attr.access > b.attr.access
|
||||
end
|
||||
elseif self.collate == "modification" then
|
||||
elseif collate == "modification" then
|
||||
sorting = function(a, b)
|
||||
return a.attr.modification > b.attr.modification
|
||||
end
|
||||
elseif self.collate == "change" then
|
||||
elseif collate == "change" then
|
||||
sorting = function(a, b)
|
||||
if DocSettings:hasSidecarFile(a.fullpath) and not DocSettings:hasSidecarFile(b.fullpath) then
|
||||
return false
|
||||
@@ -196,11 +190,11 @@ function FileChooser:genItemTableFromPath(path)
|
||||
end
|
||||
return a.attr.change > b.attr.change
|
||||
end
|
||||
elseif self.collate == "size" then
|
||||
elseif collate == "size" then
|
||||
sorting = function(a, b)
|
||||
return a.attr.size < b.attr.size
|
||||
end
|
||||
elseif self.collate == "type" then
|
||||
elseif collate == "type" then
|
||||
sorting = function(a, b)
|
||||
if a.suffix == nil and b.suffix == nil then
|
||||
return ffiUtil.strcoll(a.name, b.name)
|
||||
@@ -208,17 +202,17 @@ function FileChooser:genItemTableFromPath(path)
|
||||
return ffiUtil.strcoll(a.suffix, b.suffix)
|
||||
end
|
||||
end
|
||||
elseif self.collate == "percent_unopened_first" or self.collate == "percent_unopened_last" then
|
||||
elseif collate == "percent_unopened_first" or collate == "percent_unopened_last" then
|
||||
sorting = function(a, b)
|
||||
if DocSettings:hasSidecarFile(a.fullpath) and not DocSettings:hasSidecarFile(b.fullpath) then
|
||||
if self.collate == "percent_unopened_first" then
|
||||
if collate == "percent_unopened_first" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
if not DocSettings:hasSidecarFile(a.fullpath) and DocSettings:hasSidecarFile(b.fullpath) then
|
||||
if self.collate == "percent_unopened_first" then
|
||||
if collate == "percent_unopened_first" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
@@ -233,7 +227,7 @@ function FileChooser:genItemTableFromPath(path)
|
||||
|
||||
return a.percent_finished < b.percent_finished
|
||||
end
|
||||
elseif self.collate == "numeric" then
|
||||
elseif collate == "natural" then
|
||||
-- adapted from: http://notebook.kulchenko.com/algorithms/alphanumeric-natural-sorting-for-humans-in-lua
|
||||
local function addLeadingZeroes(d)
|
||||
local dec, n = string.match(d, "(%.?)0*(.+)")
|
||||
@@ -249,11 +243,23 @@ function FileChooser:genItemTableFromPath(path)
|
||||
end
|
||||
end
|
||||
|
||||
if self.reverse_collate then
|
||||
if reverse_collate then
|
||||
local sorting_unreversed = sorting
|
||||
sorting = function(a, b) return sorting_unreversed(b, a) end
|
||||
end
|
||||
|
||||
return sorting
|
||||
end
|
||||
|
||||
function FileChooser:genItemTableFromPath(path)
|
||||
local dirs = {}
|
||||
local files = {}
|
||||
local up_folder_arrow = BD.mirroredUILayout() and BD.ltr("../ ⬆") or "⬆ ../"
|
||||
|
||||
self.list(path, dirs, files)
|
||||
|
||||
local sorting = self:getSortingFunction(self.collate, self.reverse_collate)
|
||||
|
||||
if self.collate ~= "strcoll_mixed" then
|
||||
table.sort(dirs, sorting)
|
||||
table.sort(files, sorting)
|
||||
|
||||
Reference in New Issue
Block a user