FileChooser: fix sorting and getNextFile() issues (#10176)

- Fix sorting folders when collate is "type", "size", "percentage":
  folders are sorted by name now.
- Fix getting next file in folder when collate is "mixed files and
  folders": returned nil when next item was a folder.
reviewable/pr10188/r1
hius07 1 year ago committed by GitHub
parent 5fce41d7d9
commit d2ed7402da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,21 +1,19 @@
local BD = require("ui/bidi")
local ConfirmBox = require("ui/widget/confirmbox")
local Device = require("device")
local DocSettings = require("docsettings")
local DocumentRegistry = require("document/documentregistry")
local OpenWithDialog = require("ui/widget/openwithdialog")
local ConfirmBox = require("ui/widget/confirmbox")
local Menu = require("ui/widget/menu")
local OpenWithDialog = require("ui/widget/openwithdialog")
local UIManager = require("ui/uimanager")
local ffi = require("ffi")
local lfs = require("libs/libkoreader-lfs")
local ffiUtil = require("ffi/util")
local T = ffiUtil.template
local _ = require("gettext")
local Screen = Device.screen
local lfs = require("libs/libkoreader-lfs")
local sort = require("sort")
local util = require("util")
local getFileNameSuffix = util.getFileNameSuffix
local getFriendlySize = util.getFriendlySize
local _ = require("gettext")
local Screen = Device.screen
local T = ffiUtil.template
local FileChooser = Menu:extend{
no_title = true,
@ -73,7 +71,7 @@ local FileChooser = Menu:extend{
"^%.fat32%-epoch$",
"^%.metadata%.json$",
},
collate = "strcoll", -- or collate = "access",
collate = "strcoll",
reverse_collate = false,
path_items = nil, -- hash, store last browsed location (item index) for each path
goto_letter = true,
@ -99,6 +97,7 @@ function FileChooser:show_file(filename)
end
function FileChooser:init()
self.up_folder_arrow = BD.mirroredUILayout() and BD.ltr("../ ⬆") or "⬆ ../"
self.path_items = {}
self.width = Screen:getWidth()
self.list = function(path, dirs, files, count_only)
@ -116,7 +115,6 @@ function FileChooser:init()
if self:show_dir(f) then
if not count_only then
item = {name = f,
suffix = getFileNameSuffix(f),
fullpath = filename,
attr = attributes,}
end
@ -134,9 +132,9 @@ function FileChooser:init()
end
end
item = {name = f,
suffix = getFileNameSuffix(f),
fullpath = filename,
attr = attributes,
suffix = util.getFileNameSuffix(f),
percent_finished = percent_finished or 0,}
end
table.insert(files, item)
@ -177,6 +175,25 @@ function FileChooser:getSortingFunction(collate, reverse_collate)
sorting = function(a, b)
return ffiUtil.strcoll(a.name, b.name)
end
elseif collate == "natural" then
local natsort
-- Only keep the cache if we're an *instance* of FileChooser
if self ~= FileChooser then
natsort, self.natsort_cache = sort.natsort_cmp(self.natsort_cache)
sorting = function(a, b)
return natsort(a.name, b.name)
end
else
natsort = sort.natsort_cmp()
sorting = function(a, b)
return natsort(a.name, b.name)
end
end
elseif self.collate == "strcoll_mixed" then
sorting = function(a, b)
if b.text == self.up_folder_arrow then return false end
return ffiUtil.strcoll(a.text, b.text)
end
elseif collate == "access" then
sorting = function(a, b)
return a.attr.access > b.attr.access
@ -205,7 +222,7 @@ function FileChooser:getSortingFunction(collate, reverse_collate)
end
return ffiUtil.strcoll(a.name, b.name)
end
elseif collate == "percent_unopened_first" or collate == "percent_unopened_last" then
else -- collate == "percent_unopened_first" or collate == "percent_unopened_last"
sorting = function(a, b)
local a_opened = DocSettings:hasSidecarFile(a.fullpath)
local b_opened = DocSettings:hasSidecarFile(b.fullpath)
@ -220,24 +237,6 @@ function FileChooser:getSortingFunction(collate, reverse_collate)
end
return a_opened
end
elseif collate == "natural" then
local natsort
-- Only keep the cache if we're an *instance* of FileChooser
if self ~= FileChooser then
natsort, self.natsort_cache = sort.natsort_cmp(self.natsort_cache)
sorting = function(a, b)
return natsort(a.name, b.name)
end
else
natsort = sort.natsort_cmp()
sorting = function(a, b)
return natsort(a.name, b.name)
end
end
else
sorting = function(a, b)
return a.name < b.name
end
end
if reverse_collate then
@ -251,28 +250,35 @@ 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)
if self.collate == "size" or
self.collate == "type" or
self.collate == "percent_unopened_first" or
self.collate == "percent_unopened_last" then
sorting = self:getSortingFunction("strcoll", self.reverse_collate)
end
table.sort(dirs, sorting)
end
if path ~= "/" and not (G_reader_settings:isTrue("lock_home_folder") and
path == G_reader_settings:readSetting("home_dir")) then
table.insert(dirs, 1, {name = ".."})
end
if self.show_current_dir_for_hold then table.insert(dirs, 1, {name = "."}) end
if self.show_current_dir_for_hold then
table.insert(dirs, 1, {name = "."})
end
local item_table = {}
for i, dir in ipairs(dirs) do
local subdir_path = self.path.."/"..dir.name
local text, bidi_wrap_func, istr
if dir.name == ".." then
text = up_folder_arrow
text = self.up_folder_arrow
elseif dir.name == "." then -- possible with show_current_dir_for_hold
text = _("Long-press to choose current folder")
elseif dir.name == "./." then -- added as content of an unreadable directory
@ -294,7 +300,7 @@ function FileChooser:genItemTableFromPath(path)
bidi_wrap_func = bidi_wrap_func,
mandatory = istr,
path = subdir_path,
is_go_up = dir.name == ".."
is_go_up = dir.name == "..",
})
end
@ -303,11 +309,9 @@ function FileChooser:genItemTableFromPath(path)
-- otherwise, show new files in bold
local show_file_in_bold = G_reader_settings:readSetting("show_file_in_bold")
for i = 1, #files do
local file = files[i]
for i, file in ipairs(files) do
local full_path = self.path.."/"..file.name
local file_size = lfs.attributes(full_path, "size") or 0
local sstr = getFriendlySize(file_size)
local sstr = util.getFriendlySize(file.attr.size or 0)
local file_item = {
text = file.name,
bidi_wrap_func = BD.filename,
@ -328,20 +332,12 @@ function FileChooser:genItemTableFromPath(path)
end
if self.collate == "strcoll_mixed" then
sorting = function(a, b)
if b.text == up_folder_arrow then return false end
return ffiUtil.strcoll(a.text, b.text)
end
if self.reverse_collate then
local sorting_unreversed = sorting
sorting = function(a, b) return sorting_unreversed(b, a) end
end
table.sort(item_table, sorting)
end
-- lfs.dir iterated node string may be encoded with some weird codepage on
-- Windows we need to encode them to utf-8
if ffi.os == "Windows" then
for k, v in pairs(item_table) do
for _, v in ipairs(item_table) do
if v.text then
v.text = ffiUtil.multiByteToUTF8(v.text) or ""
end
@ -428,7 +424,7 @@ end
function FileChooser:changePageToPath(path)
if not path then return end
for num, item in ipairs(self.item_table) do
if item.path == path then
if not item.is_file and item.path == path then
local page = math.floor((num-1) / self.perpage) + 1
if page ~= self.page then
self:onGotoPage(page)
@ -461,7 +457,7 @@ end
function FileChooser:onMenuSelect(item)
-- parent directory of dir without permission get nil mode
-- we need to change to parent path in this case
if lfs.attributes(item.path, "mode") == "file" then
if item.is_file then
self:onFileSelect(item.path)
else
self:changeToPath(item.path, item.is_go_up and self.path)
@ -487,27 +483,26 @@ function FileChooser:onPathChanged(path)
return true
end
-- Used in ReaderStatus:onOpenNextDocumentInFolder().
function FileChooser:getNextFile(curr_file)
local next_file
for index, data in pairs(self.item_table) do
if data.path == curr_file then
if index+1 <= #self.item_table then
next_file = self.item_table[index+1].path
if lfs.attributes(next_file, "mode") == "file" and DocumentRegistry:hasProvider(next_file) then
break
else
next_file = nil
end
local is_curr_file_found
for i, item in ipairs(self.item_table) do
if not is_curr_file_found and item.path == curr_file then
is_curr_file_found = true
end
if is_curr_file_found then
local next_file = self.item_table[i+1]
if next_file and next_file.is_file and DocumentRegistry:hasProvider(next_file.path) then
return next_file.path
end
end
end
return next_file
end
-- Used in file manager select mode to select all files in a folder,
-- that are visible in all file browser pages, without subfolders.
function FileChooser:selectAllFilesInFolder()
for _, item in pairs(self.item_table) do
for _, item in ipairs(self.item_table) do
if item.is_file then
self.filemanager.selected_files[item.path] = true
end

Loading…
Cancel
Save