mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
80244ea4e2
Squash of feat/koreader-widget-board. KOReader plugin 2.0.0 gets the widget-board dashboard, redesigned book details, menus, lists and dialogs, Decor page and reading companions. Highlights, notes and bookmarks now stay in step across web, Kobo, KOReader and the phones (defects D-00 to D-20, migration 0121), and reading progress and narration hand off cleanly between devices.
177 lines
7.3 KiB
Lua
177 lines
7.3 KiB
Lua
-- Single and bulk downloads write to one destination, KOReader's own
|
|
-- download_dir, so both sheets have to offer the same chooser and see each
|
|
-- other's choice.
|
|
|
|
local shown = {}
|
|
local next_ticks = {}
|
|
|
|
package.loaded["ui/bidi"] = {
|
|
dirpath = function(value) return value end,
|
|
filepath = function(value) return value end,
|
|
}
|
|
package.loaded["datastorage"] = {
|
|
getSettingsDir = function() return "/tmp/bookorbit-spec" end,
|
|
getDataDir = function() return "/tmp/bookorbit-spec" end,
|
|
}
|
|
package.loaded["dump"] = function(value) return tostring(value) end
|
|
package.loaded["document/documentregistry"] = { hasProvider = function() return true end }
|
|
package.loaded["ui/widget/buttondialog"] = {
|
|
new = function(_, opts)
|
|
opts = opts or {}
|
|
function opts:setTitle(title) self.title = title end
|
|
return opts
|
|
end,
|
|
}
|
|
package.loaded["ui/widget/infomessage"] = { new = function(_, opts) return opts or {} end }
|
|
package.loaded["ui/widget/confirmbox"] = package.loaded["ui/widget/infomessage"]
|
|
package.loaded["ui/widget/inputdialog"] = package.loaded["ui/widget/infomessage"]
|
|
package.loaded["ui/widget/notification"] = package.loaded["ui/widget/infomessage"]
|
|
package.loaded["ui/uimanager"] = {
|
|
show = function(_, widget) table.insert(shown, widget) end,
|
|
close = function() end,
|
|
nextTick = function(_, callback) table.insert(next_ticks, callback) end,
|
|
scheduleIn = function(_, _, callback) table.insert(next_ticks, callback) end,
|
|
preventStandby = function() end,
|
|
allowStandby = function() end,
|
|
forceRePaint = function() end,
|
|
}
|
|
package.loaded["libs/libkoreader-lfs"] = {
|
|
attributes = function() return nil end,
|
|
dir = function() return function() return nil end end,
|
|
}
|
|
package.loaded["logger"] = { dbg = function() end, warn = function() end }
|
|
package.loaded["util"] = {
|
|
fixUtf8 = function(value) return value end,
|
|
getSafeFilename = function(value) return value end,
|
|
makePath = function() end,
|
|
trim = function(value) return value end,
|
|
}
|
|
package.loaded["ffi/util"] = {
|
|
template = function(value, ...)
|
|
local values = { ... }
|
|
return (tostring(value):gsub("%%(%d+)", function(index)
|
|
return tostring(values[tonumber(index)])
|
|
end))
|
|
end,
|
|
}
|
|
package.loaded["gettext"] = setmetatable({
|
|
ngettext = function(one, many, count) return count == 1 and one or many end,
|
|
}, { __call = function(_, text) return text end })
|
|
package.loaded["bookorbit_state_manager"] = {}
|
|
package.loaded["bookorbit_download_transfer"] = {}
|
|
package.loaded["bookorbit_bulk_checkpoint"] = { MAX_FAILURES = 8 }
|
|
package.loaded["bookorbit_capabilities"] = { has = function() return false end }
|
|
|
|
-- The chooser is KOReader's own directory browser; the test drives its confirm
|
|
-- callback directly rather than rendering it.
|
|
local chooser = { opened = 0, start_dir = nil, confirm = nil }
|
|
package.loaded["ui/downloadmgr"] = {
|
|
new = function(_, opts)
|
|
return {
|
|
chooseDir = function(_, start_dir)
|
|
chooser.opened = chooser.opened + 1
|
|
chooser.start_dir = start_dir
|
|
chooser.confirm = opts.onConfirm
|
|
end,
|
|
}
|
|
end,
|
|
}
|
|
|
|
-- The bulk sheet is drawn elsewhere; here it records what it was opened with
|
|
-- and offers its Folder row the way the sheet does.
|
|
local plans = {}
|
|
package.loaded["bookorbit_bulk_sheet"] = {
|
|
openPlan = function(catalog, plan)
|
|
table.insert(plans, plan)
|
|
return { catalog = catalog, plan = plan }
|
|
end,
|
|
}
|
|
|
|
package.path = "koreader-plugin/bookorbit.koplugin/?.lua;" .. package.path
|
|
|
|
local BulkDownload = require("bookorbit_catalog_bulk_download")
|
|
local CatalogDownload = require("bookorbit_catalog_download")
|
|
|
|
local function assertEqual(actual, expected, label)
|
|
if actual ~= expected then
|
|
error(string.format("%s: expected %s, got %s", label, tostring(expected), tostring(actual)))
|
|
end
|
|
end
|
|
|
|
local stored = { download_dir = "/mnt/onboard/Books" }
|
|
local saved = {}
|
|
local persisted_dir
|
|
G_reader_settings = {
|
|
readSetting = function(_, key) return stored[key] end,
|
|
saveSetting = function(_, key, value)
|
|
stored[key] = value
|
|
table.insert(saved, { key = key, value = value })
|
|
end,
|
|
flush = function() persisted_dir = stored.download_dir end,
|
|
}
|
|
|
|
local Catalog = {}
|
|
BulkDownload.install(Catalog)
|
|
CatalogDownload.install(Catalog)
|
|
Catalog.settings = {}
|
|
Catalog.client = { server_url = "http://localhost", username = "test" }
|
|
Catalog:initBulkDownloadState()
|
|
|
|
-- The bulk settings sheet offers the folder alongside the other knobs.
|
|
Catalog:showBulkDownloadSettings()
|
|
assertEqual(#plans, 1, "the settings sheet opened")
|
|
assertEqual(plans[1].settings_only, true, "it opens as settings, with nothing to download")
|
|
assertEqual(Catalog:getCurrentDownloadDir(), "/mnt/onboard/Books", "the sheet's Folder row reports the current folder")
|
|
|
|
-- Its Folder row runs the shared chooser and redraws the sheet once the
|
|
-- choice is saved.
|
|
local redrawn = 0
|
|
Catalog:chooseDownloadDir(function() redrawn = redrawn + 1 end)
|
|
assertEqual(chooser.opened, 1, "the chooser opened")
|
|
assertEqual(chooser.start_dir, "/mnt/onboard/Books", "the chooser starts at the current folder")
|
|
|
|
chooser.confirm("/mnt/onboard/Books/BookOrbit")
|
|
assertEqual(#saved, 1, "one setting was written")
|
|
assertEqual(saved[1].key, "download_dir", "the shared download_dir is what changed")
|
|
assertEqual(saved[1].value, "/mnt/onboard/Books/BookOrbit", "the chosen path was stored")
|
|
assertEqual(persisted_dir, stored.download_dir, "the chosen folder is durable before the sheet redraws")
|
|
|
|
assertEqual(#next_ticks, 1, "the sheet was scheduled to redraw")
|
|
next_ticks[1]()
|
|
assertEqual(redrawn, 1, "the sheet redraws with the new folder")
|
|
|
|
-- The same choice is what a bulk run then downloads into.
|
|
assertEqual(Catalog:getCurrentDownloadDir(), "/mnt/onboard/Books/BookOrbit", "bulk downloads follow the choice")
|
|
|
|
-- An over-long path keeps the end, which is the part that says where the files
|
|
-- actually land; truncating the other way would leave every folder looking the
|
|
-- same.
|
|
local CatalogUtil = require("bookorbit_catalog_util")
|
|
local deep = "/mnt/onboard/Books/Fiction/Science Fiction/Series/Long Name"
|
|
local short = CatalogUtil.shortPath(deep, 24)
|
|
assertEqual(#short, 24, "the label is bounded")
|
|
assertEqual(short:sub(1, 3), "...", "the truncation is marked")
|
|
assertEqual(deep:sub(-10), short:sub(-10), "the tail of the path survives")
|
|
assertEqual(CatalogUtil.shortPath("/short", 24), "/short", "a short path is left alone")
|
|
|
|
local file = assert(io.open("koreader-plugin/bookorbit.koplugin/bookorbit_main_menu.lua"))
|
|
local source = file:read("*a")
|
|
file:close()
|
|
local block = assert(source:match("(function MainMenu:chooseDownloadFolder.-)\n%-%- %-%-+ shortcut"))
|
|
local MainMenu = {}
|
|
local chunk = assert(loadstring(block))
|
|
setfenv(chunk, setmetatable({ MainMenu = MainMenu, UIManager = package.loaded["ui/uimanager"] }, { __index = _G }))
|
|
chunk()
|
|
local returned = false
|
|
MainMenu:chooseDownloadFolder(nil, function()
|
|
assertEqual(persisted_dir, "/path/to/library/downloads", "direct Settings chooser persists before returning")
|
|
returned = true
|
|
end)
|
|
chooser.confirm("/path/to/library/downloads")
|
|
assertEqual(persisted_dir, stored.download_dir, "the fallback chooser also persists immediately")
|
|
assertEqual(returned, false, "the fallback waits until the chooser closes before returning")
|
|
next_ticks[#next_ticks]()
|
|
assertEqual(returned, true, "direct Settings receives the saved folder")
|
|
|
|
print("bookorbit_download_folder_test.lua: ok")
|