diff --git a/frontend/apps/reader/modules/readertypography.lua b/frontend/apps/reader/modules/readertypography.lua index 7e263a9f6..5ad82e922 100644 --- a/frontend/apps/reader/modules/readertypography.lua +++ b/frontend/apps/reader/modules/readertypography.lua @@ -12,10 +12,14 @@ local C_ = _.pgettext local T = require("ffi/util").template local Screen = Device.screen +local ReaderTypography = InputContainer:new{} + -- This is used to migrate old hyph settings, and to show the currently -- used hyph dict language in the hyphenation menu. -- It will be completed with info from the LANGUAGES table below. -local HYPH_DICT_NAME_TO_LANG_NAME_TAG = { +-- NOTE: Actual migration is handled in ui/data/onetime_migration, +-- which is why this hash is public. +ReaderTypography.HYPH_DICT_NAME_TO_LANG_NAME_TAG = { ["@none"] = { "@none", "en" }, ["@softhyphens"] = { "@softhyphens", "en" }, ["@algorithm"] = { "@algorithm", "en" }, @@ -93,7 +97,7 @@ local LANGUAGES = { { "zu", {"zul"}, "H ", _("Zulu"), "Zulu.pattern" }, } -local DEFAULT_LANG_TAG = "en-US" -- English_US.pattern is loaded by default in crengine +ReaderTypography.DEFAULT_LANG_TAG = "en-US" -- English_US.pattern is loaded by default in crengine local LANG_TAG_TO_LANG_NAME = {} local LANG_ALIAS_TO_LANG_TAG = {} @@ -106,12 +110,10 @@ for __, v in ipairs(LANGUAGES) do end end if hyph_filename then - HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_filename] = { lang_name, lang_tag } + ReaderTypography.HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_filename] = { lang_name, lang_tag } end end -local ReaderTypography = InputContainer:new{} - function ReaderTypography:init() self.menu_table = {} self.language_submenu = {} @@ -124,44 +126,6 @@ function ReaderTypography:init() self.hyph_force_algorithmic = false self.floating_punctuation = 0 - -- Migrate old readerhyphenation settings (but keep them in case one - -- go back to a previous version) - if G_reader_settings:hasNot("text_lang_default") and G_reader_settings:hasNot("text_lang_fallback") then - local g_text_lang_set = false - local hyph_alg_default = G_reader_settings:readSetting("hyph_alg_default") - if hyph_alg_default then - local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg_default] - if dict_info then - G_reader_settings:saveSetting("text_lang_default", dict_info[2]) - g_text_lang_set = true - -- Tweak the other settings if the default hyph algo happens - -- to be one of these: - if hyph_alg_default == "@none" then - G_reader_settings:makeFalse("hyphenation") - elseif hyph_alg_default == "@softhyphens" then - G_reader_settings:makeTrue("hyph_soft_hyphens_only") - elseif hyph_alg_default == "@algorithm" then - G_reader_settings:makeTrue("hyph_force_algorithmic") - end - end - end - local hyph_alg_fallback = G_reader_settings:readSetting("hyph_alg_fallback") - if not g_text_lang_set and hyph_alg_fallback then - local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg_fallback] - if dict_info then - G_reader_settings:saveSetting("text_lang_fallback", dict_info[2]) - g_text_lang_set = true - -- We can't really tweak other settings if the hyph algo fallback - -- happens to be @none, @softhyphens, @algortihm... - end - end - if not g_text_lang_set then - -- If nothing migrated, set the fallback to DEFAULT_LANG_TAG, - -- as we'll always have one of text_lang_default/_fallback set. - G_reader_settings:saveSetting("text_lang_fallback", DEFAULT_LANG_TAG) - end - end - local info_text = _([[ Some languages have specific typographic rules: these include hyphenation, line breaking rules, and language specific glyph variants. KOReader will choose one according to the language tag from the book's metadata, but you can select another one. @@ -639,7 +603,7 @@ end function ReaderTypography:getCurrentDefaultHyphDictLanguage() local hyph_dict_name = self.ui.document:getTextMainLangDefaultHyphDictionary() - local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_dict_name] + local dict_info = self.HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_dict_name] if dict_info then hyph_dict_name = dict_info[1] else -- shouldn't happen @@ -703,7 +667,7 @@ function ReaderTypography:onReadSettings(config) -- Migrate old readerhyphenation setting, if one was set if config:hasNot("text_lang") and config:has("hyph_alg") then local hyph_alg = config:readSetting("hyph_alg") - local dict_info = HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg] + local dict_info = self.HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg] if dict_info then config:saveSetting("text_lang", dict_info[2]) -- Set the other settings if the default hyph algo happens @@ -792,7 +756,7 @@ function ReaderTypography:onReadSettings(config) else self.allow_doc_lang_tag_override = true -- None decided, use default (shouldn't be reached) - self.text_lang_tag = DEFAULT_LANG_TAG + self.text_lang_tag = self.DEFAULT_LANG_TAG logger.dbg("Typography lang: no lang set, using", self.text_lang_tag) end self.ui.document:setTextMainLang(self.text_lang_tag) diff --git a/frontend/cache.lua b/frontend/cache.lua index e7add0d23..5f075cf72 100644 --- a/frontend/cache.lua +++ b/frontend/cache.lua @@ -39,12 +39,6 @@ end local cache_path = DataStorage:getDataDir() .. "/cache/" --- NOTE: Before 2021.04, fontlist used to squat our folder, needlessly polluting our state tracking. -os.remove(cache_path .. "/fontinfo.dat") --- Ditto for Calibre -os.remove(cache_path .. "/calibre-libraries.lua") -os.remove(cache_path .. "/calibre-books.dat") - --[[ -- return a snapshot of disk cached items for subsequent check --]] @@ -160,7 +154,7 @@ function Cache:serialize() -- calculate disk cache size local cached_size = 0 local sorted_caches = {} - for _,file in pairs(self.cached) do + for _, file in pairs(self.cached) do table.insert(sorted_caches, {file=file, time=lfs.attributes(file, "access")}) cached_size = cached_size + (lfs.attributes(file, "size") or 0) end @@ -203,4 +197,9 @@ function Cache:clear() self.current_memsize = 0 end +-- Refresh the disk snapshot (mainly used by ui/data/onetime_migration) +function Cache:refreshSnapshot() + self.cached = getDiskCache() +end + return Cache diff --git a/frontend/ui/data/onetime_migration.lua b/frontend/ui/data/onetime_migration.lua new file mode 100644 index 000000000..a7b61c9bb --- /dev/null +++ b/frontend/ui/data/onetime_migration.lua @@ -0,0 +1,202 @@ +--[[ +Centralizes any and all one time migration concerns. +--]] + +local DataStorage = require("datastorage") +local lfs = require("libs/libkoreader-lfs") +local logger = require("logger") + +-- Date at which the last migration snippet was added +local CURRENT_MIGRATION_DATE = 20210413 + +-- Retrieve the date of the previous migration, if any +local last_migration_date = G_reader_settings:readSetting("last_migration_date", 0) + +-- If there's nothing new to migrate since the last time, we're done. +if last_migration_date == CURRENT_MIGRATION_DATE then + return +end + +-- Keep this in rough chronological order, with a reference to the PR that implemented the change. + +-- Global settings, https://github.com/koreader/koreader/pull/4945 & https://github.com/koreader/koreader/pull/5655 +-- Limit the check to the most recent update. ReaderUI calls this one unconditionally to update docsettings, too. +if last_migration_date < 20191129 then + logger.info("Performing one-time migration for 20191129") + + local SettingsMigration = require("ui/data/settings_migration") + SettingsMigration:migrateSettings(G_reader_settings) +end + +-- ReaderTypography, https://github.com/koreader/koreader/pull/6072 +if last_migration_date < 20200421 then + logger.info("Performing one-time migration for 20200421") + + local ReaderTypography = require("apps/reader/modules/readertypography") + -- Migrate old readerhyphenation settings + -- (but keep them in case one goes back to a previous version) + if G_reader_settings:hasNot("text_lang_default") and G_reader_settings:hasNot("text_lang_fallback") then + local g_text_lang_set = false + local hyph_alg_default = G_reader_settings:readSetting("hyph_alg_default") + if hyph_alg_default then + local dict_info = ReaderTypography.HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg_default] + if dict_info then + G_reader_settings:saveSetting("text_lang_default", dict_info[2]) + g_text_lang_set = true + -- Tweak the other settings if the default hyph algo happens to be one of these: + if hyph_alg_default == "@none" then + G_reader_settings:makeFalse("hyphenation") + elseif hyph_alg_default == "@softhyphens" then + G_reader_settings:makeTrue("hyph_soft_hyphens_only") + elseif hyph_alg_default == "@algorithm" then + G_reader_settings:makeTrue("hyph_force_algorithmic") + end + end + end + local hyph_alg_fallback = G_reader_settings:readSetting("hyph_alg_fallback") + if not g_text_lang_set and hyph_alg_fallback then + local dict_info = ReaderTypography.HYPH_DICT_NAME_TO_LANG_NAME_TAG[hyph_alg_fallback] + if dict_info then + G_reader_settings:saveSetting("text_lang_fallback", dict_info[2]) + g_text_lang_set = true + -- We can't really tweak other settings if the hyph algo fallback happens to be + -- @none, @softhyphens, @algortihm... + end + end + if not g_text_lang_set then + -- If nothing migrated, set the fallback to DEFAULT_LANG_TAG, + -- as we'll always have one of text_lang_default/_fallback set. + G_reader_settings:saveSetting("text_lang_fallback", ReaderTypography.DEFAULT_LANG_TAG) + end + end +end + +-- NOTE: ReaderRolling, on the other hand, does some lower-level things @ onReadSettings tied to CRe that would be much harder to factor out. +-- https://github.com/koreader/koreader/pull/1930 +-- NOTE: The Gestures plugin also handles its settings migration on its own, but deals with it sanely. + +-- ScreenSaver, https://github.com/koreader/koreader/pull/7371 +if last_migration_date < 20210306 then + logger.info("Performing one-time migration for 20210306 (1/2)") + + -- Migrate settings from 2021.02 or older. + if G_reader_settings:readSetting("screensaver_type") == "message" then + G_reader_settings:saveSetting("screensaver_type", "disable") + G_reader_settings:makeTrue("screensaver_show_message") + end + if G_reader_settings:has("screensaver_no_background") then + if G_reader_settings:isTrue("screensaver_no_background") then + G_reader_settings:saveSetting("screensaver_background", "none") + end + G_reader_settings:delSetting("screensaver_no_background") + end + if G_reader_settings:has("screensaver_white_background") then + if G_reader_settings:isTrue("screensaver_white_background") then + G_reader_settings:saveSetting("screensaver_background", "white") + end + G_reader_settings:delSetting("screensaver_white_background") + end +end + +-- OPDS, same as above +if last_migration_date < 20210306 then + logger.info("Performing one-time migration for 20210306 (2/2)") + + local opds_servers = G_reader_settings:readSetting("opds_servers") + if opds_servers then + -- Update deprecated URLs & remove deprecated entries + for i = #opds_servers, 1, -1 do + local server = opds_servers[i] + + if server.url == "http://bookserver.archive.org/catalog/" then + server.url = "https://bookserver.archive.org" + elseif server.url == "http://m.gutenberg.org/ebooks.opds/?format=opds" then + server.url = "https://m.gutenberg.org/ebooks.opds/?format=opds" + elseif server.url == "http://www.feedbooks.com/publicdomain/catalog.atom" then + server.url = "https://catalog.feedbooks.com/catalog/public_domain.atom" + end + + if server.title == "Gallica [Fr] [Searchable]" or server.title == "Project Gutenberg [Searchable]" then + table.remove(opds_servers, i) + end + end + G_reader_settings:saveSetting("opds_servers", opds_servers) + end +end + +-- Statistics, https://github.com/koreader/koreader/pull/7471 +if last_migration_date < 20210330 then + logger.info("Performing one-time migration for 20210330") + + -- c.f., PluginLoader + local package_path = package.path + package.path = string.format("%s/?.lua;%s", "plugins/statistics.koplugin", package_path) + local ok, ReaderStatistics = pcall(dofile, "plugins/statistics.koplugin/main.lua") + package.path = package_path + if not ok or not ReaderStatistics then + logger.warn("Error when loading plugins/statistics.koplugin/main.lua:", ReaderStatistics) + else + local settings = G_reader_settings:readSetting("statistics", ReaderStatistics.default_settings) + -- Handle a snafu in 2021.03 that could lead to an empty settings table on fresh installs. + for k, v in pairs(ReaderStatistics.default_settings) do + if settings[k] == nil then + settings[k] = v + end + end + G_reader_settings:saveSetting("statistics", settings) + end +end + +-- ScreenSaver, https://github.com/koreader/koreader/pull/7496 +if last_migration_date < 20210404 then + logger.info("Performing one-time migration for 20210404") + + -- Migrate settings from 2021.03 or older. + if G_reader_settings:has("screensaver_background") then + G_reader_settings:saveSetting("screensaver_img_background", G_reader_settings:readSetting("screensaver_background")) + G_reader_settings:delSetting("screensaver_background") + end +end + +-- Fontlist, cache migration, https://github.com/koreader/koreader/pull/7524 +if last_migration_date < 20210409 then + logger.info("Performing one-time migration for 20210409") + + -- NOTE: Before 2021.04, fontlist used to squat our folder, needlessly polluting our state tracking. + local cache_path = DataStorage:getDataDir() .. "/cache" + local new_path = cache_path .. "/fontlist" + lfs.mkdir(new_path) + local ok, err = os.rename(cache_path .. "/fontinfo.dat", new_path .. "/fontinfo.dat") + if not ok then + logger.warn("os.rename:", err) + end + + -- Make sure Cache gets the memo + local Cache = require("cache") + Cache:refreshSnapshot() +end + +-- Calibre, cache migration, https://github.com/koreader/koreader/pull/7528 +if last_migration_date < 20210412 then + logger.info("Performing one-time migration for 20210412") + + -- Ditto for Calibre + local cache_path = DataStorage:getDataDir() .. "/cache" + local new_path = cache_path .. "/calibre" + lfs.mkdir(new_path) + local ok, err = os.rename(cache_path .. "/calibre-libraries.lua", new_path .. "/libraries.lua") + if not ok then + logger.warn("os.rename:", err) + end + ok, err = os.rename(cache_path .. "/calibre-books.dat", new_path .. "/books.dat") + if not ok then + logger.warn("os.rename:", err) + end + + -- Make sure Cache gets the memo + local Cache = require("cache") + Cache:refreshSnapshot() +end + +-- We're done, store the current migration date +G_reader_settings:saveSetting("last_migration_date", CURRENT_MIGRATION_DATE) diff --git a/frontend/ui/data/settings_migration.lua b/frontend/ui/data/settings_migration.lua index b4bbf9827..d36444259 100644 --- a/frontend/ui/data/settings_migration.lua +++ b/frontend/ui/data/settings_migration.lua @@ -24,7 +24,7 @@ function SettingsMigration:migrateSettings(config) return end - -- Fine-grained CRe margins (#4945) + -- Fine-grained CRe margins (https://github.com/koreader/koreader/pull/4945) if config:has("copt_page_margins") then local old_margins = config:readSetting("copt_page_margins") logger.info("Migrating old", cfg_class, "CRe margin settings: L", old_margins[1], "T", old_margins[2], "R", old_margins[3], "B", old_margins[4]) @@ -36,7 +36,7 @@ function SettingsMigration:migrateSettings(config) config:delSetting("copt_page_margins") end - -- Space condensing to Word spacing + -- Space condensing to Word spacing (https://github.com/koreader/koreader/pull/5655) -- From a single number (space condensing) to a table of 2 numbers ({space width scale, space condensing}). -- Be conservative and don't change space width scale: use 100% if config:hasNot("copt_word_spacing") and config:has("copt_space_condensing") then diff --git a/frontend/ui/screensaver.lua b/frontend/ui/screensaver.lua index a6d9c0bcf..6177916ea 100644 --- a/frontend/ui/screensaver.lua +++ b/frontend/ui/screensaver.lua @@ -23,29 +23,6 @@ local _ = require("gettext") local Screen = Device.screen local T = require("ffi/util").template --- Migrate settings from 2021.02 or older. -if G_reader_settings:readSetting("screensaver_type") == "message" then - G_reader_settings:saveSetting("screensaver_type", "disable") - G_reader_settings:makeTrue("screensaver_show_message") -end -if G_reader_settings:has("screensaver_no_background") then - if G_reader_settings:isTrue("screensaver_no_background") then - G_reader_settings:saveSetting("screensaver_background", "none") - end - G_reader_settings:delSetting("screensaver_no_background") -end -if G_reader_settings:has("screensaver_white_background") then - if G_reader_settings:isTrue("screensaver_white_background") then - G_reader_settings:saveSetting("screensaver_background", "white") - end - G_reader_settings:delSetting("screensaver_white_background") -end --- Migrate settings from 2021.03 or older. -if G_reader_settings:has("screensaver_background") then - G_reader_settings:saveSetting("screensaver_img_background", G_reader_settings:readSetting("screensaver_background")) - G_reader_settings:delSetting("screensaver_background") -end - -- Default settings if G_reader_settings:hasNot("screensaver_show_message") then G_reader_settings:makeFalse("screensaver_show_message") diff --git a/frontend/version.lua b/frontend/version.lua index f07597d62..702949c2f 100644 --- a/frontend/version.lua +++ b/frontend/version.lua @@ -67,4 +67,22 @@ function Version:getShortVersion() return self.short end +--- Returns the release date of the current version of KOReader, YYYYmmdd, in UTC. +--- Technically closer to the build date, but close enough where official builds are concerned ;). +-- @treturn int date +function Version:getBuildDate() + if not self.date then + local lfs = require("libs/libkoreader-lfs") + local mtime = lfs.attributes("git-rev", "modification") + if mtime then + local ts = os.date("!%Y%m%d", mtime) + self.date = tonumber(ts) or 0 + else + -- No git-rev file? + self.date = 0 + end + end + return self.date +end + return Version diff --git a/plugins/opds.koplugin/opdsbrowser.lua b/plugins/opds.koplugin/opdsbrowser.lua index 3e737f9c0..c36b97905 100644 --- a/plugins/opds.koplugin/opdsbrowser.lua +++ b/plugins/opds.koplugin/opdsbrowser.lua @@ -80,13 +80,6 @@ local OPDSBrowser = Menu:extend{ } function OPDSBrowser:init() - -- Update deprecated URLs - for _, server in ipairs(self.opds_servers) do - if server.url == "http://bookserver.archive.org/catalog/" then - server.url = "https://bookserver.archive.org" - end - end - self.item_table = self:genItemTableFromRoot() self.catalog_title = nil Menu.init(self) -- call parent's init() diff --git a/plugins/statistics.koplugin/main.lua b/plugins/statistics.koplugin/main.lua index 9dfdfdd0b..d2f9d208a 100644 --- a/plugins/statistics.koplugin/main.lua +++ b/plugins/statistics.koplugin/main.lua @@ -125,6 +125,19 @@ function ReaderStatistics:isDocless() return self.ui == nil or self.ui.document == nil end +-- NOTE: This is used in a migration script by ui/data/onetime_migration, +-- which is why it's public. +ReaderStatistics.default_settings = { + min_sec = DEFAULT_MIN_READ_SEC, + max_sec = DEFAULT_MAX_READ_SEC, + is_enabled = true, + convert_to_db = nil, + calendar_start_day_of_week = DEFAULT_CALENDAR_START_DAY_OF_WEEK, + calendar_nb_book_spans = DEFAULT_CALENDAR_NB_BOOK_SPANS, + calendar_show_histogram = true, + calendar_browse_future_months = false, +} + function ReaderStatistics:init() if not self:isDocless() and self.ui.document.is_pic then return @@ -132,23 +145,7 @@ function ReaderStatistics:init() self.start_current_period = os.time() self:resetVolatileStats() - local default_settings = { - min_sec = DEFAULT_MIN_READ_SEC, - max_sec = DEFAULT_MAX_READ_SEC, - is_enabled = true, - convert_to_db = nil, - calendar_start_day_of_week = DEFAULT_CALENDAR_START_DAY_OF_WEEK, - calendar_nb_book_spans = DEFAULT_CALENDAR_NB_BOOK_SPANS, - calendar_show_histogram = true, - calendar_browse_future_months = false, - } - self.settings = G_reader_settings:readSetting("statistics", default_settings) - -- Handle a snafu in 2021.03 that could lead to an empty settings table on fresh installs. - for k, v in pairs(default_settings) do - if self.settings[k] == nil then - self.settings[k] = v - end - end + self.settings = G_reader_settings:readSetting("statistics", self.default_settings) self.ui.menu:registerToMainMenu(self) self:checkInitDatabase() diff --git a/reader.lua b/reader.lua index 0f97da2bb..88b2fe225 100755 --- a/reader.lua +++ b/reader.lua @@ -172,14 +172,13 @@ if Device:hasEinkScreen() then end end --- Handle global settings migration -local SettingsMigration = require("ui/data/settings_migration") -SettingsMigration:migrateSettings(G_reader_settings) - -- Document renderers canvas local CanvasContext = require("document/canvascontext") CanvasContext:init(Device) +-- Handle one time migration stuff (settings, deprecation, ...) in case of an upgrade... +require("ui/data/onetime_migration") + -- Touch screen (this may display some widget, on first install on Kobo Touch, -- so have it done after CanvasContext:init() but before Bidi.setup() to not -- have mirroring mess x/y probing).