From 1ef6d0b25710ad4cd1a9f963c602db3e99695611 Mon Sep 17 00:00:00 2001 From: Frans de Jonge Date: Sun, 17 Jan 2021 09:22:48 +0100 Subject: [PATCH] [feat] Support mimetypes in DocumentRegistry:hasProvider() (#7155) And make .djvu the canonical extension for DjVu. Fixes #5478. --- frontend/document/djvudocument.lua | 2 +- frontend/document/documentregistry.lua | 16 ++++++++++- frontend/ui/widget/opdsbrowser.lua | 39 ++++++++------------------ plugins/wallabag.koplugin/main.lua | 18 ++++++++---- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/frontend/document/djvudocument.lua b/frontend/document/djvudocument.lua index b4fbc55b0..5979f277d 100644 --- a/frontend/document/djvudocument.lua +++ b/frontend/document/djvudocument.lua @@ -149,8 +149,8 @@ function DjvuDocument:drawPage(target, x, y, rect, pageno, zoom, rotation, gamma end function DjvuDocument:register(registry) - registry:addProvider("djv", "image/vnd.djvu", self, 100) registry:addProvider("djvu", "image/vnd.djvu", self, 100) + registry:addProvider("djv", "image/vnd.djvu", self, 100) end return DjvuDocument diff --git a/frontend/document/documentregistry.lua b/frontend/document/documentregistry.lua index 741dc3af6..ac54e0177 100644 --- a/frontend/document/documentregistry.lua +++ b/frontend/document/documentregistry.lua @@ -10,6 +10,7 @@ local DocumentRegistry = { registry = {}, providers = {}, filetype_provider = {}, + mimetype_ext = {}, } function DocumentRegistry:addProvider(extension, mimetype, provider, weight) @@ -21,6 +22,10 @@ function DocumentRegistry:addProvider(extension, mimetype, provider, weight) weight = weight or 100, }) self.filetype_provider[extension] = true + -- We regard the first extension registered for a mimetype as canonical. + -- Provided we order the calls to addProvider() correctly, that means + -- epub instead of epub3, etc. + self.mimetype_ext[mimetype] = self.mimetype_ext[mimetype] or extension end function DocumentRegistry:getRandomFile(dir, opened, extension) @@ -53,7 +58,12 @@ end --- Returns true if file has provider. -- @string file -- @treturn boolean -function DocumentRegistry:hasProvider(file) +function DocumentRegistry:hasProvider(file, mimetype) + if mimetype and self.mimetype_ext[mimetype] then + return true + end + if not file then return false end + local filename_suffix = string.lower(util.getFileNameSuffix(file)) local filetype_provider = G_reader_settings:readSetting("provider") or {} @@ -179,6 +189,10 @@ function DocumentRegistry:setProvider(file, provider, all) end end +function DocumentRegistry:mimeToExt(mimetype) + return self.mimetype_ext[mimetype] +end + function DocumentRegistry:openDocument(file, provider) -- force a GC, so that any previous document used memory can be reused -- immediately by this new document without having to wait for the diff --git a/frontend/ui/widget/opdsbrowser.lua b/frontend/ui/widget/opdsbrowser.lua index c8c0b4ca4..ad4476ea7 100644 --- a/frontend/ui/widget/opdsbrowser.lua +++ b/frontend/ui/widget/opdsbrowser.lua @@ -4,6 +4,7 @@ local ButtonDialogTitle = require("ui/widget/buttondialogtitle") local Cache = require("cache") local CacheItem = require("cacheitem") local ConfirmBox = require("ui/widget/confirmbox") +local DocumentRegistry = require("document/documentregistry") local InfoMessage = require("ui/widget/infomessage") local Menu = require("ui/widget/menu") local MultiInputDialog = require("ui/widget/multiinputdialog") @@ -45,27 +46,6 @@ local OPDSBrowser = Menu:extend{ image_rel = "http://opds-spec.org/image", thumbnail_rel = "http://opds-spec.org/image/thumbnail", - formats = { - ["application/epub+zip"] = "EPUB", - ["application/fb2+zip"] = "FB2", - ["application/pdf"] = "PDF", - ["text/html"] = "HTML", - ["text/plain"] = "TXT", - ["application/x-mobipocket-ebook"] = "MOBI", - ["application/x-mobi8-ebook"] = "AZW3", - ["application/vnd.amazon.mobi8-ebook"] = "AZW3", - ["application/x-cbz"] = "CBZ", - ["application/vnd.comicbook+zip"] = "CBZ", - ["application/zip"] = "CBZ", - ["application/x-cbr"] = "CBR", - ["application/vnd.comicbook-rar"] = "CBR", - ["application/x-rar-compressed"] = "CBR", - ["application/vnd.rar"] = "CBR", - ["application/djvu"] = "DJVU", - ["image/x-djvu"] = "DJVU", - ["image/vnd.djvu"] = "DJVU", - }, - width = Screen:getWidth(), height = Screen:getHeight(), no_title = false, @@ -551,10 +531,10 @@ function OPDSBrowser.getCurrentDownloadDir() return G_reader_settings:readSetting("download_dir") or lastdir end -function OPDSBrowser:downloadFile(item, format, remote_url) +function OPDSBrowser:downloadFile(item, filetype, remote_url) -- download to user selected directory or last opened dir local download_dir = self.getCurrentDownloadDir() - local filename = util.getSafeFilename(item.author .. " - " .. item.title .. "." .. string.lower(format), download_dir) + local filename = util.getSafeFilename(item.author .. " - " .. item.title .. "." .. filetype, download_dir) local local_path = download_dir .. "/" .. filename local_path = util.fixUtf8(local_path, "_") @@ -646,12 +626,17 @@ function OPDSBrowser:showDownloads(item) local index = (i-1)*downloadsperline + j local acquisition = acquisitions[index] if acquisition then - local format = self.formats[acquisition.type] - if format then + local filetype + if DocumentRegistry:hasProvider(nil, acquisition.type) then + filetype = DocumentRegistry:mimeToExt(acquisition.type) + elseif DocumentRegistry:hasProvider(acquisition.href) then + filetype = string.lower(util.getFileNameSuffix(acquisition.href)) + end + if filetype then -- append DOWNWARDS BLACK ARROW ⬇ U+2B07 to format - button.text = format .. "\xE2\xAC\x87" + button.text = string.upper(filetype) .. "\xE2\xAC\x87" button.callback = function() - self:downloadFile(item, format, acquisition.href) + self:downloadFile(item, filetype, acquisition.href) UIManager:close(self.download_dialog) end table.insert(line, button) diff --git a/plugins/wallabag.koplugin/main.lua b/plugins/wallabag.koplugin/main.lua index c434bad4e..121a1767d 100644 --- a/plugins/wallabag.koplugin/main.lua +++ b/plugins/wallabag.koplugin/main.lua @@ -6,6 +6,7 @@ local BD = require("ui/bidi") local DataStorage = require("datastorage") local Dispatcher = require("dispatcher") local DocSettings = require("docsettings") +local DocumentRegistry = require("document/documentregistry") local Event = require("ui/event") local FFIUtil = require("ffi/util") local FileManager = require("apps/filemanager/filemanager") @@ -485,11 +486,18 @@ function Wallabag:download(article) local file_ext = ".epub" local item_url = "/api/entries/" .. article.id .. "/export.epub" - -- If the article links to a pdf file, we will download it directly - ---- @todo use hasProvider to skip all supported mimetypes - if article.mimetype == "application/pdf" then - file_ext = ".pdf" - item_url = article.url + -- If the article links to a supported file, we will download it directly. + -- All webpages are HTML. Ignore them since we want the Wallabag EPUB instead! + if article.mimetype ~= "text/html" then + if DocumentRegistry:hasProvider(nil, article.mimetype) then + file_ext = "."..DocumentRegistry:mimeToExt(article.mimetype) + item_url = article.url + -- A function represents `null` in our JSON.decode, because `nil` would just disappear. + -- In that case, fall back to the file extension. + elseif type(article.mimetype) == "function" and DocumentRegistry:hasProvider(article.url) then + file_ext = "" + item_url = article.url + end end local local_path = self.directory .. article_id_prefix .. article.id .. article_id_postfix .. title .. file_ext