From b8090c641c64471c514fba4aaac2cff066118cd1 Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Wed, 7 Feb 2024 10:35:52 +0200 Subject: [PATCH] Minimize DocSettings:open() calls (#11437) --- frontend/apps/filemanager/filemanager.lua | 38 ++++++++----- .../filemanager/filemanagercollection.lua | 32 ++++++++--- .../apps/filemanager/filemanagerhistory.lua | 47 ++++++++++------ frontend/apps/filemanager/filemanagerutil.lua | 46 ++++++++++------ frontend/apps/reader/readerui.lua | 15 +++--- frontend/document/documentregistry.lua | 7 +-- frontend/readhistory.lua | 53 +++++++++---------- plugins/coverbrowser.koplugin/covermenu.lua | 6 +-- 8 files changed, 149 insertions(+), 95 deletions(-) diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index 246827635..2646ea1f2 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -269,14 +269,26 @@ function FileManager:setupLayout() } if is_file then - self.bookinfo = nil + self.book_props = nil -- in 'self' to provide access to it in CoverBrowser local has_provider = DocumentRegistry:hasProvider(file) - if has_provider or DocSettings:hasSidecarFile(file) then - self.bookinfo = file_manager.coverbrowser and file_manager.coverbrowser:getBookInfo(file) - table.insert(buttons, filemanagerutil.genStatusButtonsRow(file, close_dialog_refresh_callback)) + local has_sidecar = DocSettings:hasSidecarFile(file) + if has_provider or has_sidecar then + self.book_props = file_manager.coverbrowser and file_manager.coverbrowser:getBookInfo(file) + local doc_settings_or_file + if has_sidecar then + doc_settings_or_file = DocSettings:open(file) + if not self.book_props then + local props = doc_settings_or_file:readSetting("doc_props") + self.book_props = FileManagerBookInfo.extendProps(props, file) + self.book_props.has_cover = true -- to enable "Book cover" button, we do not know if cover exists + end + else + doc_settings_or_file = file + end + table.insert(buttons, filemanagerutil.genStatusButtonsRow(doc_settings_or_file, close_dialog_refresh_callback)) table.insert(buttons, {}) -- separator table.insert(buttons, { - filemanagerutil.genResetSettingsButton(file, close_dialog_refresh_callback), + filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_refresh_callback), filemanagerutil.genAddRemoveFavoritesButton(file, close_dialog_callback), }) end @@ -288,12 +300,12 @@ function FileManager:setupLayout() file_manager:showOpenWithDialog(file) end, }, - filemanagerutil.genBookInformationButton(file, self.bookinfo, close_dialog_callback), + filemanagerutil.genBookInformationButton(file, self.book_props, close_dialog_callback), }) if has_provider then table.insert(buttons, { - filemanagerutil.genBookCoverButton(file, self.bookinfo, close_dialog_callback), - filemanagerutil.genBookDescriptionButton(file, self.bookinfo, close_dialog_callback), + filemanagerutil.genBookCoverButton(file, self.book_props, close_dialog_callback), + filemanagerutil.genBookDescriptionButton(file, self.book_props, close_dialog_callback), }) end if Device:canExecuteScript(file) then @@ -1414,13 +1426,14 @@ function FileManager:showOpenWithDialog(file) end end local t = {} - for extension, provider_key in BaseUtil.orderedPairs(associated_providers) do + for extension, provider_key in pairs(associated_providers) do local provider = DocumentRegistry:getProviderFromKey(provider_key) if provider then local space = string.rep(" ", max_len - #extension) table.insert(t, T("%1%2: %3", extension, space, provider.provider_name)) end end + table.sort(t) UIManager:show(InfoMessage:new{ text = table.concat(t, "\n"), monospace_font = true, @@ -1479,11 +1492,10 @@ function FileManager:showOpenWithDialog(file) end function FileManager:openFile(file, provider, doc_caller_callback, aux_caller_callback) - if not provider then -- check associated - local provider_key = DocumentRegistry:getAssociatedProviderKey(file) - provider = provider_key and DocumentRegistry:getProviderFromKey(provider_key) + if provider == nil then + provider = DocumentRegistry:getProvider(file, true) -- include auxiliary end - if provider and provider.order then -- auxiliary + if provider.order then -- auxiliary if aux_caller_callback then aux_caller_callback() end diff --git a/frontend/apps/filemanager/filemanagercollection.lua b/frontend/apps/filemanager/filemanagercollection.lua index 8b4422f90..4775916ff 100644 --- a/frontend/apps/filemanager/filemanagercollection.lua +++ b/frontend/apps/filemanager/filemanagercollection.lua @@ -1,7 +1,9 @@ local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local Device = require("device") +local DocSettings = require("docsettings") local DocumentRegistry = require("document/documentregistry") +local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local Menu = require("ui/widget/menu") local ReadCollection = require("readcollection") local UIManager = require("ui/uimanager") @@ -49,7 +51,7 @@ end function FileManagerCollection:onMenuHold(item) local file = item.file self.collfile_dialog = nil - self.bookinfo = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) + self.book_props = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) local function close_dialog_callback() UIManager:close(self.collfile_dialog) @@ -66,11 +68,29 @@ function FileManagerCollection:onMenuHold(item) local is_currently_opened = file == (self.ui.document and self.ui.document.file) local buttons = {} - local doc_settings_or_file = is_currently_opened and self.ui.doc_settings or file + local doc_settings_or_file + if is_currently_opened then + doc_settings_or_file = self.ui.doc_settings + if not self.book_props then + self.book_props = self.ui.doc_props + self.book_props.has_cover = true + end + else + if DocSettings:hasSidecarFile(file) then + doc_settings_or_file = DocSettings:open(file) + if not self.book_props then + local props = doc_settings_or_file:readSetting("doc_props") + self.book_props = FileManagerBookInfo.extendProps(props, file) + self.book_props.has_cover = true + end + else + doc_settings_or_file = file + end + end table.insert(buttons, filemanagerutil.genStatusButtonsRow(doc_settings_or_file, close_dialog_update_callback)) table.insert(buttons, {}) -- separator table.insert(buttons, { - filemanagerutil.genResetSettingsButton(file, close_dialog_update_callback, is_currently_opened), + filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_update_callback, is_currently_opened), { text = _("Remove from favorites"), callback = function() @@ -82,11 +102,11 @@ function FileManagerCollection:onMenuHold(item) }) table.insert(buttons, { filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback), - filemanagerutil.genBookInformationButton(file, self.bookinfo, close_dialog_callback), + filemanagerutil.genBookInformationButton(file, self.book_props, close_dialog_callback), }) table.insert(buttons, { - filemanagerutil.genBookCoverButton(file, self.bookinfo, close_dialog_callback), - filemanagerutil.genBookDescriptionButton(file, self.bookinfo, close_dialog_callback), + filemanagerutil.genBookCoverButton(file, self.book_props, close_dialog_callback), + filemanagerutil.genBookDescriptionButton(file, self.book_props, close_dialog_callback), }) if Device:canExecuteScript(file) then diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index 6e1784526..8b4f5cfac 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -2,6 +2,8 @@ local BD = require("ui/bidi") local ButtonDialog = require("ui/widget/buttondialog") local CheckButton = require("ui/widget/checkbutton") local ConfirmBox = require("ui/widget/confirmbox") +local DocSettings = require("docsettings") +local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") local InputDialog = require("ui/widget/inputdialog") local Menu = require("ui/widget/menu") local UIManager = require("ui/uimanager") @@ -62,32 +64,25 @@ function FileManagerHistory:fetchStatuses(count) end function FileManagerHistory:updateItemTable() - -- try to stay on current page - local select_number = nil - if self.hist_menu.page and self.hist_menu.perpage and self.hist_menu.page > 0 then - select_number = (self.hist_menu.page - 1) * self.hist_menu.perpage + 1 - end self.count = { all = #require("readhistory").hist, reading = 0, abandoned = 0, complete = 0, deleted = 0, new = 0, } local item_table = {} for _, v in ipairs(require("readhistory").hist) do if self:isItemMatch(v) then - if self.is_frozen and v.status == "complete" then - v.mandatory_dim = true - end + v.mandatory_dim = (self.is_frozen and v.status == "complete") and true or nil table.insert(item_table, v) end if self.statuses_fetched then self.count[v.status] = self.count[v.status] + 1 end end - local subtitle + local subtitle = "" if self.search_string then subtitle = T(_("Search results (%1)"), #item_table) elseif self.filter ~= "all" then subtitle = T(_("Status: %1 (%2)"), filter_text[self.filter]:lower(), #item_table) end - self.hist_menu:switchItemTable(nil, item_table, select_number, nil, subtitle or "") + self.hist_menu:switchItemTable(nil, item_table, -1, nil, subtitle) end function FileManagerHistory:isItemMatch(item) @@ -126,7 +121,7 @@ end function FileManagerHistory:onMenuHold(item) local file = item.file self.histfile_dialog = nil - self.bookinfo = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) + self.book_props = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) local function close_dialog_callback() UIManager:close(self.histfile_dialog) @@ -137,7 +132,7 @@ function FileManagerHistory:onMenuHold(item) end local function close_dialog_update_callback() UIManager:close(self.histfile_dialog) - if self._manager.filter ~= "all" then + if self._manager.filter ~= "all" or self._manager.is_frozen then self._manager:fetchStatuses(false) else self._manager.statuses_fetched = false @@ -148,13 +143,31 @@ function FileManagerHistory:onMenuHold(item) local is_currently_opened = file == (self.ui.document and self.ui.document.file) local buttons = {} + local doc_settings_or_file + if is_currently_opened then + doc_settings_or_file = self.ui.doc_settings + if not self.book_props then + self.book_props = self.ui.doc_props + self.book_props.has_cover = true + end + else + if DocSettings:hasSidecarFile(file) then + doc_settings_or_file = DocSettings:open(file) + if not self.book_props then + local props = doc_settings_or_file:readSetting("doc_props") + self.book_props = FileManagerBookInfo.extendProps(props, file) + self.book_props.has_cover = true + end + else + doc_settings_or_file = file + end + end if not item.dim then - local doc_settings_or_file = is_currently_opened and self.ui.doc_settings or file table.insert(buttons, filemanagerutil.genStatusButtonsRow(doc_settings_or_file, close_dialog_update_callback)) table.insert(buttons, {}) -- separator end table.insert(buttons, { - filemanagerutil.genResetSettingsButton(file, close_dialog_update_callback, is_currently_opened), + filemanagerutil.genResetSettingsButton(doc_settings_or_file, close_dialog_update_callback, is_currently_opened), filemanagerutil.genAddRemoveFavoritesButton(file, close_dialog_callback, item.dim), }) table.insert(buttons, { @@ -182,11 +195,11 @@ function FileManagerHistory:onMenuHold(item) }) table.insert(buttons, { filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback, item.dim), - filemanagerutil.genBookInformationButton(file, self.bookinfo, close_dialog_callback, item.dim), + filemanagerutil.genBookInformationButton(file, self.book_props, close_dialog_callback, item.dim), }) table.insert(buttons, { - filemanagerutil.genBookCoverButton(file, self.bookinfo, close_dialog_callback, item.dim), - filemanagerutil.genBookDescriptionButton(file, self.bookinfo, close_dialog_callback, item.dim), + filemanagerutil.genBookCoverButton(file, self.book_props, close_dialog_callback, item.dim), + filemanagerutil.genBookDescriptionButton(file, self.book_props, close_dialog_callback, item.dim), }) self.histfile_dialog = ButtonDialog:new{ diff --git a/frontend/apps/filemanager/filemanagerutil.lua b/frontend/apps/filemanager/filemanagerutil.lua index 2ed6be3f4..713c381a2 100644 --- a/frontend/apps/filemanager/filemanagerutil.lua +++ b/frontend/apps/filemanager/filemanagerutil.lua @@ -108,9 +108,14 @@ function filemanagerutil.getStatus(file) end -- Set a document status ("reading", "complete", or "abandoned") -function filemanagerutil.setStatus(file, status) +function filemanagerutil.setStatus(doc_settings_or_file, status) -- In case the book doesn't have a sidecar file, this'll create it - local doc_settings = DocSettings:open(file) + local doc_settings + if type(doc_settings_or_file) == "table" then + doc_settings = doc_settings_or_file + else + doc_settings = DocSettings:open(doc_settings_or_file) + end local summary = doc_settings:readSetting("summary", {}) summary.status = status summary.modified = os.date("%Y-%m-%d", os.time()) @@ -131,9 +136,9 @@ end -- Generate all book status file dialog buttons in a row function filemanagerutil.genStatusButtonsRow(doc_settings_or_file, caller_callback) local file, summary, status - if type(doc_settings_or_file) == "table" then -- currently opened file + if type(doc_settings_or_file) == "table" then file = doc_settings_or_file:readSetting("doc_path") - summary = doc_settings_or_file:readSetting("summary") + summary = doc_settings_or_file:readSetting("summary", {}) status = summary.status else file = doc_settings_or_file @@ -146,7 +151,7 @@ function filemanagerutil.genStatusButtonsRow(doc_settings_or_file, caller_callba enabled = status ~= to_status, callback = function() summary.status = to_status - filemanagerutil.setStatus(file, to_status) + filemanagerutil.setStatus(doc_settings_or_file, to_status) UIManager:broadcastEvent(Event:new("DocSettingsItemsChanged", file, { summary = summary })) -- for CoverBrowser caller_callback() end, @@ -160,9 +165,16 @@ function filemanagerutil.genStatusButtonsRow(doc_settings_or_file, caller_callba end -- Generate "Reset" file dialog button -function filemanagerutil.genResetSettingsButton(file, caller_callback, button_disabled) - file = ffiutil.realpath(file) or file - local has_sidecar_file = DocSettings:hasSidecarFile(file) +function filemanagerutil.genResetSettingsButton(doc_settings_or_file, caller_callback, button_disabled) + local doc_settings, file, has_sidecar_file + if type(doc_settings_or_file) == "table" then + doc_settings = doc_settings_or_file + file = doc_settings_or_file:readSetting("doc_path") + has_sidecar_file = true + else + file = ffiutil.realpath(doc_settings_or_file) or doc_settings_or_file + has_sidecar_file = DocSettings:hasSidecarFile(file) + end local custom_cover_file = DocSettings:findCustomCoverFile(file) local has_custom_cover_file = custom_cover_file and true or false local custom_metadata_file = DocSettings:findCustomMetadataFile(file) @@ -185,7 +197,7 @@ function filemanagerutil.genResetSettingsButton(file, caller_callback, button_di custom_cover_file = check_button_cover.checked and custom_cover_file, custom_metadata_file = check_button_metadata.checked and custom_metadata_file, } - DocSettings:open(file):purge(nil, data_to_purge) + (doc_settings or DocSettings:open(file)):purge(nil, data_to_purge) if data_to_purge.custom_cover_file or data_to_purge.custom_metadata_file then UIManager:broadcastEvent(Event:new("InvalidateMetadataCache", file)) end @@ -260,23 +272,23 @@ function filemanagerutil.genShowFolderButton(file, caller_callback, button_disab } end -function filemanagerutil.genBookInformationButton(file, bookinfo, caller_callback, button_disabled) +function filemanagerutil.genBookInformationButton(file, book_props, caller_callback, button_disabled) return { text = _("Book information"), enabled = not button_disabled, callback = function() caller_callback() local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") - FileManagerBookInfo:show(file, bookinfo and FileManagerBookInfo.extendProps(bookinfo)) + FileManagerBookInfo:show(file, book_props and FileManagerBookInfo.extendProps(book_props)) end, } end -function filemanagerutil.genBookCoverButton(file, bookinfo, caller_callback, button_disabled) - local has_cover = bookinfo and bookinfo.has_cover +function filemanagerutil.genBookCoverButton(file, book_props, caller_callback, button_disabled) + local has_cover = book_props and book_props.has_cover return { text = _("Book cover"), - enabled = (not button_disabled and (not bookinfo or has_cover)) and true or false, + enabled = (not button_disabled and (not book_props or has_cover)) and true or false, callback = function() caller_callback() local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") @@ -285,12 +297,12 @@ function filemanagerutil.genBookCoverButton(file, bookinfo, caller_callback, but } end -function filemanagerutil.genBookDescriptionButton(file, bookinfo, caller_callback, button_disabled) - local description = bookinfo and bookinfo.description +function filemanagerutil.genBookDescriptionButton(file, book_props, caller_callback, button_disabled) + local description = book_props and book_props.description return { text = _("Book description"), -- enabled for deleted books if description is kept in CoverBrowser bookinfo cache - enabled = (not (button_disabled or bookinfo) or description) and true or false, + enabled = (not (button_disabled or book_props) or description) and true or false, callback = function() caller_callback() local FileManagerBookInfo = require("apps/filemanager/filemanagerbookinfo") diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index acaa30599..708c39bff 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -470,21 +470,22 @@ function ReaderUI:init() -- And have an extended and customized copy in memory for quick access. self.doc_props = FileManagerBookInfo.extendProps(props, self.document.file) - -- Set "reading" status if there is no status. + local md5 = self.doc_settings:readSetting("partial_md5_checksum") + if md5 == nil then + md5 = util.partialMD5(self.document.file) + self.doc_settings:saveSetting("partial_md5_checksum", md5) + end + local summary = self.doc_settings:readSetting("summary", {}) if summary.status == nil then summary.status = "reading" summary.modified = os.date("%Y-%m-%d", os.time()) end - local md5 = self.doc_settings:readSetting("partial_md5_checksum") - if md5 == nil then - md5 = util.partialMD5(self.document.file) - self.doc_settings:saveSetting("partial_md5_checksum", md5) + if summary.status ~= "complete" or not G_reader_settings:isTrue("history_freeze_finished_books") then + require("readhistory"):addItem(self.document.file) -- (will update "lastfile") end - require("readhistory"):addItem(self.document.file) -- (will update "lastfile") - -- After initialisation notify that document is loaded and rendered -- CREngine only reports correct page count after rendering is done -- Need the same event for PDF document diff --git a/frontend/document/documentregistry.lua b/frontend/document/documentregistry.lua index 76a9cd46f..117b3100e 100644 --- a/frontend/document/documentregistry.lua +++ b/frontend/document/documentregistry.lua @@ -86,14 +86,15 @@ end --- Returns the preferred registered document handler or fallback provider. -- @string file +-- @bool include_aux include auxiliary (non-document) providers -- @treturn table provider -function DocumentRegistry:getProvider(file) +function DocumentRegistry:getProvider(file, include_aux) local providers = self:getProviders(file) - if providers then + if providers or include_aux then -- associated provider local provider_key = DocumentRegistry:getAssociatedProviderKey(file) local provider = provider_key and self.known_providers[provider_key] - if provider and not provider.order then -- excluding auxiliary + if provider and (not provider.order or include_aux) then -- excluding auxiliary by default return provider end -- highest weighted provider diff --git a/frontend/readhistory.lua b/frontend/readhistory.lua index f01be5672..ebd10642c 100644 --- a/frontend/readhistory.lua +++ b/frontend/readhistory.lua @@ -3,7 +3,6 @@ local DocSettings = require("docsettings") local datetime = require("datetime") local dump = require("dump") local ffiutil = require("ffi/util") -local filemanagerutil = require("apps/filemanager/filemanagerutil") local util = require("util") local joinPath = ffiutil.joinPath local lfs = require("libs/libkoreader-lfs") @@ -323,36 +322,32 @@ end --- Adds new item (last opened document) to the top of the history list. -- If item time (ts) is passed, add item to the history list at this time position. function ReadHistory:addItem(file, ts, no_flush) - if file ~= nil and lfs.attributes(file, "mode") == "file" then - local index = self:getIndexByFile(realpath(file)) - if index then -- book is in the history already - if ts and self.hist[index].time == ts then - return -- legacy item already added - end - if not ts and G_reader_settings:isTrue("history_freeze_finished_books") - and filemanagerutil.getStatus(file) == "complete" then - return -- book marked as finished, do not update timestamps of item and file - end - end - local now = ts or os.time() - local mtime = lfs.attributes(file, "modification") - lfs.touch(file, now, mtime) -- update book access time for sorting by last read date - if index == 1 and not ts then -- last book, update access time only - self.hist[1].time = now - self.hist[1].mandatory = getMandatory(now) - else -- old or new book - if index then -- old book - table.remove(self.hist, index) - end - index = ts and self:getIndexByTime(ts, file:gsub(".*/", "")) or 1 - table.insert(self.hist, index, buildEntry(now, file)) - end - if not no_flush then - self:_reduce() - self:_flush() + file = realpath(file) + if not file or (ts and lfs.attributes(file, "mode") ~= "file") then + return -- bad legacy item + end + local index = self:getIndexByFile(file) + if ts and index and self.hist[index].time == ts then + return -- legacy item already added + end + local now = ts or os.time() + local mtime = lfs.attributes(file, "modification") + lfs.touch(file, now, mtime) -- update book access time for sorting by last read date + if index == 1 and not ts then -- last book, update access time only + self.hist[1].time = now + self.hist[1].mandatory = getMandatory(now) + else -- old or new book + if index then -- old book + table.remove(self.hist, index) end - return true -- used while adding legacy items + index = ts and self:getIndexByTime(ts, file:gsub(".*/", "")) or 1 + table.insert(self.hist, index, buildEntry(now, file)) + end + if not no_flush then + self:_reduce() + self:_flush() end + return true -- used while adding legacy items end --- Updates last book access time on closing the document. diff --git a/plugins/coverbrowser.koplugin/covermenu.lua b/plugins/coverbrowser.koplugin/covermenu.lua index 8f53a4f6a..6b1bfb7d0 100644 --- a/plugins/coverbrowser.koplugin/covermenu.lua +++ b/plugins/coverbrowser.koplugin/covermenu.lua @@ -247,7 +247,7 @@ function CoverMenu:updateItems(select_number) -- and store it as self.file_dialog, and UIManager:show() it. self.showFileDialog_orig(self, file) - local bookinfo = self.bookinfo -- getBookInfo(file) called by FileManager + local bookinfo = self.book_props -- getBookInfo(file) called by FileManager if not bookinfo or bookinfo._is_directory then -- If no bookinfo (yet) about this file, or it's a directory, let the original dialog be return true @@ -326,7 +326,7 @@ function CoverMenu:onHistoryMenuHold(item) self.onMenuHold_orig(self, item) local file = item.file - local bookinfo = self.bookinfo -- getBookInfo(file) called by FileManagerHistory + local bookinfo = self.book_props -- getBookInfo(file) called by FileManagerHistory if not bookinfo then -- If no bookinfo (yet) about this file, let the original dialog be return true @@ -397,7 +397,7 @@ function CoverMenu:onCollectionsMenuHold(item) self.onMenuHold_orig(self, item) local file = item.file - local bookinfo = self.bookinfo -- getBookInfo(file) called by FileManagerCollection + local bookinfo = self.book_props -- getBookInfo(file) called by FileManagerCollection if not bookinfo then -- If no bookinfo (yet) about this file, let the original dialog be return true