2
0
mirror of https://github.com/koreader/koreader synced 2024-11-16 06:12:56 +00:00
koreader/frontend/apps/filemanager/filemanagercollection.lua

231 lines
8.0 KiB
Lua
Raw Normal View History

2023-06-08 05:27:52 +00:00
local ButtonDialog = require("ui/widget/buttondialog")
local Device = require("device")
2023-06-08 05:27:52 +00:00
local DocumentRegistry = require("document/documentregistry")
local Menu = require("ui/widget/menu")
local ReadCollection = require("readcollection")
local UIManager = require("ui/uimanager")
Clarify our OOP semantics across the codebase (#9586) Basically: * Use `extend` for class definitions * Use `new` for object instantiations That includes some minor code cleanups along the way: * Updated `Widget`'s docs to make the semantics clearer. * Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283) * Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass). * Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events. * Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier. * Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references. * ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak). * Terminal: Make sure the shell is killed on plugin teardown. * InputText: Fix Home/End/Del physical keys to behave sensibly. * InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...). * OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of. * ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed! * Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local Screen = require("device").screen
2022-12-25 07:46:44 +00:00
local filemanagerutil = require("apps/filemanager/filemanagerutil")
local _ = require("gettext")
Clarify our OOP semantics across the codebase (#9586) Basically: * Use `extend` for class definitions * Use `new` for object instantiations That includes some minor code cleanups along the way: * Updated `Widget`'s docs to make the semantics clearer. * Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283) * Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass). * Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events. * Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier. * Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references. * ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak). * Terminal: Make sure the shell is killed on plugin teardown. * InputText: Fix Home/End/Del physical keys to behave sensibly. * InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...). * OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of. * ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed! * Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
local FileManagerCollection = WidgetContainer:extend{
title = _("Favorites"),
}
function FileManagerCollection:init()
self.ui.menu:registerToMainMenu(self)
end
function FileManagerCollection:addToMainMenu(menu_items)
menu_items.collections = {
text = self.title,
callback = function()
self:onShowColl()
end,
}
end
function FileManagerCollection:updateItemTable()
local item_table = {}
for _, item in pairs(ReadCollection.coll[self.coll_menu.collection_name]) do
table.insert(item_table, item)
end
table.sort(item_table, function(v1, v2) return v1.order < v2.order end)
self.coll_menu:switchItemTable(self.title, item_table, -1)
end
2023-03-31 16:35:27 +00:00
function FileManagerCollection:onMenuChoice(item)
local file = item.file
if self.ui.document then
if self.ui.document.file ~= file then
self.ui:switchDocument(file)
end
else
local ReaderUI = require("apps/reader/readerui")
ReaderUI:showReader(file)
end
2023-03-31 16:35:27 +00:00
end
function FileManagerCollection:onMenuHold(item)
local file = item.file
self.collfile_dialog = nil
2023-03-31 16:35:27 +00:00
local function close_dialog_callback()
UIManager:close(self.collfile_dialog)
end
2023-06-08 05:27:52 +00:00
local function close_dialog_menu_callback()
UIManager:close(self.collfile_dialog)
self._manager.coll_menu.close_callback()
end
local function close_dialog_update_callback()
UIManager:close(self.collfile_dialog)
self._manager:updateItemTable()
self._manager.files_updated = true
end
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
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),
{
text = _("Remove from favorites"),
callback = function()
UIManager:close(self.collfile_dialog)
ReadCollection:removeItem(file, self.collection_name)
self._manager:updateItemTable()
end,
},
})
table.insert(buttons, {
filemanagerutil.genShowFolderButton(file, close_dialog_menu_callback),
filemanagerutil.genBookInformationButton(file, close_dialog_callback),
})
table.insert(buttons, {
filemanagerutil.genBookCoverButton(file, close_dialog_callback),
filemanagerutil.genBookDescriptionButton(file, close_dialog_callback),
})
if Device:canExecuteScript(file) then
table.insert(buttons, {
filemanagerutil.genExecuteScriptButton(file, close_dialog_menu_callback)
})
end
2023-06-08 05:27:52 +00:00
self.collfile_dialog = ButtonDialog:new{
title = item.text,
title_align = "center",
buttons = buttons,
}
UIManager:show(self.collfile_dialog)
return true
end
function FileManagerCollection:MenuSetRotationModeHandler(rotation)
if rotation ~= nil and rotation ~= Screen:getRotationMode() then
UIManager:close(self._manager.coll_menu)
if self._manager.ui.view and self._manager.ui.view.onSetRotationMode then
self._manager.ui.view:onSetRotationMode(rotation)
elseif self._manager.ui.onSetRotationMode then
self._manager.ui:onSetRotationMode(rotation)
else
Screen:setRotationMode(rotation)
end
self._manager:onShowColl()
end
return true
end
function FileManagerCollection:onShowColl(collection_name)
collection_name = collection_name or ReadCollection.default_collection_name
self.coll_menu = Menu:new{
ui = self.ui,
covers_fullscreen = true, -- hint for UIManager:_repaint()
is_borderless = true,
is_popout = false,
-- item and book cover thumbnail dimensions in Mosaic and Detailed list display modes
-- must be equal in File manager, History and Collection windows to avoid image scaling
title_bar_fm_style = true,
2023-06-08 05:27:52 +00:00
title_bar_left_icon = "appbar.menu",
onLeftButtonTap = function() self:showCollDialog() end,
2023-03-31 16:35:27 +00:00
onMenuChoice = self.onMenuChoice,
onMenuHold = self.onMenuHold,
onSetRotationMode = self.MenuSetRotationModeHandler,
_manager = self,
collection_name = collection_name,
}
self.coll_menu.close_callback = function()
if self.files_updated then
if self.ui.file_chooser then
self.ui.file_chooser:refreshPath()
end
self.files_updated = nil
end
UIManager:close(self.coll_menu)
self.coll_menu = nil
end
self:updateItemTable()
UIManager:show(self.coll_menu)
return true
end
2023-06-08 05:27:52 +00:00
function FileManagerCollection:showCollDialog()
local coll_dialog
local buttons = {
{{
text = _("Sort favorites"),
2023-06-08 05:27:52 +00:00
callback = function()
UIManager:close(coll_dialog)
self:sortCollection()
2023-06-08 05:27:52 +00:00
end,
}},
{{
text = _("Add a book to favorites"),
callback = function()
UIManager:close(coll_dialog)
local PathChooser = require("ui/widget/pathchooser")
local path_chooser = PathChooser:new{
path = G_reader_settings:readSetting("home_dir"),
select_directory = false,
file_filter = function(file)
return DocumentRegistry:hasProvider(file)
2023-06-08 05:27:52 +00:00
end,
onConfirm = function(file)
if not ReadCollection:hasFile(file) then
ReadCollection:addItem(file, self.coll_menu.collection_name)
2023-06-08 05:27:52 +00:00
self:updateItemTable()
end
end,
}
UIManager:show(path_chooser)
end,
}},
}
if self.ui.document then
local has_file = ReadCollection:hasFile(self.ui.document.file)
table.insert(buttons, {{
text_func = function()
return has_file and _("Remove current book from favorites") or _("Add current book to favorites")
end,
2023-06-08 05:27:52 +00:00
callback = function()
UIManager:close(coll_dialog)
if has_file then
ReadCollection:removeItem(self.ui.document.file)
else
ReadCollection:addItem(self.ui.document.file, self.coll_menu.collection_name)
end
self:updateItemTable()
2023-06-08 05:27:52 +00:00
end,
}})
end
2023-06-08 05:27:52 +00:00
coll_dialog = ButtonDialog:new{
buttons = buttons,
}
UIManager:show(coll_dialog)
end
function FileManagerCollection:sortCollection()
local item_table = ReadCollection:getOrderedCollection(self.coll_menu.collection_name)
2023-06-08 05:27:52 +00:00
local SortWidget = require("ui/widget/sortwidget")
local sort_widget
sort_widget = SortWidget:new{
title = _("Sort favorites"),
item_table = item_table,
callback = function()
ReadCollection:updateCollectionOrder(self.coll_menu.collection_name, sort_widget.item_table)
2023-06-08 05:27:52 +00:00
self:updateItemTable()
end
}
UIManager:show(sort_widget)
end
2023-09-06 06:41:10 +00:00
function FileManagerCollection:onBookMetadataChanged()
if self.coll_menu then
self.coll_menu:updateItems()
end
end
return FileManagerCollection