diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index 4a4f3c76c..bd8d2da6b 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -61,6 +61,7 @@ local Device = { canSuspend = yes, canReboot = no, canPowerOff = no, + canAssociateFileExtensions = no, -- use these only as a last resort. We should abstract the functionality -- and have device dependent implementations in the corresponting @@ -311,6 +312,11 @@ end -- and only if allowed state is true at the time of waitForEvents() invocation. function Device:setAutoStandby(isAllowed) end +-- Hardware specific method to set OS-level file associations to launch koreader. Expects boolean map. +function Device:associateFileExtensions(exts) + logger.dbg("Device:associateFileExtensions():", util.tableSize(exts), "entries, OS handler missing") +end + -- Hardware specific method to handle usb plug in event function Device:usbPlugIn() end diff --git a/frontend/document/documentregistry.lua b/frontend/document/documentregistry.lua index 847dd020f..741dc3af6 100644 --- a/frontend/document/documentregistry.lua +++ b/frontend/document/documentregistry.lua @@ -148,6 +148,18 @@ function DocumentRegistry:getProviders(file) end end +--- Get mapping of file extensions to providers +-- @treturn table mapping file extensions to a list of providers +function DocumentRegistry:getExtensions() + local t = {} + for _, provider in ipairs(self.providers) do + local ext = provider.extension + t[ext] = t[ext] or {} + table.insert(t[ext], provider) + end + return t +end + --- Sets the preferred registered document handler. -- @string file -- @bool all diff --git a/frontend/ui/elements/common_settings_menu_table.lua b/frontend/ui/elements/common_settings_menu_table.lua index 30403fb74..1a9fd831c 100644 --- a/frontend/ui/elements/common_settings_menu_table.lua +++ b/frontend/ui/elements/common_settings_menu_table.lua @@ -48,6 +48,14 @@ if Device:canToggleMassStorage() then common_settings.mass_storage_actions = MassStorage:getActionsMenuTable() end +-- Associate OS level file extensions (must be off by default, because we're not associated initially) +if Device:canAssociateFileExtensions() then + common_settings.file_ext_assoc = { + text = _("Associate file extensions"), + sub_item_table = require("ui/elements/file_ext_assoc"):getSettingsMenuTable() + } +end + -- This affects the topmenu, we want to be able to access it even if !Device:setDateTime() common_settings.time = { text = _("Time and date"), diff --git a/frontend/ui/elements/file_ext_assoc.lua b/frontend/ui/elements/file_ext_assoc.lua new file mode 100644 index 000000000..4c042e461 --- /dev/null +++ b/frontend/ui/elements/file_ext_assoc.lua @@ -0,0 +1,71 @@ +local Device = require("device") +local DocumentRegistry = require("document/documentregistry") +local _ = require("gettext") + +local ExtAssoc = { + assoc = G_reader_settings:readSetting("file_ext_assoc") or {}, +} + +function ExtAssoc:commit() + G_reader_settings:saveSetting("file_ext_assoc", self.assoc):flush() + -- Translate the boolean map back to map of providers the OS backend can inquire further + local t = {} + for k, v in pairs(DocumentRegistry:getExtensions()) do + if self.assoc[k] then t[k] = v end + end + Device:associateFileExtensions(t) +end + +function ExtAssoc:setAll(state) + for k, dummy in pairs(DocumentRegistry:getExtensions()) do + self:setOne(k, state) + end + self:commit() +end + +function ExtAssoc:setOne(ext, state) + self.assoc[ext] = state and true or nil +end + +function ExtAssoc:getSettingsMenuTable() + local ret = { + { + keep_menu_open = true, + text = _("Enable all"), + callback = function(menu) + self:setAll(true) + menu:updateItems() + end, + }, + { + keep_menu_open = true, + text = _("Disable all"), + callback = function(menu) + self:setAll(false) + menu:updateItems() + end, + separator = true, + }, + } + local exts = DocumentRegistry:getExtensions() + local keys = {} + for k, dummy in pairs(exts) do + table.insert(keys, k) + end + table.sort(keys) + for dummy, k in ipairs(keys) do + table.insert(ret, { + keep_menu_open = true, + text = k, + checked_func = function() return self.assoc[k] end, + callback = function() + self:setOne(k, not self.assoc[k]) + self:commit() + end + }) + end + return ret +end + +return ExtAssoc + diff --git a/frontend/ui/elements/filemanager_menu_order.lua b/frontend/ui/elements/filemanager_menu_order.lua index 8bcd3212a..3e81215f2 100644 --- a/frontend/ui/elements/filemanager_menu_order.lua +++ b/frontend/ui/elements/filemanager_menu_order.lua @@ -47,6 +47,7 @@ local order = { "ignore_sleepcover", "ignore_open_sleepcover", "mass_storage_settings", + "file_ext_assoc", "screenshot", }, navigation = { diff --git a/frontend/ui/elements/reader_menu_order.lua b/frontend/ui/elements/reader_menu_order.lua index 22ce4e9cb..500c3516a 100644 --- a/frontend/ui/elements/reader_menu_order.lua +++ b/frontend/ui/elements/reader_menu_order.lua @@ -67,6 +67,7 @@ local order = { "ignore_sleepcover", "ignore_open_sleepcover", "mass_storage_settings", + "file_ext_assoc", "screenshot", }, navigation = {