From 48d1b2346933d9262c8f3b816bfc428f71b595b7 Mon Sep 17 00:00:00 2001 From: zwim <36999612+zwim@users.noreply.github.com> Date: Sun, 18 Jul 2021 20:21:39 +0200 Subject: [PATCH] FileSearcher honor filemanagers sorting order (#7978) --- frontend/apps/filemanager/filemanager.lua | 4 +- .../filemanager/filemanagerfilesearcher.lua | 26 +++++-- frontend/apps/filemanager/filemanagermenu.lua | 2 + frontend/ui/data/onetime_migration.lua | 13 +++- frontend/ui/widget/filechooser.lua | 78 ++++++++++--------- 5 files changed, 76 insertions(+), 47 deletions(-) diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 6b74074f8..86b479804 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -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"), diff --git a/frontend/apps/filemanager/filemanagerfilesearcher.lua b/frontend/apps/filemanager/filemanagerfilesearcher.lua index 826877e9f..9e2c0e589 100644 --- a/frontend/apps/filemanager/filemanagerfilesearcher.lua +++ b/frontend/apps/filemanager/filemanagerfilesearcher.lua @@ -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 diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index 304db9780..7736b53d1 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -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")) diff --git a/frontend/ui/data/onetime_migration.lua b/frontend/ui/data/onetime_migration.lua index fe82959c2..89e8f65f3 100644 --- a/frontend/ui/data/onetime_migration.lua +++ b/frontend/ui/data/onetime_migration.lua @@ -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) diff --git a/frontend/ui/widget/filechooser.lua b/frontend/ui/widget/filechooser.lua index 72dc1482b..36d529b0d 100644 --- a/frontend/ui/widget/filechooser.lua +++ b/frontend/ui/widget/filechooser.lua @@ -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: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 +function FileChooser:show_dir(dirname) + for _, pattern in ipairs(self.exclude_dirs) do + if dirname:match(pattern) then return false end 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 + 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() 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)