From 30378eb2a82ac1b2f686b0db638b194b642af4ab Mon Sep 17 00:00:00 2001 From: Hzj_jie Date: Tue, 16 May 2017 02:11:11 -0700 Subject: [PATCH] Add restart koreader function and ensure FlushSettings event can be delivered to all widgets (#2772) --- frontend/apps/filemanager/filemanager.lua | 3 +- frontend/apps/filemanager/filemanagermenu.lua | 47 +++++++--- frontend/apps/reader/modules/readermenu.lua | 28 ++++-- frontend/apps/reader/readerui.lua | 2 - frontend/dbg.lua | 2 + frontend/device/generic/device.lua | 4 - frontend/device/kindle/device.lua | 2 - .../ui/elements/filemanager_menu_order.lua | 1 + frontend/ui/elements/reader_menu_order.lua | 1 + frontend/ui/uimanager.lua | 91 +++++++++++++++---- frontend/ui/widget/confirmbox.lua | 51 +++++++---- frontend/ui/widget/eventlistener.lua | 4 - kodev | 9 +- platform/kindle/koreader.sh | 9 +- platform/kobo/koreader.sh | 9 +- platform/pocketbook/koreader.app | 8 +- platform/ubuntu-touch/koreader.sh | 9 +- plugins/batterystat.koplugin/main.lua | 63 ++++++++++--- plugins/kosync.koplugin/main.lua | 10 +- reader.lua | 14 ++- spec/unit/readerfooter_spec.lua | 1 + spec/unit/readerhighlight_spec.lua | 4 + spec/unit/readerpaging_spec.lua | 8 +- spec/unit/readertoc_spec.lua | 2 + spec/unit/uimanager_spec.lua | 1 + 25 files changed, 279 insertions(+), 104 deletions(-) diff --git a/frontend/apps/filemanager/filemanager.lua b/frontend/apps/filemanager/filemanager.lua index f3cb6f63f..0540963e2 100644 --- a/frontend/apps/filemanager/filemanager.lua +++ b/frontend/apps/filemanager/filemanager.lua @@ -325,7 +325,6 @@ function FileManager:init() table.insert(self, ReaderDictionary:new{ ui = self }) table.insert(self, ReaderWikipedia:new{ ui = self }) - self.loaded_modules = {} -- koreader plugins for _,plugin_module in ipairs(PluginLoader:loadPlugins()) do if not plugin_module.is_doc_only then @@ -333,7 +332,7 @@ function FileManager:init() plugin_module, { ui = self, }) -- Keep references to the modules which do not register into menu. if ok then - table.insert(self.loaded_modules, plugin_or_err) + table.insert(self, plugin_or_err) logger.info("FM loaded plugin", plugin_module.name, "at", plugin_module.path) end diff --git a/frontend/apps/filemanager/filemanagermenu.lua b/frontend/apps/filemanager/filemanagermenu.lua index cfb9bf498..f8bcbcc29 100644 --- a/frontend/apps/filemanager/filemanagermenu.lua +++ b/frontend/apps/filemanager/filemanagermenu.lua @@ -269,18 +269,13 @@ function FileManagerMenu:setUpdateItemTable() self.menu_items.exit = { text = _("Exit"), callback = function() - if SetDefaults.settings_changed then - SetDefaults.settings_changed = false - UIManager:show(ConfirmBox:new{ - text = _("You have unsaved default settings. Save them now?"), - ok_callback = function() - SetDefaults:saveSettings() - end, - }) - else - UIManager:close(self.menu_container) - self.ui:onClose() - end + self:exitOrRestart() + end, + } + self.menu_items.restart_koreader = { + text = _("Restart KOReader"), + callback = function() + self:exitOrRestart(function() UIManager:restartKOReader() end) end, } @@ -298,6 +293,34 @@ dbg:guard(FileManagerMenu, 'setUpdateItemTable', end end) +function FileManagerMenu:exitOrRestart(callback) + if SetDefaults.settings_changed then + UIManager:show(ConfirmBox:new{ + text = _("You have unsaved default settings. Save them now?\nTap \"Cancel\" to return to KOReader."), + ok_text = _("Save"), + ok_callback = function() + SetDefaults.settings_changed = false + SetDefaults:saveSettings() + self:exitOrRestart(callback) + end, + cancel_text = _("Don't save"), + cancel_callback = function() + SetDefaults.settings_changed = false + self:exitOrRestart(callback) + end, + other_buttons = {{ + text = _("Cancel"), + }} + }) + else + UIManager:close(self.menu_container) + self.ui:onClose() + if callback then + callback() + end + end +end + function FileManagerMenu:onShowMenu() local tab_index = G_reader_settings:readSetting("filemanagermenu_tab_index") or 1 if self.tab_item_table == nil then diff --git a/frontend/apps/reader/modules/readermenu.lua b/frontend/apps/reader/modules/readermenu.lua index aad7f5e2d..88f8c8b6a 100644 --- a/frontend/apps/reader/modules/readermenu.lua +++ b/frontend/apps/reader/modules/readermenu.lua @@ -186,12 +186,14 @@ function ReaderMenu:setUpdateItemTable() self.menu_items.exit = { text = _("Exit"), callback = function() - self:onTapCloseMenu() - UIManager:scheduleIn(0.1, function() self.ui:onClose() end) - local FileManager = require("apps/filemanager/filemanager") - if FileManager.instance then - FileManager.instance:onClose() - end + self:exitOrRestart() + end, + } + + self.menu_items.restart_koreader = { + text = _("Restart KOReader"), + callback = function() + self:exitOrRestart(function() UIManager:restartKOReader() end) end, } @@ -209,6 +211,20 @@ dbg:guard(ReaderMenu, 'setUpdateItemTable', end end) +function ReaderMenu:exitOrRestart(callback) + self:onTapCloseMenu() + UIManager:nextTick(function() + self.ui:onClose() + if callback ~= nil then + callback() + end + end) + local FileManager = require("apps/filemanager/filemanager") + if FileManager.instance then + FileManager.instance:onClose() + end +end + function ReaderMenu:onShowReaderMenu() if self.tab_item_table == nil then self:setUpdateItemTable() diff --git a/frontend/apps/reader/readerui.lua b/frontend/apps/reader/readerui.lua index f9c1ccfb6..5c8916dfd 100644 --- a/frontend/apps/reader/readerui.lua +++ b/frontend/apps/reader/readerui.lua @@ -481,7 +481,6 @@ end function ReaderUI:onFlushSettings() self:saveSettings() - return true end function ReaderUI:closeDocument() @@ -530,7 +529,6 @@ function ReaderUI:onClose() if _running_instance == self then _running_instance = nil end - return true end return ReaderUI diff --git a/frontend/dbg.lua b/frontend/dbg.lua index 15d71e36a..ff328695b 100644 --- a/frontend/dbg.lua +++ b/frontend/dbg.lua @@ -47,6 +47,7 @@ function Dbg:turnOn() return unpack(values) end end + Dbg.dassert = function(check, msg) assert(check, msg) end -- TODO: close ev.log fd for children -- create or clear ev log file @@ -59,6 +60,7 @@ function Dbg:turnOff() logger:setLevel(logger.levels.info) function Dbg_mt.__call() end function Dbg.guard() end + function Dbg.dassert() end if self.ev_log then io.close(self.ev_log) self.ev_log = nil diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index b61c5784e..52c5a4ca2 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -1,4 +1,3 @@ -local Event = require("ui/event") local logger = require("logger") local _ = require("gettext") @@ -125,9 +124,6 @@ function Device:onPowerEvent(ev) elseif ev == "Power" or ev == "Suspend" then self.powerd:beforeSuspend() local UIManager = require("ui/uimanager") - -- flushing settings first in case the screensaver takes too long time - -- that flushing has no chance to run - UIManager:broadcastEvent(Event:new("FlushSettings")) logger.dbg("Suspending...") -- always suspend in portrait mode self.orig_rotation_mode = self.screen:getRotationMode() diff --git a/frontend/device/kindle/device.lua b/frontend/device/kindle/device.lua index 725caf14f..07b15c05a 100644 --- a/frontend/device/kindle/device.lua +++ b/frontend/device/kindle/device.lua @@ -1,6 +1,5 @@ local Generic = require("device/generic/device") local util = require("ffi/util") -local Event = require("ui/event") local logger = require("logger") local function yes() return true end @@ -93,7 +92,6 @@ function Kindle:intoScreenSaver() os.execute("killall -cont awesome") end end - require("ui/uimanager"):broadcastEvent(Event:new("FlushSettings")) end function Kindle:outofScreenSaver() diff --git a/frontend/ui/elements/filemanager_menu_order.lua b/frontend/ui/elements/filemanager_menu_order.lua index 10f9572a0..ddf812de8 100644 --- a/frontend/ui/elements/filemanager_menu_order.lua +++ b/frontend/ui/elements/filemanager_menu_order.lua @@ -63,6 +63,7 @@ local order = { "help", "system_statistics", "----------------------------", + "restart_koreader", "poweroff", -- if Device:isKobo() "reboot", -- if Device:isKobo() "----------------------------", diff --git a/frontend/ui/elements/reader_menu_order.lua b/frontend/ui/elements/reader_menu_order.lua index e8c5e7bd6..d7f322949 100644 --- a/frontend/ui/elements/reader_menu_order.lua +++ b/frontend/ui/elements/reader_menu_order.lua @@ -81,6 +81,7 @@ local order = { "help", "system_statistics", "----------------------------", + "restart_koreader", "poweroff", -- if Device:isKobo() "reboot", -- if Device:isKobo() "----------------------------", diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index dabe55009..0da45eda9 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -33,6 +33,7 @@ local UIManager = { _refresh_stack = {}, _refresh_func_stack = {}, _entered_poweroff_stage = false, + _exit_code = nil, } function UIManager:init() @@ -41,7 +42,7 @@ function UIManager:init() self:sendEvent(input_event) end, SaveState = function() - self:broadcastEvent(Event:new("FlushSettings")) + self:flushSettings() end, Power = function(input_event) Device:onPowerEvent(input_event) @@ -73,6 +74,7 @@ function UIManager:init() -- resume. self:_initAutoSuspend() self.event_handlers["Suspend"] = function() + self:_beforeSuspend() if self._stopAutoSuspend then -- TODO(Hzj-jie): Why _stopAutoSuspend could be nil in test cases. --[[ @@ -87,13 +89,12 @@ function UIManager:init() --]] self:_stopAutoSuspend() end - self:broadcastEvent(Event:new("Suspend")) Device:onPowerEvent("Suspend") end self.event_handlers["Resume"] = function() Device:onPowerEvent("Resume") - self:broadcastEvent(Event:new("Resume")) self:_startAutoSuspend() + self:_afterResume() end self.event_handlers["PowerPress"] = function() UIManager:scheduleIn(2, self.poweroff_action) @@ -101,24 +102,24 @@ function UIManager:init() self.event_handlers["PowerRelease"] = function() if not self._entered_poweroff_stage then UIManager:unschedule(self.poweroff_action) - self.event_handlers["Suspend"]() + self:suspend() end end if not G_reader_settings:readSetting("ignore_power_sleepcover") then self.event_handlers["SleepCoverClosed"] = function() Device.is_cover_closed = true - self.event_handlers["Suspend"]() + self:suspend() end self.event_handlers["SleepCoverOpened"] = function() Device.is_cover_closed = false - self.event_handlers["Resume"]() + self:resume() end else -- Closing/opening the cover will still wake up the device, so we -- need to put it back to sleep if we are in screen saver mode self.event_handlers["SleepCoverClosed"] = function() if Device.screen_saver_mode then - self.event_handlers["Suspend"]() + self:suspend() end end self.event_handlers["SleepCoverOpened"] = self.event_handlers["SleepCoverClosed"] @@ -127,15 +128,16 @@ function UIManager:init() Device:getPowerDevice():toggleFrontlight() end self.event_handlers["Charging"] = function() - self:broadcastEvent(Event:new("Charging")) + self:_beforeCharging() if Device.screen_saver_mode then - self.event_handlers["Suspend"]() + self:suspend() end end self.event_handlers["NotCharging"] = function() - self:broadcastEvent(Event:new("NotCharging")) + -- We need to put the device into suspension, other things need to be done before it. + self:_afterNotCharging() if Device.screen_saver_mode then - self.event_handlers["Suspend"]() + self:suspend() end end self.event_handlers["__default__"] = function(input_event) @@ -143,27 +145,27 @@ function UIManager:init() -- Suspension in Kobo can be interrupted by screen updates. We -- ignore user touch input here so screen udpate won't be -- triggered in suspend mode - self.event_handlers["Suspend"]() + self:suspend() else self:sendEvent(input_event) end end elseif Device:isKindle() then self.event_handlers["IntoSS"] = function() - self:broadcastEvent(Event:new("Suspend")) + self:_beforeSuspend() Device:intoScreenSaver() end self.event_handlers["OutOfSS"] = function() Device:outofScreenSaver() - self:broadcastEvent(Event:new("Resume")) + self:_afterResume(); end self.event_handlers["Charging"] = function() - self:broadcastEvent(Event:new("Charging")) + self:_beforeCharging() Device:usbPlugIn() end self.event_handlers["NotCharging"] = function() Device:usbPlugOut() - self:broadcastEvent(Event:new("NotCharging")) + self:_afterNotCharging() end end end @@ -226,6 +228,8 @@ function UIManager:close(widget, refreshtype, refreshregion) end logger.dbg("close widget", widget.id or widget.name) local dirty = false + -- Ensure all the widgets can get onFlushSettings event. + widget:handleEvent(Event:new("FlushSettings")) -- first send close event to widget widget:handleEvent(Event:new("CloseWidget")) -- make it disabled by default and check any widget that enables it @@ -412,6 +416,7 @@ end --- Signals to quit. function UIManager:quit() + if not self._running then return end logger.info("quitting uimanager") self._task_queue_dirty = false self._running = false @@ -765,12 +770,14 @@ function UIManager:run() self.looper:add_callback(function() self:handleInput() end) self.looper:start() end + + return self._exit_code end -- run uimanager forever for testing purpose function UIManager:runForever() self._run_forever = true - self:run() + return self:run() end -- Kobo does not have an auto suspend function, so we implement it ourselves. @@ -792,7 +799,7 @@ function UIManager:_initAutoSuspend() local now = os.time() -- Do not repeat auto suspend procedure after suspend. if self.last_action_sec + self.auto_suspend_sec <= now then - self.event_handlers["Suspend"]() + self:suspend() else self:scheduleIn( self.last_action_sec + self.auto_suspend_sec - now, @@ -824,6 +831,54 @@ function UIManager:_initAutoSuspend() end end +-- The common operations should be performed before suspending the device. Ditto. +function UIManager:_beforeSuspend() + self:flushSettings() + self:broadcastEvent(Event:new("Suspend")) +end + +-- The common operations should be performed after resuming the device. Ditto. +function UIManager:_afterResume() + self:broadcastEvent(Event:new("Resume")) +end + +function UIManager:_beforeCharging() + self:broadcastEvent(Event:new("Charging")) +end + +function UIManager:_afterNotCharging() + self:broadcastEvent(Event:new("NotCharging")) +end + +-- Executes all the operations of a suspending request. This function usually puts the device into +-- suspension. +function UIManager:suspend() + if Device:isKobo() then + self.event_handlers["Suspend"]() + elseif Device:isKindle() then + self.event_handlers["IntoSS"]() + end +end + +-- Executes all the operations of a resume request. This function usually wakes up the device. +function UIManager:resume() + if Device:isKobo() then + self.event_handlers["Resume"]() + elseif Device:isKindle() then + self.event_handlers["OutOfSS"]() + end +end + +function UIManager:flushSettings() + self:broadcastEvent(Event:new("FlushSettings")) +end + +function UIManager:restartKOReader() + self:quit() + -- This is just a magic number to indicate the restart request for shell scripts. + self._exit_code = 85 +end + UIManager._resetAutoSuspendTimer = noop UIManager:init() diff --git a/frontend/ui/widget/confirmbox.lua b/frontend/ui/widget/confirmbox.lua index b393cd3c6..00ae2d277 100644 --- a/frontend/ui/widget/confirmbox.lua +++ b/frontend/ui/widget/confirmbox.lua @@ -44,6 +44,7 @@ local ConfirmBox = InputContainer:new{ cancel_text = _("Cancel"), ok_callback = function() end, cancel_callback = function() end, + other_buttons = nil, margin = 5, padding = 5, } @@ -78,28 +79,42 @@ function ConfirmBox:init() width = Screen:getWidth()*2/3, } } + + local buttons = {{ + text = self.cancel_text, + callback = function() + self.cancel_callback() + UIManager:close(self) + end, + }, { + text = self.ok_text, + callback = function() + self.ok_callback() + UIManager:close(self) + end, + },} + + if self.other_buttons ~= nil then + for __, button in ipairs(self.other_buttons) do + assert(type(button.text) == "string") + assert(button.callback == nil or type(button.callback) == "function") + table.insert(buttons, { + text = button.text, + callback = function() + if button.callback ~= nil then + button.callback() + end + UIManager:close(self) + end, + }) + end + end + local button_table = ButtonTable:new{ width = content:getSize().w, button_font_face = "cfont", button_font_size = 20, - buttons = { - { - { - text = self.cancel_text, - callback = function() - self.cancel_callback() - UIManager:close(self) - end, - }, - { - text = self.ok_text, - callback = function() - self.ok_callback() - UIManager:close(self) - end, - }, - }, - }, + buttons = { buttons }, zero_sep = true, show_parent = self, } diff --git a/frontend/ui/widget/eventlistener.lua b/frontend/ui/widget/eventlistener.lua index 2f0035f56..ff41ae580 100644 --- a/frontend/ui/widget/eventlistener.lua +++ b/frontend/ui/widget/eventlistener.lua @@ -8,7 +8,6 @@ will call a method "onEventName" for an event with name ]] local EventListener = {} -local DEBUG = require("dbg") function EventListener:new(new_o) local o = new_o or {} @@ -29,9 +28,6 @@ By default, it's `"on"..Event.name`. ]] function EventListener:handleEvent(event) if self[event.handler] then - if self.id or self.name then - DEBUG:v(self.id or self.name, "handling event", event) - end return self[event.handler](self, unpack(event.args)) end end diff --git a/kodev b/kodev index 8576bd7bf..bc233844b 100755 --- a/kodev +++ b/kodev @@ -366,8 +366,12 @@ OPTIONS: [[ $args != /* ]] && args="${CURDIR}/${args}" fi - EMULATE_READER_W=${screen_width} EMULATE_READER_H=${screen_height} \ - ./reader.lua -d "$args" + RETURN_VALUE=85 + while [ $RETURN_VALUE -eq 85 ]; do + EMULATE_READER_W=${screen_width} EMULATE_READER_H=${screen_height} \ + ./reader.lua -d "$args" + RETURN_VALUE=$? + done } || exit popd } @@ -417,6 +421,7 @@ OPTIONS: make "${EMU_DIR}/.busted" pushd "${EMU_DIR}" && { test_path="./spec/$1/unit" + rm -rf "${test_path}"/data/*.sdr if [ ! -z "$2" ]; then test_path="${test_path}/$2" diff --git a/platform/kindle/koreader.sh b/platform/kindle/koreader.sh index 3d79bd533..733a21e5a 100755 --- a/platform/kindle/koreader.sh +++ b/platform/kindle/koreader.sh @@ -255,7 +255,12 @@ if [ -e crash.log ]; then tail -c 500000 crash.log >crash.log.new mv -f crash.log.new crash.log fi -./reader.lua "$@" >>crash.log 2>&1 + +RETURN_VALUE=85 +while [ $RETURN_VALUE -eq 85 ]; do + ./reader.lua "$@" >>crash.log 2>&1 + RETURN_VALUE=$? +done # clean up our own process tree in case the reader crashed (if needed, to avoid flooding KUAL's log) if pidof reader.lua >/dev/null 2>&1; then @@ -345,3 +350,5 @@ if [ "${PASSCODE_DISABLED}" = "yes" ]; then logmsg "Restoring system passcode . . ." touch "/var/local/system/userpasswdenabled" fi + +exit $RETURN_VALUE diff --git a/platform/kobo/koreader.sh b/platform/kobo/koreader.sh index 09d67339a..fe95c1944 100755 --- a/platform/kobo/koreader.sh +++ b/platform/kobo/koreader.sh @@ -119,8 +119,11 @@ if [ -e crash.log ]; then mv -f crash.log.new crash.log fi -./reader.lua "${args}" >>crash.log 2>&1 -RESULT=$? +RETURN_VALUE=85 +while [ $RETURN_VALUE -eq 85 ]; do + ./reader.lua "${args}" >>crash.log 2>&1 + RETURN_VALUE=$? +done if [ "${FROM_NICKEL}" = "true" ]; then if [ "${FROM_KFMON}" != "true" ]; then @@ -145,4 +148,4 @@ else fi fi -return ${RESULT} +exit $RETURN_VALUE diff --git a/platform/pocketbook/koreader.app b/platform/pocketbook/koreader.app index 446a7b0f1..707116b7b 100755 --- a/platform/pocketbook/koreader.app +++ b/platform/pocketbook/koreader.app @@ -42,8 +42,14 @@ if [ -e crash.log ]; then mv -f crash.log.new crash.log fi -./reader.lua "${args}" >>crash.log 2>&1 +RETURN_VALUE=85 +while [ $RETURN_VALUE -eq 85 ]; do + ./reader.lua "${args}" >>crash.log 2>&1 + RETURN_VALUE=$? +done if pidof reader.lua >/dev/null 2>&1; then killall -TERM reader.lua fi + +exit $RETURN_VALUE diff --git a/platform/ubuntu-touch/koreader.sh b/platform/ubuntu-touch/koreader.sh index f3440233e..33d958021 100755 --- a/platform/ubuntu-touch/koreader.sh +++ b/platform/ubuntu-touch/koreader.sh @@ -29,4 +29,11 @@ export EXT_FONT_DIR="${HOME}/fonts" # set fullscreen mode export SDL_FULLSCREEN=1 -./reader.lua -d ~/Documents +RETURN_VALUE=85 + +while [ $RETURN_VALUE -eq 85 ]; do + ./reader.lua -d ~/Documents + RETURN_VALUE=$? +done + +exit $RETURN_VALUE diff --git a/plugins/batterystat.koplugin/main.lua b/plugins/batterystat.koplugin/main.lua index 3e024866f..47117c6f6 100644 --- a/plugins/batterystat.koplugin/main.lua +++ b/plugins/batterystat.koplugin/main.lua @@ -6,6 +6,7 @@ local PowerD = require("device"):getPowerDevice() local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") local T = require("ffi/util").template +local dbg = require("dbg") local logger = require("logger") local util = require("ffi/util") local _ = require("gettext") @@ -94,11 +95,12 @@ local BatteryStat = { settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/batterstat.lua"), dump_file = util.realpath(DataStorage:getDataDir()) .. "/batterystat.log", debugging = false, + kv_page = nil, } function BatteryStat:init() self.charging = Usage:new(self.settings:readSetting("charging")) - self.decharging = Usage:new(self.settings:readSetting("decharging")) + self.discharging = Usage:new(self.settings:readSetting("discharging")) self.awake = Usage:new(self.settings:readSetting("awake")) self.sleeping = Usage:new(self.settings:readSetting("sleeping")) @@ -125,7 +127,7 @@ end function BatteryStat:onFlushSettings() self.settings:reset({ charging = self.charging, - decharging = self.decharging, + discharging = self.discharging, awake = self.awake, sleeping = self.sleeping, charging_state = self.charging_state, @@ -146,7 +148,7 @@ function BatteryStat:accumulate() -- Decharging to charging. self.charging:append(self.charging_state) else - self.decharging:append(self.charging_state) + self.discharging:append(self.charging_state) end self.awake_state = State:new() self.charging_state = State:new() @@ -183,20 +185,14 @@ end function BatteryStat:onCharging() self:debugOutput("onCharging") self.was_charging = false - self:dumpToText() - self.charging = Usage:new() - self.awake = Usage:new() - self.sleeping = Usage:new() + self:reset(true, false) self:accumulate() end function BatteryStat:onNotCharging() self:debugOutput("onNotCharging") self.was_charging = true - self:dumpToText() - self.decharging = Usage:new() - self.awake = Usage:new() - self.sleeping = Usage:new() + self:rest(false, true) self:accumulate() end @@ -207,10 +203,47 @@ function BatteryStat:showStatistics() table.insert(kv_pairs, "----------") table.insert(kv_pairs, {_("Historical records are dumped to"), ""}) table.insert(kv_pairs, {self.dump_file, ""}) - UIManager:show(KeyValuePage:new{ + table.insert(kv_pairs, "----------") + table.insert(kv_pairs, {_("If you would like to reset the data,"), "", + callback = function() + self:resetAll() + self:restart() + end}) + table.insert(kv_pairs, {_("please tap here."), "", + callback = function() + self:resetAll() + self:restart() + end}) + self.kv_page = KeyValuePage:new{ title = _("Battery statistics"), kv_pairs = kv_pairs, - }) + } + UIManager:show(self.kv_page) +end + +function BatteryStat:reset(withCharging, withDischarging) + self:dumpToText() + self.awake = Usage:new() + self.sleeping = Usage:new() + + if withCharging then + self.charging = Usage:new() + end + if withDischarging then + self.discharging = Usage:new() + end +end + +function BatteryStat:resetAll() + self:reset(true, true) + self.charging_state = State:new() + self.awake_state = State:new() +end + +function BatteryStat:restart() + dbg.dassert(self.kv_page ~= nil) + UIManager:close(self.kv_page) + self:showStatistics() end function BatteryStat:dumpToText() @@ -237,8 +270,8 @@ function BatteryStat:dump() self.charging:dump(kv_pairs) self.charging:dumpCharging(kv_pairs) table.insert(kv_pairs, {_("Since last charge"), ""}) - self.decharging:dump(kv_pairs) - self.decharging:dumpRemaining(kv_pairs) + self.discharging:dump(kv_pairs) + self.discharging:dumpRemaining(kv_pairs) return kv_pairs end diff --git a/plugins/kosync.koplugin/main.lua b/plugins/kosync.koplugin/main.lua index a5a0ee9f4..29aa888ab 100644 --- a/plugins/kosync.koplugin/main.lua +++ b/plugins/kosync.koplugin/main.lua @@ -223,7 +223,7 @@ end function KOSync:setCustomServer(server) DEBUG("set custom server", server) self.kosync_custom_server = server ~= "" and server or nil - self:onSaveSettings() + self:saveSettings() end function KOSync:login() @@ -324,7 +324,7 @@ function KOSync:doRegister(username, password) }) end - self:onSaveSettings() + self:saveSettings() end function KOSync:doLogin(username, password) @@ -359,13 +359,13 @@ function KOSync:doLogin(username, password) }) end - self:onSaveSettings() + self:saveSettings() end function KOSync:logout() self.kosync_userkey = nil self.kosync_auto_sync = true - self:onSaveSettings() + self:saveSettings() end function KOSync:getLastPercent() @@ -555,7 +555,7 @@ function KOSync:getProgress(manual) end end -function KOSync:onSaveSettings() +function KOSync:saveSettings() local settings = { custom_server = self.kosync_custom_server, username = self.kosync_username, diff --git a/reader.lua b/reader.lua index a93303825..3fad0d2f9 100755 --- a/reader.lua +++ b/reader.lua @@ -11,7 +11,6 @@ io.stdout:write([[ [*] Current time: ]], os.date("%x-%X"), "\n\n") io.stdout:flush() - -- load default settings require("defaults") local DataStorage = require("datastorage") @@ -165,6 +164,8 @@ if Device:needsTouchScreenProbe() then Device:touchScreenProbe() end +local exit_code = nil + if ARGV[argidx] and ARGV[argidx] ~= "" then local file = nil if lfs.attributes(ARGV[argidx], "mode") == "file" then @@ -189,13 +190,13 @@ if ARGV[argidx] and ARGV[argidx] ~= "" then FileManager:showFiles(home_dir) end) end - UIManager:run() + exit_code = UIManager:run() elseif last_file then local ReaderUI = require("apps/reader/readerui") UIManager:nextTick(function() ReaderUI:showReader(last_file) end) - UIManager:run() + exit_code = UIManager:run() else return showusage() end @@ -213,7 +214,12 @@ local function exitReader() Device:exit() if Profiler then Profiler.stop() end - os.exit(0) + + if type(exit_code) == "number" then + os.exit(exit_code) + else + os.exit(0) + end end exitReader() diff --git a/spec/unit/readerfooter_spec.lua b/spec/unit/readerfooter_spec.lua index e17b12db0..7e9a2564e 100644 --- a/spec/unit/readerfooter_spec.lua +++ b/spec/unit/readerfooter_spec.lua @@ -43,6 +43,7 @@ describe("Readerfooter module", function() book_time_to_read = true, chapter_time_to_read = true, }) + UIManager:run() end) it("should setup footer as visible in all_at_once mode", function() diff --git a/spec/unit/readerhighlight_spec.lua b/spec/unit/readerhighlight_spec.lua index 698d3daf6..5a75f2ccd 100644 --- a/spec/unit/readerhighlight_spec.lua +++ b/spec/unit/readerhighlight_spec.lua @@ -18,6 +18,7 @@ describe("Readerhighlight module", function() UIManager:scheduleIn(1, function() UIManager:close(readerui.dictionary.dict_window) UIManager:close(readerui) + UIManager:quit() end) UIManager:run() end @@ -57,6 +58,7 @@ describe("Readerhighlight module", function() UIManager:nextTick(function() UIManager:close(readerui.highlight.edit_highlight_dialog) UIManager:close(readerui) + UIManager:quit() end) UIManager:run() end @@ -169,6 +171,7 @@ describe("Readerhighlight module", function() after_each(function() readerui.highlight:clear() readerui.document.configurable.text_wrap = 0 + UIManager:close(readerui) -- close to flush settings end) it("should highlight single word", function() highlight_single_word(readerui, Geom:new{ x = 260, y = 70 }) @@ -253,6 +256,7 @@ describe("Readerhighlight module", function() after_each(function() readerui.highlight:clear() readerui.document.configurable.text_wrap = 0 + UIManager:close(readerui) -- close to flush settings end) it("should highlight single word", function() highlight_single_word(readerui, Geom:new{ x = 260, y = 70 }) diff --git a/spec/unit/readerpaging_spec.lua b/spec/unit/readerpaging_spec.lua index 42c94394c..439a91ad1 100644 --- a/spec/unit/readerpaging_spec.lua +++ b/spec/unit/readerpaging_spec.lua @@ -22,7 +22,7 @@ describe("Readerpaging module", function() it("should emit EndOfBook event at the end", function() UIManager:quit() UIManager:show(readerui) - UIManager:scheduleIn(1, function() UIManager:close(readerui) end) + UIManager:nextTick(function() UIManager:close(readerui) end) UIManager:run() readerui:handleEvent(Event:new("SetScrollMode", false)) readerui.zooming:setZoomMode("pageheight") @@ -54,7 +54,7 @@ describe("Readerpaging module", function() it("should emit EndOfBook event at the end", function() UIManager:quit() UIManager:show(readerui) - UIManager:scheduleIn(1, function() UIManager:close(readerui) end) + UIManager:nextTick(function() UIManager:close(readerui) end) UIManager:run() paging.page_positions = {} readerui:handleEvent(Event:new("SetScrollMode", true)) @@ -71,7 +71,7 @@ describe("Readerpaging module", function() UIManager:quit() end) - it("should scroll withtout crash backward on the first page", function() + it("should scroll backward on the first page without crash", function() local sample_djvu = "spec/front/unit/data/djvu3spec.djvu" local tmp_readerui = ReaderUI:new{ document = DocumentRegistry:openDocument(sample_djvu), @@ -79,7 +79,7 @@ describe("Readerpaging module", function() tmp_readerui.paging:onScrollPanRel(-100) end) - it("should scroll withtout crash forward on the last page", function() + it("should scroll forward on the last page without crash", function() local sample_djvu = "spec/front/unit/data/djvu3spec.djvu" local tmp_readerui = ReaderUI:new{ document = DocumentRegistry:openDocument(sample_djvu), diff --git a/spec/unit/readertoc_spec.lua b/spec/unit/readertoc_spec.lua index 170531b05..21b615ff5 100644 --- a/spec/unit/readertoc_spec.lua +++ b/spec/unit/readertoc_spec.lua @@ -12,6 +12,8 @@ describe("Readertoc module", function() readerui = ReaderUI:new{ document = DocumentRegistry:openDocument(sample_epub), } + -- reset book to first page + readerui.rolling:onGotoPage(0) toc = readerui.toc end) diff --git a/spec/unit/uimanager_spec.lua b/spec/unit/uimanager_spec.lua index c0d011a7d..62f33141a 100644 --- a/spec/unit/uimanager_spec.lua +++ b/spec/unit/uimanager_spec.lua @@ -172,6 +172,7 @@ describe("UIManager spec", function() assert.truthy(old_reset_timer) G_reader_settings:saveSetting("auto_suspend_timeout_seconds", 3600) + UIManager:run() UIManager:quit() -- should skip on non-kobo devices UIManager:_initAutoSuspend()