From cd8ef3ceb5bb6c7e03f42c2e859869ac81ed410a Mon Sep 17 00:00:00 2001 From: hius07 <62179190+hius07@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:54:32 +0200 Subject: [PATCH] FileManager, History, Collections: expose file dialog buttons (#12845) --- frontend/apps/filemanager/filemanager.lua | 38 +++ .../filemanager/filemanagercollection.lua | 26 +- .../apps/filemanager/filemanagerhistory.lua | 28 +- plugins/coverbrowser.koplugin/covermenu.lua | 240 ------------------ plugins/coverbrowser.koplugin/main.lua | 71 +++++- 5 files changed, 139 insertions(+), 264 deletions(-) diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index e4c284666..1aaa4c584 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -323,6 +323,15 @@ function FileManager:setupLayout() }) end + if file_manager.file_dialog_added_buttons ~= nil then + for _, row_func in ipairs(file_manager.file_dialog_added_buttons) do + local row = row_func(file, is_file, self.book_props) + if row ~= nil then + table.insert(buttons, row) + end + end + end + self.file_dialog = ButtonDialog:new{ title = is_file and BD.filename(file:match("([^/]+)$")) or BD.directory(file:match("([^/]+)$")), title_align = "center", @@ -470,6 +479,35 @@ function FileManager:onSwipeFM(ges) return true end +function FileManager:addFileDialogButtons(row_id, row_func) -- FileManager, History, Collections file_dialog + self.file_dialog_added_buttons = self.file_dialog_added_buttons or { index = {} } + if self.file_dialog_added_buttons.index[row_id] == nil then + table.insert(self.file_dialog_added_buttons, row_func) + self.file_dialog_added_buttons.index[row_id] = #self.file_dialog_added_buttons + end +end + +function FileManager:removeFileDialogButtons(row_id) + local index = self.file_dialog_added_buttons and self.file_dialog_added_buttons.index[row_id] + if index ~= nil then + table.remove(self.file_dialog_added_buttons, index) + if #self.file_dialog_added_buttons == 0 then + self.file_dialog_added_buttons = nil + else + self.file_dialog_added_buttons.index[row_id] = nil + for id, idx in pairs(self.file_dialog_added_buttons.index) do + if idx > index then + self.file_dialog_added_buttons.index[id] = idx - 1 + end + end + end + end +end + +function FileManager.getMenuInstance() + return FileManager.instance.file_chooser +end + function FileManager:onShowPlusMenu() self:tapPlus() return true diff --git a/frontend/apps/filemanager/filemanagercollection.lua b/frontend/apps/filemanager/filemanagercollection.lua index 5c01762f4..1edc22670 100644 --- a/frontend/apps/filemanager/filemanagercollection.lua +++ b/frontend/apps/filemanager/filemanagercollection.lua @@ -122,18 +122,18 @@ end function FileManagerCollection:onMenuHold(item) local file = item.file - self.collfile_dialog = nil + self.file_dialog = nil self.book_props = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) local function close_dialog_callback() - UIManager:close(self.collfile_dialog) + UIManager:close(self.file_dialog) end local function close_dialog_menu_callback() - UIManager:close(self.collfile_dialog) + UIManager:close(self.file_dialog) self._manager.coll_menu.close_callback() end local function close_dialog_update_callback() - UIManager:close(self.collfile_dialog) + UIManager:close(self.file_dialog) self._manager:updateItemTable() self._manager.files_updated = true end @@ -197,15 +197,29 @@ function FileManagerCollection:onMenuHold(item) }) end - self.collfile_dialog = ButtonDialog:new{ + if self._manager.file_dialog_added_buttons ~= nil then + for _, row_func in ipairs(self._manager.file_dialog_added_buttons) do + local row = row_func(file, true, self.book_props) + if row ~= nil then + table.insert(buttons, row) + end + end + end + + self.file_dialog = ButtonDialog:new{ title = BD.filename(item.text), title_align = "center", buttons = buttons, } - UIManager:show(self.collfile_dialog) + UIManager:show(self.file_dialog) return true end +function FileManagerCollection.getMenuInstance() + local ui = require("apps/filemanager/filemanager").instance or require("apps/reader/readerui").instance + return ui.collections.coll_menu +end + function FileManagerCollection:showCollDialog() local coll_dialog local buttons = { diff --git a/frontend/apps/filemanager/filemanagerhistory.lua b/frontend/apps/filemanager/filemanagerhistory.lua index cf4766ee9..71ccaf482 100644 --- a/frontend/apps/filemanager/filemanagerhistory.lua +++ b/frontend/apps/filemanager/filemanagerhistory.lua @@ -134,18 +134,18 @@ end function FileManagerHistory:onMenuHold(item) local file = item.file - self.histfile_dialog = nil + self.file_dialog = nil self.book_props = self.ui.coverbrowser and self.ui.coverbrowser:getBookInfo(file) local function close_dialog_callback() - UIManager:close(self.histfile_dialog) + UIManager:close(self.file_dialog) end local function close_dialog_menu_callback() - UIManager:close(self.histfile_dialog) + UIManager:close(self.file_dialog) self._manager.hist_menu.close_callback() end local function close_dialog_update_callback() - UIManager:close(self.histfile_dialog) + UIManager:close(self.file_dialog) if self._manager.filter ~= "all" or self._manager.is_frozen then self._manager:fetchStatuses(false) else @@ -199,7 +199,7 @@ function FileManagerHistory:onMenuHold(item) { text = _("Remove from history"), callback = function() - UIManager:close(self.histfile_dialog) + UIManager:close(self.file_dialog) -- The item's idx field is tied to the current *view*, so we can only pass it as-is when there's no filtering *at all* involved. local index = item.idx if self._manager.search_string or self._manager.selected_collections or self._manager.filter ~= "all" then @@ -219,15 +219,29 @@ function FileManagerHistory:onMenuHold(item) filemanagerutil.genBookDescriptionButton(file, self.book_props, close_dialog_callback, item.dim), }) - self.histfile_dialog = ButtonDialog:new{ + if self._manager.file_dialog_added_buttons ~= nil then + for _, row_func in ipairs(self._manager.file_dialog_added_buttons) do + local row = row_func(file, true, self.book_props) + if row ~= nil then + table.insert(buttons, row) + end + end + end + + self.file_dialog = ButtonDialog:new{ title = BD.filename(item.text), title_align = "center", buttons = buttons, } - UIManager:show(self.histfile_dialog) + UIManager:show(self.file_dialog) return true end +function FileManagerHistory.getMenuInstance() + local ui = require("apps/filemanager/filemanager").instance or require("apps/reader/readerui").instance + return ui.history.hist_menu +end + function FileManagerHistory:onShowHist(search_info) self.hist_menu = Menu:new{ ui = self.ui, diff --git a/plugins/coverbrowser.koplugin/covermenu.lua b/plugins/coverbrowser.koplugin/covermenu.lua index b86bc551d..77f8ccf0d 100644 --- a/plugins/coverbrowser.koplugin/covermenu.lua +++ b/plugins/coverbrowser.koplugin/covermenu.lua @@ -219,246 +219,6 @@ function CoverMenu:updateItems(select_number, no_recalculate_dimen) end UIManager:scheduleIn(1, self.items_update_action) end - - -- (We may not need to do the following if we extend showFileDialog - -- code in filemanager.lua to check for existence and call a - -- method: self:getAdditionalButtons() to add our buttons - -- to its own set.) - - -- We want to add some buttons to the showFileDialog popup. This function - -- is dynamically created by FileManager:init(), and we don't want - -- to override this... So, here, when we see the showFileDialog function, - -- we replace it by ours. - -- (FileManager may replace file_chooser.showFileDialog after we've been called once, so we need - -- to replace it again if it is not ours) - if self.path -- FileManager only - and (not self.showFileDialog_ours -- never replaced - or self.showFileDialog ~= self.showFileDialog_ours) then -- it is no more ours - -- We need to do it at nextTick, once FileManager has instantiated - -- its FileChooser completely - UIManager:nextTick(function() - -- Store original function, so we can call it - self.showFileDialog_orig = self.showFileDialog - - -- Replace it with ours - -- This causes luacheck warning: "shadowing upvalue argument 'self' on line 34". - -- Ignoring it (as done in filemanager.lua for the same showFileDialog) - self.showFileDialog = function(self, item) -- luacheck: ignore - local file = item.path - -- Call original function: it will create a ButtonDialog - -- and store it as self.file_dialog, and UIManager:show() it. - self.showFileDialog_orig(self, item) - - 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 - end - - -- Remember some of this original ButtonDialog properties - local orig_title = self.file_dialog.title - local orig_title_align = self.file_dialog.title_align - local orig_buttons = self.file_dialog.buttons - -- Close original ButtonDialog (it has not yet been painted - -- on screen, so we won't see it) - UIManager:close(self.file_dialog) - -- And clear the rendering stack to avoid inheriting its dirty/refresh queue - UIManager:clearRenderStack() - - -- Add some new buttons to original buttons set - table.insert(orig_buttons, { - { -- Allow user to ignore some offending cover image - text = bookinfo.ignore_cover and _("Unignore cover") or _("Ignore cover"), - enabled = bookinfo.has_cover and true or false, - callback = function() - BookInfoManager:setBookInfoProperties(file, { - ["ignore_cover"] = not bookinfo.ignore_cover and 'Y' or false, - }) - UIManager:close(self.file_dialog) - self:updateItems(1, true) - end, - }, - { -- Allow user to ignore some bad metadata (filename will be used instead) - text = bookinfo.ignore_meta and _("Unignore metadata") or _("Ignore metadata"), - enabled = bookinfo.has_meta and true or false, - callback = function() - BookInfoManager:setBookInfoProperties(file, { - ["ignore_meta"] = not bookinfo.ignore_meta and 'Y' or false, - }) - UIManager:close(self.file_dialog) - self:updateItems(1, true) - end, - }, - }) - table.insert(orig_buttons, { - { -- Allow a new extraction (multiple interruptions, book replaced)... - text = _("Refresh cached book information"), - callback = function() - -- Wipe the cache - self:updateCache(file) - BookInfoManager:deleteBookInfo(file) - UIManager:close(self.file_dialog) - self:updateItems(1, true) - end, - }, - }) - - -- Create the new ButtonDialog, and let UIManager show it - self.file_dialog = ButtonDialog:new{ - title = orig_title, - title_align = orig_title_align, - buttons = orig_buttons, - } - UIManager:show(self.file_dialog) - return true - end - - -- Remember our function - self.showFileDialog_ours = self.showFileDialog - end) - end -end - --- Similar to showFileDialog setup just above, but for History, --- which is plugged in main.lua _FileManagerHistory_updateItemTable() -function CoverMenu:onHistoryMenuHold(item) - -- Call original function: it will create a ButtonDialog - -- and store it as self.histfile_dialog, and UIManager:show() it. - self.onMenuHold_orig(self, item) - local file = item.file - - 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 - end - - -- Remember some of this original ButtonDialog properties - local orig_title = self.histfile_dialog.title - local orig_title_align = self.histfile_dialog.title_align - local orig_buttons = self.histfile_dialog.buttons - -- Close original ButtonDialog (it has not yet been painted - -- on screen, so we won't see it) - UIManager:close(self.histfile_dialog) - UIManager:clearRenderStack() - - -- Add some new buttons to original buttons set - table.insert(orig_buttons, { - { -- Allow user to ignore some offending cover image - text = bookinfo.ignore_cover and _("Unignore cover") or _("Ignore cover"), - enabled = bookinfo.has_cover and true or false, - callback = function() - BookInfoManager:setBookInfoProperties(file, { - ["ignore_cover"] = not bookinfo.ignore_cover and 'Y' or false, - }) - UIManager:close(self.histfile_dialog) - self:updateItems(1, true) - end, - }, - { -- Allow user to ignore some bad metadata (filename will be used instead) - text = bookinfo.ignore_meta and _("Unignore metadata") or _("Ignore metadata"), - enabled = bookinfo.has_meta and true or false, - callback = function() - BookInfoManager:setBookInfoProperties(file, { - ["ignore_meta"] = not bookinfo.ignore_meta and 'Y' or false, - }) - UIManager:close(self.histfile_dialog) - self:updateItems(1, true) - end, - }, - }) - table.insert(orig_buttons, { - { -- Allow a new extraction (multiple interruptions, book replaced)... - text = _("Refresh cached book information"), - callback = function() - -- Wipe the cache - self:updateCache(file) - BookInfoManager:deleteBookInfo(file) - UIManager:close(self.histfile_dialog) - self:updateItems(1, true) - end, - }, - }) - - -- Create the new ButtonDialog, and let UIManager show it - self.histfile_dialog = ButtonDialog:new{ - title = orig_title, - title_align = orig_title_align, - buttons = orig_buttons, - } - UIManager:show(self.histfile_dialog) - return true -end - --- Similar to showFileDialog setup just above, but for Collections, --- which is plugged in main.lua _FileManagerCollections_updateItemTable() -function CoverMenu:onCollectionsMenuHold(item) - -- Call original function: it will create a ButtonDialog - -- and store it as self.collfile_dialog, and UIManager:show() it. - self.onMenuHold_orig(self, item) - local file = item.file - - 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 - end - - -- Remember some of this original ButtonDialog properties - local orig_title = self.collfile_dialog.title - local orig_title_align = self.collfile_dialog.title_align - local orig_buttons = self.collfile_dialog.buttons - -- Close original ButtonDialog (it has not yet been painted - -- on screen, so we won't see it) - UIManager:close(self.collfile_dialog) - UIManager:clearRenderStack() - - -- Add some new buttons to original buttons set - table.insert(orig_buttons, { - { -- Allow user to ignore some offending cover image - text = bookinfo.ignore_cover and _("Unignore cover") or _("Ignore cover"), - enabled = bookinfo.has_cover and true or false, - callback = function() - BookInfoManager:setBookInfoProperties(file, { - ["ignore_cover"] = not bookinfo.ignore_cover and 'Y' or false, - }) - UIManager:close(self.collfile_dialog) - self:updateItems(1, true) - end, - }, - { -- Allow user to ignore some bad metadata (filename will be used instead) - text = bookinfo.ignore_meta and _("Unignore metadata") or _("Ignore metadata"), - enabled = bookinfo.has_meta and true or false, - callback = function() - BookInfoManager:setBookInfoProperties(file, { - ["ignore_meta"] = not bookinfo.ignore_meta and 'Y' or false, - }) - UIManager:close(self.collfile_dialog) - self:updateItems(1, true) - end, - }, - }) - table.insert(orig_buttons, { - { -- Allow a new extraction (multiple interruptions, book replaced)... - text = _("Refresh cached book information"), - callback = function() - -- Wipe the cache - self:updateCache(file) - BookInfoManager:deleteBookInfo(file) - UIManager:close(self.collfile_dialog) - self:updateItems(1, true) - end, - }, - }) - - -- Create the new ButtonDialog, and let UIManager show it - self.collfile_dialog = ButtonDialog:new{ - title = orig_title, - title_align = orig_title_align, - buttons = orig_buttons, - } - UIManager:show(self.collfile_dialog) - return true end function CoverMenu:onCloseWidget() diff --git a/plugins/coverbrowser.koplugin/main.lua b/plugins/coverbrowser.koplugin/main.lua index b5eec3013..69a8d3960 100644 --- a/plugins/coverbrowser.koplugin/main.lua +++ b/plugins/coverbrowser.koplugin/main.lua @@ -509,14 +509,63 @@ function CoverBrowser.initGrid(menu, display_mode) menu.display_mode_type = display_mode and display_mode:gsub("_.*", "") -- "mosaic" or "list" end +function CoverBrowser.addFileDialogButtons(widget) + FileManager.addFileDialogButtons(widget, "coverbrowser_1", function(file, is_file, bookinfo) + if is_file then + return bookinfo and { + { -- Allow user to ignore some offending cover image + text = bookinfo.ignore_cover and _("Unignore cover") or _("Ignore cover"), + enabled = bookinfo.has_cover and true or false, + callback = function() + BookInfoManager:setBookInfoProperties(file, { + ["ignore_cover"] = not bookinfo.ignore_cover and 'Y' or false, + }) + local menu = widget.getMenuInstance() + UIManager:close(menu.file_dialog) + menu:updateItems(1, true) + end, + }, + { -- Allow user to ignore some bad metadata (filename will be used instead) + text = bookinfo.ignore_meta and _("Unignore metadata") or _("Ignore metadata"), + enabled = bookinfo.has_meta and true or false, + callback = function() + BookInfoManager:setBookInfoProperties(file, { + ["ignore_meta"] = not bookinfo.ignore_meta and 'Y' or false, + }) + local menu = widget.getMenuInstance() + UIManager:close(menu.file_dialog) + menu:updateItems(1, true) + end, + }, + } + end + end) + FileManager.addFileDialogButtons(widget, "coverbrowser_2", function(file, is_file, bookinfo) + if is_file then + return bookinfo and { + { -- Allow a new extraction (multiple interruptions, book replaced)... + text = _("Refresh cached book information"), + callback = function() + local menu = widget.getMenuInstance() + menu:updateCache(file) -- wipe the cache + BookInfoManager:deleteBookInfo(file) + UIManager:close(menu.file_dialog) + menu:updateItems(1, true) + end, + }, + } + end + end) +end + +function CoverBrowser.removeFileDialogButtons(widget) + FileManager.removeFileDialogButtons(widget, "coverbrowser_2") + FileManager.removeFileDialogButtons(widget, "coverbrowser_1") +end + function CoverBrowser:refreshFileManagerInstance() local fc = self.ui.file_chooser if fc then - if not filemanager_display_mode and fc.showFileDialog_orig then - fc.showFileDialog = fc.showFileDialog_orig - fc.showFileDialog_orig = nil - fc.showFileDialog_ours = nil - end fc:_recalculateDimen() fc:changeToPath(fc.path, fc.prev_focused_path) end @@ -557,6 +606,7 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) FileChooser.onCloseWidget = _FileChooser_onCloseWidget_orig FileChooser._recalculateDimen = _FileChooser__recalculateDimen_orig FileManager.tapPlus = _FileManager_tapPlus_orig + CoverBrowser.removeFileDialogButtons(FileManager) -- Also clean-up what we added, even if it does not bother original code FileChooser.updateCache = nil FileChooser._updateItemsBuildUI = nil @@ -574,6 +624,7 @@ function CoverBrowser:setupFileManagerDisplayMode(display_mode) FileChooser.updateCache = CoverMenu.updateCache FileChooser.updateItems = CoverMenu.updateItems FileChooser.onCloseWidget = CoverMenu.onCloseWidget + CoverBrowser.addFileDialogButtons(FileManager) if FileChooser.display_mode_type == "mosaic" then -- Replace some other original methods with those from our MosaicMenu local MosaicMenu = require("mosaicmenu") @@ -630,9 +681,6 @@ local function _FileManagerHistory_updateItemTable(self) hist_menu.updateCache = CoverMenu.updateCache hist_menu.updateItems = CoverMenu.updateItems hist_menu.onCloseWidget = CoverMenu.onCloseWidget - -- Also replace original onMenuHold (it will use original method, so remember it) - hist_menu.onMenuHold_orig = hist_menu.onMenuHold - hist_menu.onMenuHold = CoverMenu.onHistoryMenuHold CoverBrowser.initGrid(hist_menu, display_mode) if hist_menu.display_mode_type == "mosaic" then @@ -681,10 +729,12 @@ function CoverBrowser:setupHistoryDisplayMode(display_mode) -- We only need to replace one FileManagerHistory method if not display_mode then -- classic mode + CoverBrowser.removeFileDialogButtons(FileManagerHistory) -- Put back original methods FileManagerHistory.updateItemTable = _FileManagerHistory_updateItemTable_orig FileManagerHistory.display_mode = nil else + CoverBrowser.addFileDialogButtons(FileManagerHistory) -- Replace original method with the one defined above FileManagerHistory.updateItemTable = _FileManagerHistory_updateItemTable -- And let it know which display_mode we should use @@ -709,9 +759,6 @@ local function _FileManagerCollections_updateItemTable(self) coll_menu.updateCache = CoverMenu.updateCache coll_menu.updateItems = CoverMenu.updateItems coll_menu.onCloseWidget = CoverMenu.onCloseWidget - -- Also replace original onMenuHold (it will use original method, so remember it) - coll_menu.onMenuHold_orig = coll_menu.onMenuHold - coll_menu.onMenuHold = CoverMenu.onCollectionsMenuHold CoverBrowser.initGrid(coll_menu, display_mode) if coll_menu.display_mode_type == "mosaic" then @@ -760,10 +807,12 @@ function CoverBrowser:setupCollectionDisplayMode(display_mode) -- We only need to replace one FileManagerCollection method if not display_mode then -- classic mode + CoverBrowser.removeFileDialogButtons(FileManagerCollection) -- Put back original methods FileManagerCollection.updateItemTable = _FileManagerCollection_updateItemTable_orig FileManagerCollection.display_mode = nil else + CoverBrowser.addFileDialogButtons(FileManagerCollection) -- Replace original method with the one defined above FileManagerCollection.updateItemTable = _FileManagerCollections_updateItemTable -- And let it know which display_mode we should use