From 908151a3b0fbbe15e2228f04ca01163ebcdbbeca Mon Sep 17 00:00:00 2001 From: poire-z Date: Wed, 1 Jan 2020 12:27:51 +0100 Subject: [PATCH] [feat] Adds Document> Auto-save book metadata sub-menu (#5687) Replaces DAUTO_SAVE_PAGING_COUNT in defaults.lua with a new option available in menu, that allows setting an interval in minutes instead of a page count. --- .luacheckrc | 1 - defaults.lua | 3 +- frontend/apps/reader/modules/readerview.lua | 47 +++++++------ .../elements/common_settings_menu_table.lua | 67 +++++++++++++++++++ plugins/kosync.koplugin/main.lua | 14 +++- 5 files changed, 107 insertions(+), 25 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index ca28814b3..528d81f86 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -111,7 +111,6 @@ read_globals = { "DMINIBAR_CONTAINER_HEIGHT", "DMINIBAR_FONT_SIZE", "DGESDETECT_DISABLE_DOUBLE_TAP", - "DAUTO_SAVE_PAGING_COUNT", "FRONTLIGHT_SENSITIVITY_DECREASE", "DALPHA_SORT_CASE_INSENSITIVE", "SEARCH_CASESENSITIVE", diff --git a/defaults.lua b/defaults.lua index 9fccd15db..8efae163e 100644 --- a/defaults.lua +++ b/defaults.lua @@ -197,7 +197,8 @@ DMINIBAR_FONT_SIZE = 14 --DMINIBAR_HEIGHT = 7 -- Should be smaller than DMINIBAR_CONTAINER_HEIGHT -- change this to any numerical value if you want to automatically save settings when turning pages -DAUTO_SAVE_PAGING_COUNT = nil +-- no longer needed (now available in menu as an interval in minutes) +-- DAUTO_SAVE_PAGING_COUNT = nil -- dictionary font size -- no longer needed diff --git a/frontend/apps/reader/modules/readerview.lua b/frontend/apps/reader/modules/readerview.lua index 32b38aca1..8fcd5106c 100644 --- a/frontend/apps/reader/modules/readerview.lua +++ b/frontend/apps/reader/modules/readerview.lua @@ -76,10 +76,8 @@ local ReaderView = OverlapGroup:extend{ dogear_visible = false, -- in flipping state flipping_visible = false, - - -- auto save settings after turning pages - auto_save_paging_count = 0, - autoSaveSettings = function()end + -- to ensure periodic flush of settings + settings_last_save_ts = nil, } function ReaderView:init() @@ -788,14 +786,14 @@ function ReaderView:onPageUpdate(new_page_no) self.state.page = new_page_no self:recalculate() self.highlight.temp = {} - UIManager:nextTick(self.autoSaveSettings) + self:checkAutoSaveSettings() end function ReaderView:onPosUpdate(new_pos) self.state.pos = new_pos self:recalculate() self.highlight.temp = {} - UIManager:nextTick(self.autoSaveSettings) + self:checkAutoSaveSettings() end function ReaderView:onZoomUpdate(zoom) @@ -921,20 +919,29 @@ function ReaderView:onCloseDocument() end function ReaderView:onReaderReady() - if DAUTO_SAVE_PAGING_COUNT ~= nil then - if DAUTO_SAVE_PAGING_COUNT <= 0 then - self.autoSaveSettings = function() - self.ui:saveSettings() - end - else - self.autoSaveSettings = function() - self.auto_save_paging_count = self.auto_save_paging_count + 1 - if self.auto_save_paging_count == DAUTO_SAVE_PAGING_COUNT then - self.ui:saveSettings() - self.auto_save_paging_count = 0 - end - end - end + self.settings_last_save_ts = os.time() +end + +function ReaderView:onResume() + -- As settings were saved on suspend, reset this on resume, + -- as there's no need for a possibly immediate save. + self.settings_last_save_ts = os.time() +end + +function ReaderView:checkAutoSaveSettings() + if not self.settings_last_save_ts then -- reader not yet ready + return + end + local interval = G_reader_settings:readSetting("auto_save_settings_interval_minutes") + if not interval then -- no auto save + return + end + if os.time() - self.settings_last_save_ts >= interval*60 then + self.settings_last_save_ts = os.time() + UIManager:nextTick(function() + self.ui:saveSettings() + self.settings_last_save_ts = os.time() -- re-set when saving done + end) end end diff --git a/frontend/ui/elements/common_settings_menu_table.lua b/frontend/ui/elements/common_settings_menu_table.lua index 2a5e375f0..c553cd74b 100644 --- a/frontend/ui/elements/common_settings_menu_table.lua +++ b/frontend/ui/elements/common_settings_menu_table.lua @@ -345,9 +345,76 @@ if Device:hasKeys() then } end +-- Auto-save settings: default value, info text and warning, and menu items +if G_reader_settings:readSetting("auto_save_settings_interval_minutes") == nil then + -- Default to auto save every 15 mn + G_reader_settings:saveSetting("auto_save_settings_interval_minutes", 15) +end + +local auto_save_help_text = _([[ +This sets how often to rewrite to disk global settings and book metadata, including your current position and any highlights and bookmarks made, when you're reading a document. + +The normal behavior is to save those only when the document is closed, or your device suspended, or when exiting KOReader. + +Setting it to some interval may help prevent losing new settings/sidecar data after a software crash, but will cause more I/O writes the lower the interval is, and may slowly wear out your storage media in the long run.]]) + +-- Some devices with FAT32 storage may not like having settings rewritten too often, +-- so let that be known. See https://github.com/koreader/koreader/pull/3625 +local warn_about_auto_save = Device:isKobo() or Device:isKindle() or Device:isCervantes() or Device:isPocketBook() or Device:isSonyPRSTUX() +if warn_about_auto_save then + local auto_save_help_warning = _([[Please be warned that on this device, setting a low interval may exacerbate the potential for filesystem corruption and complete data loss after a hardware crash.]]) + auto_save_help_text = auto_save_help_text .. "\n\n" .. auto_save_help_warning +end + +local function genAutoSaveMenuItem(value) + local setting_name = "auto_save_settings_interval_minutes" + local text + if not value then + text = _("Only on close, suspend and exit") + else + text = T(_("Every %1 mn"), value) + end + return { + text = text, + help_text = auto_save_help_text, + checked_func = function() + return G_reader_settings:readSetting(setting_name) == value + end, + callback = function() + G_reader_settings:saveSetting(setting_name, value) + end, + } +end + common_settings.document = { text = _("Document"), sub_item_table = { + { + text_func = function() + local interval = G_reader_settings:readSetting("auto_save_settings_interval_minutes") + local s_interval + if interval == false then + s_interval = "only on close" + else + s_interval = T(_("every %1 mn"), interval) + end + return T(_("Auto-save book metadata: %1"), s_interval) + end, + help_text = auto_save_help_text, + sub_item_table = { + genAutoSaveMenuItem(false), + genAutoSaveMenuItem(5), + genAutoSaveMenuItem(15), + genAutoSaveMenuItem(60), + warn_about_auto_save and { + text = _("Important info about this auto-save option"), + keep_menu_open = true, + callback = function() + UIManager:show(InfoMessage:new{ text = auto_save_help_text, }) + end, + } or nil, + }, + }, { text = _("Save document (write highlights into PDF)"), sub_item_table = { diff --git a/plugins/kosync.koplugin/main.lua b/plugins/kosync.koplugin/main.lua index 81d46b566..be047ab8b 100644 --- a/plugins/kosync.koplugin/main.lua +++ b/plugins/kosync.koplugin/main.lua @@ -18,6 +18,14 @@ if not G_reader_settings:readSetting("device_id") then G_reader_settings:saveSetting("device_id", random.uuid()) end +-- DAUTO_SAVE_PAGING_COUNT was set to nil in defaults.lua, but +-- could be overriden in defaults.persistent.lua with a value +-- that was also used here as the interval for auto sync. +-- DAUTO_SAVE_PAGING_COUNT has been removed, but let's allow +-- this plugin to still pick it from defaults.persistent.lua. +--- @todo make this tunable via an added menu item below +local SYNC_PAGING_COUNT = DAUTO_SAVE_PAGING_COUNT -- luacheck: ignore + local KOSync = InputContainer:new{ name = "kosync", is_doc_only = true, @@ -616,9 +624,9 @@ function KOSync:_onPageUpdate(page) self.last_page = page self.last_page_turn_ticks = os.time() self.page_update_times = self.page_update_times + 1 - if DAUTO_SAVE_PAGING_COUNT ~= nil - and (DAUTO_SAVE_PAGING_COUNT <= 0 - or self.page_update_times == DAUTO_SAVE_PAGING_COUNT) then + if SYNC_PAGING_COUNT ~= nil + and (SYNC_PAGING_COUNT <= 0 + or self.page_update_times == SYNC_PAGING_COUNT) then self.page_update_times = 0 UIManager:scheduleIn(1, function() self:updateProgress() end) end