DocSettings: Move book metadata to preferred location (#10149)

reviewable/pr10172/r1
hius07 1 year ago committed by GitHub
parent 189739ac4c
commit 38bd768d5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -15,6 +15,7 @@ local lfs = require("libs/libkoreader-lfs")
local logger = require("logger")
local util = require("util")
local _ = require("gettext")
local N_ = _.ngettext
local T = FFIUtil.template
local FileManagerMenu = InputContainer:extend{
@ -423,6 +424,15 @@ To:
self.menu_items[id] = common_setting
end
-- settings tab - Document submenu
self.menu_items.document_metadata_location_move = {
text = _("Move book metadata"),
keep_menu_open = true,
callback = function()
self:moveBookMetadata()
end,
}
-- tools tab
self.menu_items.advanced_settings = {
text = _("Advanced settings"),
@ -790,6 +800,74 @@ dbg:guard(FileManagerMenu, 'setUpdateItemTable',
end
end)
function FileManagerMenu:moveBookMetadata()
local DocSettings = require("docsettings")
local FileChooser = self.ui.file_chooser
local function scanPath()
local sys_folders = { -- do not scan sys_folders
["/dev"] = true,
["/proc"] = true,
["/sys"] = true,
}
local books_to_move = {}
local dirs = {FileChooser.path}
while #dirs ~= 0 do
local new_dirs = {}
for _, d in ipairs(dirs) do
local ok, iter, dir_obj = pcall(lfs.dir, d)
if ok then
for f in iter, dir_obj do
local fullpath = "/" .. f
if d ~= "/" then
fullpath = d .. fullpath
end
local attributes = lfs.attributes(fullpath) or {}
if attributes.mode == "directory" and f ~= "." and f ~= ".."
and FileChooser:show_dir(f) and not sys_folders[fullpath] then
table.insert(new_dirs, fullpath)
elseif attributes.mode == "file" and not util.stringStartsWith(f, "._")
and FileChooser:show_file(f) and DocSettings:hasSidecarFile(fullpath)
and lfs.attributes(DocSettings:getSidecarFile(fullpath), "mode") ~= "file" then
table.insert(books_to_move, fullpath)
end
end
end
end
dirs = new_dirs
end
return books_to_move
end
UIManager:show(ConfirmBox:new{
text = _("Scan books in current folder and subfolders for their metadata location?"),
ok_text = _("Scan"),
ok_callback = function()
local books_to_move = scanPath()
local books_to_move_nb = #books_to_move
if books_to_move_nb == 0 then
local InfoMessage = require("ui/widget/infomessage")
UIManager:show(InfoMessage:new{
text = _("No books with metadata not in your preferred location found."),
})
else
UIManager:show(ConfirmBox:new{
text = T(N_("1 book with metadata not in your preferred location found.",
"%1 books with metadata not in your preferred location found.",
books_to_move_nb), books_to_move_nb) ..
_("\nMove book metadata to your preferred location?"),
ok_text = _("Move"),
ok_callback = function()
UIManager:close(self.menu_container)
for _, book in ipairs(books_to_move) do
DocSettings:update(book, book)
end
FileChooser:refreshPath()
end,
})
end
end,
})
end
function FileManagerMenu:exitOrRestart(callback, force)
UIManager:close(self.menu_container)

@ -98,11 +98,6 @@ function DocSettings:hasSidecarFile(doc_path)
or lfs.attributes(self:getHistoryPath(doc_path), "mode") == "file"
end
function DocSettings:getLastSaveTime(doc_path) -- for readhistory
return lfs.attributes(self:getSidecarFile(doc_path, "doc"), "modification")
or lfs.attributes(self:getSidecarFile(doc_path, "dir"), "modification")
end
function DocSettings:getHistoryPath(doc_path)
if doc_path == nil or doc_path == "" then return "" end
return HISTORY_DIR .. "/[" .. doc_path:gsub("(.*/)([^/]+)", "%1] %2"):gsub("/", "#") .. ".lua"
@ -204,6 +199,7 @@ function DocSettings:open(doc_path)
else
new.data = {}
end
new.data.doc_path = doc_path
return new
end
@ -248,7 +244,7 @@ function DocSettings:flush(data)
ffiutil.fsyncDirectory(sidecar_file)
end
self:purge(false, sidecar_file) -- remove old candidates and empty sidecar folders
self:purge(sidecar_file) -- remove old candidates and empty sidecar folders
break
end
@ -256,7 +252,7 @@ function DocSettings:flush(data)
end
--- Purges (removes) sidecar directory.
function DocSettings:purge(full, sidecar_to_keep)
function DocSettings:purge(sidecar_to_keep)
-- Remove any of the old ones we may consider as candidates in DocSettings:open()
if self.candidates then
for _, t in ipairs(self.candidates) do
@ -271,20 +267,12 @@ function DocSettings:purge(full, sidecar_to_keep)
end
end
local function purgeDir(dir, full_purge)
if lfs.attributes(dir, "mode") == "directory" then
if full_purge then
-- Asked to remove all the content of this .sdr directory, whether it's ours or not
ffiutil.purgeDir(dir)
else
-- If the sidecar folder ends up empty, os.remove() can delete it.
-- Otherwise, the following statement has no effect.
os.remove(dir)
end
end
if lfs.attributes(self.doc_sidecar_dir, "mode") == "directory" then
os.remove(self.doc_sidecar_dir) -- keep parent folders
end
if lfs.attributes(self.dir_sidecar_dir, "mode") == "directory" then
util.removePath(self.dir_sidecar_dir) -- remove empty parent folders
end
purgeDir(self.doc_sidecar_dir, full)
purgeDir(self.dir_sidecar_dir, full)
end
--- Updates sidecar info for file rename/copy/move/delete operations.

@ -528,9 +528,16 @@ common_settings.document = {
local metadata_folder_str = {
["doc"] = _("book folder"),
["dir"] = "koreader/docsettings",
["dir"] = "koreader/docsettings/",
}
local metadata_folder_help_text = _([[
Book view settings, reading progress, highlights, bookmarks and notes (collectively known as metadata) are stored in a separate folder named <book-filename>.sdr (".sdr" meaning "sidecar").
You can decide between two locations where these will be saved:
- alongside the book file itself (the long time default): these sdr folders will be visible when you browse your library directories with another file browser or from your computer, which may clutter your vision of your library. But this allows you to move them along when you reorganize your library, and also survives any renaming of parent directories. Also, if you perform directory synchronization or backups, your settings will be part of them.
- all inside koreader/docsettings/: these sdr folders will only be visible and used by KOReader, and won't clutter your vision of your library directories with another file browser or from your computer. But any reorganisation of your library (directories or filename moves and renamings) may result in KOReader not finding your previous settings for these books. These settings won't be part of any synchronization or backups of your library.]])
local function genMetadataFolderMenuItem(value)
return {
text = metadata_folder_str[value],
@ -543,12 +550,21 @@ local function genMetadataFolderMenuItem(value)
}
end
common_settings.document_metadata_folder = {
common_settings.document_metadata_location = {
text_func = function()
local value = G_reader_settings:readSetting("document_metadata_folder", "doc")
return T(_("Book metadata folder: %1"), metadata_folder_str[value])
return T(_("Book metadata location: %1"), metadata_folder_str[value])
end,
help_text = metadata_folder_help_text,
sub_item_table = {
{
text = _("About book metadata location"),
keep_menu_open = true,
callback = function()
UIManager:show(InfoMessage:new{ text = metadata_folder_help_text, })
end,
separator = true,
},
genMetadataFolderMenuItem("doc"),
genMetadataFolderMenuItem("dir"),
},

@ -36,7 +36,8 @@ local order = {
-- end common settings
},
document = {
"document_metadata_folder",
"document_metadata_location",
"document_metadata_location_move",
"document_auto_save",
"document_save",
"document_end_action",

@ -79,7 +79,7 @@ local order = {
"status_bar",
},
document = {
"document_metadata_folder",
"document_metadata_location",
"document_auto_save",
"document_save",
"document_end_action",

@ -101,7 +101,7 @@ end
function DocSettingTweak:onDocSettingsLoad(doc_settings, document)
-- check that the documents settings are empty & and that we have defaults to customize
if next(doc_settings.data) == nil and directory_defaults.data ~= nil then
if util.tableSize(doc_settings.data) == 1 and directory_defaults.data ~= nil then
local base = G_reader_settings:readSetting("home_dir") or filemanagerutil.getDefaultDir()
if document.file == nil or document.file == "" then
return
@ -111,6 +111,7 @@ function DocSettingTweak:onDocSettingsLoad(doc_settings, document)
while directory:sub(1, #base) == base do
if directory_defaults:has(directory) then
doc_settings.data = util.tableDeepCopy(directory_defaults:readSetting(directory))
doc_settings.data.doc_path = document.file
break
else
if directory == "/" or directory == "." then

@ -19,9 +19,9 @@ describe("Readerui module", function()
-- remove history settings and sidecar settings
DocSettings:open(sample_epub):purge()
local doc_settings = DocSettings:open(sample_epub)
assert.are.same(doc_settings.data, {})
assert.are.same(doc_settings.data, {doc_path = sample_epub})
readerui:saveSettings()
assert.are_not.same(readerui.doc_settings.data, {})
assert.are_not.same(readerui.doc_settings.data, {doc_path = sample_epub})
doc_settings = DocSettings:open(sample_epub)
assert.truthy(doc_settings.data.last_xpointer)
assert.are.same(doc_settings.data.last_xpointer,

Loading…
Cancel
Save