mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
BatteryStat plugin and instruction of KoboLight plugin (#2643)
* Start battery stat plugin * BatteryStat & kobolight * Several minor improvements * Remove a useless function * flush settings * Some review feedbacks * Resolve review comments * Remaining Minutes -> Remaining Hours * Add dump_file * typo * realpath * realpath on folder * Remove useless os.time() * Resolve review comments * warning * Add BatteryStat.debugging flag * treat log as txt * Minor improvement * Charging hour should be positive * Use warn instead of info * onSuspend in Kobo * Charging events for kobo and kindle * More events * dumpOrLog * Warnings * Typo * More space * Singleton * slightly format change * BatteryStat singleton * Init * Remove debugging flag * sleeping percentage is still negative * Read settings * Do not need to change was_suspending and was_charging * Typo * Remove debugging flag * Not charging should happen before suspend * Resolve review comments * was_suspend and was_charging should be updated each time in onCallback()
This commit is contained in:
@@ -4,10 +4,6 @@ local _, android = pcall(require, "android")
|
||||
local AndroidPowerD = BasePowerD:new{
|
||||
fl_min = 0, fl_max = 25,
|
||||
fl_intensity = 10,
|
||||
batt_capacity_file = "/sys/class/power_supply/battery/capacity",
|
||||
is_charging_file = "/sys/class/power_supply/battery/charging_enabled",
|
||||
battCapacity = nil,
|
||||
is_charging = nil,
|
||||
}
|
||||
|
||||
function AndroidPowerD:init()
|
||||
@@ -18,13 +14,11 @@ function AndroidPowerD:setIntensityHW()
|
||||
end
|
||||
|
||||
function AndroidPowerD:getCapacityHW()
|
||||
self.battCapacity = android.getBatteryLevel()
|
||||
return self.battCapacity
|
||||
return android.getBatteryLevel()
|
||||
end
|
||||
|
||||
function AndroidPowerD:isChargingHW()
|
||||
self.is_charging = android.isCharging()
|
||||
return self.is_charging
|
||||
return android.isCharging()
|
||||
end
|
||||
|
||||
return AndroidPowerD
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
local logger = require("logger")
|
||||
|
||||
local BasePowerD = {
|
||||
fl_min = 0, -- min frontlight intensity
|
||||
fl_max = 10, -- max frontlight intensity
|
||||
fl_intensity = nil, -- frontlight intensity
|
||||
battCapacity = nil, -- battery capacity
|
||||
device = nil, -- device object
|
||||
fl_min = 0, -- min frontlight intensity
|
||||
fl_max = 10, -- max frontlight intensity
|
||||
fl_intensity = nil, -- frontlight intensity
|
||||
battCapacity = 0, -- battery capacity
|
||||
device = nil, -- device object
|
||||
|
||||
capacity_pulled_count = 0,
|
||||
capacity_cached_count = 10,
|
||||
last_capacity_pull_time = 0, -- timestamp of last pull
|
||||
}
|
||||
|
||||
function BasePowerD:new(o)
|
||||
@@ -22,8 +21,8 @@ end
|
||||
function BasePowerD:init() end
|
||||
function BasePowerD:toggleFrontlight() end
|
||||
function BasePowerD:setIntensityHW() end
|
||||
function BasePowerD:getCapacityHW() return "0" end
|
||||
function BasePowerD:isChargingHW() end
|
||||
function BasePowerD:getCapacityHW() return 0 end
|
||||
function BasePowerD:isChargingHW() return false end
|
||||
-- Anything needs to be done before do a real hardware suspend. Such as turn off
|
||||
-- front light.
|
||||
function BasePowerD:beforeSuspend() end
|
||||
@@ -66,19 +65,17 @@ function BasePowerD:setIntensity(intensity)
|
||||
end
|
||||
|
||||
function BasePowerD:getCapacity()
|
||||
if self.capacity_pulled_count == self.capacity_cached_count then
|
||||
self.capacity_pulled_count = 0
|
||||
return self:getCapacityHW()
|
||||
else
|
||||
self.capacity_pulled_count = self.capacity_pulled_count + 1
|
||||
return self.battCapacity or self:getCapacityHW()
|
||||
if os.time() - self.last_capacity_pull_time >= 60 then
|
||||
self.battCapacity = self:getCapacityHW()
|
||||
self.last_capacity_pull_time = os.time()
|
||||
end
|
||||
return self.battCapacity
|
||||
end
|
||||
|
||||
function BasePowerD:refreshCapacity()
|
||||
-- We want our next getCapacity call to actually pull up to date info
|
||||
-- instead of a cached value ;)
|
||||
self.capacity_pulled_count = self.capacity_cached_count
|
||||
self.last_capacity_pull_time = 0
|
||||
end
|
||||
|
||||
function BasePowerD:isCharging()
|
||||
|
||||
@@ -5,8 +5,6 @@ local KindlePowerD = BasePowerD:new{
|
||||
fl_min = 0, fl_max = 24,
|
||||
|
||||
fl_intensity = nil,
|
||||
battCapacity = nil,
|
||||
is_charging = nil,
|
||||
lipc_handle = nil,
|
||||
|
||||
is_fl_on = false,
|
||||
@@ -55,20 +53,20 @@ end
|
||||
|
||||
function KindlePowerD:getCapacityHW()
|
||||
if self.lipc_handle ~= nil then
|
||||
self.battCapacity = self.lipc_handle:get_int_property("com.lab126.powerd", "battLevel")
|
||||
return self.lipc_handle:get_int_property("com.lab126.powerd", "battLevel")
|
||||
else
|
||||
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
||||
return self:read_int_file(self.batt_capacity_file)
|
||||
end
|
||||
return self.battCapacity
|
||||
end
|
||||
|
||||
function KindlePowerD:isChargingHW()
|
||||
local is_charging
|
||||
if self.lipc_handle ~= nil then
|
||||
self.is_charging = self.lipc_handle:get_int_property("com.lab126.powerd", "isCharging")
|
||||
is_charging = self.lipc_handle:get_int_property("com.lab126.powerd", "isCharging")
|
||||
else
|
||||
self.is_charging = self:read_int_file(self.is_charging_file)
|
||||
is_charging = self:read_int_file(self.is_charging_file)
|
||||
end
|
||||
return self.is_charging == 1
|
||||
return is_charging == 1
|
||||
end
|
||||
|
||||
function KindlePowerD:__gc()
|
||||
|
||||
@@ -19,8 +19,6 @@ local KoboPowerD = BasePowerD:new{
|
||||
|
||||
batt_capacity_file = batt_state_folder .. "capacity",
|
||||
is_charging_file = batt_state_folder .. "status",
|
||||
battCapacity = nil,
|
||||
is_charging = nil,
|
||||
}
|
||||
|
||||
function KoboPowerD:init()
|
||||
@@ -77,13 +75,11 @@ function KoboPowerD:setIntensityHW()
|
||||
end
|
||||
|
||||
function KoboPowerD:getCapacityHW()
|
||||
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
||||
return self.battCapacity
|
||||
return self:read_int_file(self.batt_capacity_file)
|
||||
end
|
||||
|
||||
function KoboPowerD:isChargingHW()
|
||||
self.is_charging = self:read_str_file(self.is_charging_file) == "Charging\n"
|
||||
return self.is_charging
|
||||
return self:read_str_file(self.is_charging_file) == "Charging\n"
|
||||
end
|
||||
|
||||
-- Turn off front light before suspend.
|
||||
|
||||
@@ -7,7 +7,6 @@ int IsCharging();
|
||||
]]
|
||||
|
||||
local PocketBookPowerD = BasePowerD:new{
|
||||
battCapacity = nil,
|
||||
is_charging = nil,
|
||||
batt_capacity_file = "/sys/devices/platform/sun5i-i2c.0/i2c-0/0-0034/axp20-supplyer.28/power_supply/battery/capacity",
|
||||
is_charging_file = "/sys/devices/platform/sun5i-i2c.0/i2c-0/0-0034/axp20-supplyer.28/power_supply/battery/status",
|
||||
@@ -17,8 +16,7 @@ function PocketBookPowerD:init()
|
||||
end
|
||||
|
||||
function PocketBookPowerD:getCapacityHW()
|
||||
self.battCapacity = self:read_int_file(self.batt_capacity_file)
|
||||
return self.battCapacity
|
||||
return self:read_int_file(self.batt_capacity_file)
|
||||
end
|
||||
|
||||
function PocketBookPowerD:isChargingHW()
|
||||
|
||||
@@ -2,7 +2,6 @@ local lfs = require("libs/libkoreader-lfs")
|
||||
local DataStorage = require("datastorage")
|
||||
local dump = require("dump")
|
||||
local purgeDir = require("ffi/util").purgeDir
|
||||
local logger = require("logger")
|
||||
|
||||
local DocSettings = {}
|
||||
|
||||
@@ -23,9 +22,6 @@ function DocSettings:getSidecarDir(doc_path)
|
||||
if file_without_suffix then
|
||||
return file_without_suffix..".sdr"
|
||||
end
|
||||
-- We shouldn't be called with anything but files with registered
|
||||
-- extensions, but in case we are, return something useful
|
||||
logger.err("getSidecarFile called with unexpected path:", doc_path)
|
||||
return doc_path..".sdr"
|
||||
end
|
||||
|
||||
|
||||
@@ -459,7 +459,9 @@ end
|
||||
|
||||
function CreDocument:register(registry)
|
||||
registry:addProvider("txt", "application/txt", self)
|
||||
registry:addProvider("log", "application/txt", self)
|
||||
registry:addProvider("txt.zip", "application/zip", self)
|
||||
registry:addProvider("log.zip", "application/zip", self)
|
||||
registry:addProvider("epub", "application/epub", self)
|
||||
registry:addProvider("fb2", "application/fb2", self)
|
||||
registry:addProvider("fb2.zip", "application/zip", self)
|
||||
|
||||
@@ -60,6 +60,10 @@ function LuaSettings:flipTrue(key)
|
||||
end
|
||||
end
|
||||
|
||||
function LuaSettings:reset(table)
|
||||
self.data = table
|
||||
end
|
||||
|
||||
function LuaSettings:flush()
|
||||
local f_out = io.open(self.file, "w")
|
||||
if f_out ~= nil then
|
||||
|
||||
@@ -22,13 +22,14 @@ function PluginLoader:loadPlugins()
|
||||
local ok, plugin_module = pcall(dofile, mainfile)
|
||||
if not ok or not plugin_module then
|
||||
logger.warn("Error when loading", mainfile, plugin_module)
|
||||
end
|
||||
if ok and plugin_module and not plugin_module.disabled then
|
||||
elseif type(plugin_module.disabled) ~= "boolean" or not plugin_module.disabled then
|
||||
package.path = package_path
|
||||
package.cpath = package_cpath
|
||||
plugin_module.path = path
|
||||
plugin_module.name = plugin_module.name or path:match("/(.-)%.koplugin")
|
||||
table.insert(self.plugins, plugin_module)
|
||||
else
|
||||
logger.info("Plugin ", mainfile, " has been disabled.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,11 +60,12 @@ function UIManager:init()
|
||||
self:_initAutoSuspend()
|
||||
self.event_handlers["Suspend"] = function()
|
||||
self:_stopAutoSuspend()
|
||||
self:broadcastEvent(Event:new("Suspend"))
|
||||
Device:onPowerEvent("Suspend")
|
||||
end
|
||||
self.event_handlers["Resume"] = function()
|
||||
Device:onPowerEvent("Resume")
|
||||
self:sendEvent(Event:new("Resume"))
|
||||
self:broadcastEvent(Event:new("Resume"))
|
||||
self:_startAutoSuspend()
|
||||
end
|
||||
self.event_handlers["PowerPress"] = function()
|
||||
@@ -99,11 +100,17 @@ function UIManager:init()
|
||||
Device:getPowerDevice():toggleFrontlight()
|
||||
end
|
||||
self.event_handlers["Charging"] = function()
|
||||
self:broadcastEvent(Event:new("Charging"))
|
||||
if Device.screen_saver_mode then
|
||||
self.event_handlers["Suspend"]()
|
||||
end
|
||||
end
|
||||
self.event_handlers["NotCharging"] = function()
|
||||
self:broadcastEvent(Event:new("NotCharging"))
|
||||
if Device.screen_saver_mode then
|
||||
self.event_handlers["Suspend"]()
|
||||
end
|
||||
end
|
||||
self.event_handlers["NotCharging"] = self.event_handlers["Charging"]
|
||||
self.event_handlers["__default__"] = function(input_event)
|
||||
if Device.screen_saver_mode then
|
||||
-- Suspension in Kobo can be interrupted by screen updates. We
|
||||
@@ -116,18 +123,20 @@ function UIManager:init()
|
||||
end
|
||||
elseif Device:isKindle() then
|
||||
self.event_handlers["IntoSS"] = function()
|
||||
self:broadcastEvent(Event:new("Suspend"))
|
||||
Device:intoScreenSaver()
|
||||
end
|
||||
self.event_handlers["OutOfSS"] = function()
|
||||
Device:outofScreenSaver()
|
||||
self:sendEvent(Event:new("Resume"))
|
||||
self:broadcastEvent(Event:new("Resume"))
|
||||
end
|
||||
self.event_handlers["Charging"] = function()
|
||||
self:broadcastEvent(Event:new("Charging"))
|
||||
Device:usbPlugIn()
|
||||
end
|
||||
self.event_handlers["NotCharging"] = function()
|
||||
Device:usbPlugOut()
|
||||
self:sendEvent(Event:new("NotCharging"))
|
||||
self:broadcastEvent(Event:new("NotCharging"))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -728,7 +737,7 @@ function UIManager:_initAutoSuspend()
|
||||
local now = util.gettime()
|
||||
-- Do not repeat auto suspend procedure after suspend.
|
||||
if self.last_action_sec + self.auto_suspend_sec <= now then
|
||||
Device:onPowerEvent("Suspend")
|
||||
self.event_handlers["Suspend"]()
|
||||
else
|
||||
self:scheduleIn(
|
||||
self.last_action_sec + self.auto_suspend_sec - now,
|
||||
|
||||
283
plugins/batterystat.koplugin/main.lua
Normal file
283
plugins/batterystat.koplugin/main.lua
Normal file
@@ -0,0 +1,283 @@
|
||||
|
||||
local DataStorage = require("datastorage")
|
||||
local KeyValuePage = require("ui/widget/keyvaluepage")
|
||||
local LuaSettings = require("luasettings")
|
||||
local PowerD = require("device"):getPowerDevice()
|
||||
local UIManager = require("ui/uimanager")
|
||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||
local T = require("ffi/util").template
|
||||
local logger = require("logger")
|
||||
local util = require("ffi/util")
|
||||
local _ = require("gettext")
|
||||
|
||||
local State = {}
|
||||
|
||||
function State:new(o)
|
||||
o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
if o.percentage == nil or o.timestamp == nil then
|
||||
o.percentage = PowerD:getCapacity()
|
||||
o.timestamp = os.time()
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
function State:toString()
|
||||
return string.format("{%d @ %s}", self.percentage, os.date("%c", self.timestamp))
|
||||
end
|
||||
|
||||
local Usage = {}
|
||||
|
||||
function Usage:new(o)
|
||||
o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
if o.percentage == nil or o.time == nil then
|
||||
o.percentage = 0
|
||||
o.time = 0
|
||||
end
|
||||
return o
|
||||
end
|
||||
|
||||
function Usage:append(state)
|
||||
local curr = State:new()
|
||||
self.percentage = self.percentage + (state.percentage - curr.percentage)
|
||||
self.time = self.time + os.difftime(curr.timestamp - state.timestamp)
|
||||
end
|
||||
|
||||
function Usage:minutes()
|
||||
return self.time / 60
|
||||
end
|
||||
|
||||
function Usage:hours()
|
||||
return self:minutes() / 60
|
||||
end
|
||||
|
||||
function Usage:percentagePerHour()
|
||||
if self.time == 0 then
|
||||
return 0
|
||||
else
|
||||
return self.percentage / self:hours()
|
||||
end
|
||||
end
|
||||
|
||||
function Usage:remainingHours()
|
||||
local curr = State:new()
|
||||
return curr.percentage / self:percentagePerHour()
|
||||
end
|
||||
|
||||
function Usage:chargingHours()
|
||||
local curr = State:new()
|
||||
return (curr.percentage - 100) / self:percentagePerHour()
|
||||
end
|
||||
|
||||
local function shorten(number)
|
||||
return string.format("%.2f", number);
|
||||
end
|
||||
|
||||
function Usage:dump(kv_pairs)
|
||||
table.insert(kv_pairs, {_(" Consumed %"), shorten(self.percentage)})
|
||||
table.insert(kv_pairs, {_(" Total minutes"), shorten(self:minutes())})
|
||||
table.insert(kv_pairs, {_(" % per hour"), shorten(self:percentagePerHour())})
|
||||
end
|
||||
|
||||
function Usage:dumpRemaining(kv_pairs)
|
||||
table.insert(kv_pairs, {_(" Estimated remaining hours"), shorten(self:remainingHours())})
|
||||
end
|
||||
|
||||
function Usage:dumpCharging(kv_pairs)
|
||||
table.insert(kv_pairs, {_(" Estimated hours for charging"), shorten(self:chargingHours())})
|
||||
end
|
||||
|
||||
local BatteryStat = {
|
||||
name = "batterstat",
|
||||
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/batterstat.lua"),
|
||||
dump_file = util.realpath(DataStorage:getDataDir()) .. "/batterystat.log",
|
||||
debugging = false,
|
||||
}
|
||||
|
||||
function BatteryStat:init()
|
||||
self.charging = Usage:new(self.settings:readSetting("charging"))
|
||||
self.decharging = Usage:new(self.settings:readSetting("decharging"))
|
||||
self.awake = Usage:new(self.settings:readSetting("awake"))
|
||||
self.sleeping = Usage:new(self.settings:readSetting("sleeping"))
|
||||
|
||||
-- Note: these fields are not the "real" timestamp and battery usage, but
|
||||
-- the unaccumulated values.
|
||||
self.charging_state = State:new(self.settings:readSetting("charging_state"))
|
||||
self.awake_state = State:new(self.settings:readSetting("awake_state"))
|
||||
self:initCurrentState()
|
||||
|
||||
if self.debugging then
|
||||
self.debugOutput = self._debugOutput
|
||||
else
|
||||
self.debugOutput = function() end
|
||||
end
|
||||
end
|
||||
|
||||
function BatteryStat:initCurrentState()
|
||||
-- Whether the device was suspending before current timestamp.
|
||||
self.was_suspending = false
|
||||
-- Whether the device was charging before current timestamp.
|
||||
self.was_charging = PowerD:isCharging()
|
||||
end
|
||||
|
||||
function BatteryStat:onFlushSettings()
|
||||
self.settings:reset({
|
||||
charging = self.charging,
|
||||
decharging = self.decharging,
|
||||
awake = self.awake,
|
||||
sleeping = self.sleeping,
|
||||
charging_state = self.charging_state,
|
||||
awake_state = self.awake_state,
|
||||
})
|
||||
self.settings:flush()
|
||||
end
|
||||
|
||||
function BatteryStat:accumulate()
|
||||
if self.was_suspending then
|
||||
-- Suspending to awake.
|
||||
self.sleeping:append(self.awake_state)
|
||||
else
|
||||
-- Awake to suspending, time between self.awake_state and now should belong to awake.
|
||||
self.awake:append(self.awake_state)
|
||||
end
|
||||
if self.was_charging then
|
||||
-- Decharging to charging.
|
||||
self.charging:append(self.charging_state)
|
||||
else
|
||||
self.decharging:append(self.charging_state)
|
||||
end
|
||||
self.awake_state = State:new()
|
||||
self.charging_state = State:new()
|
||||
end
|
||||
|
||||
function BatteryStat:dumpOrLog(content)
|
||||
local file = io.open(self.dump_file, "a")
|
||||
if file then
|
||||
file:write(content .. "\n")
|
||||
file:close()
|
||||
else
|
||||
logger.warn("Failed to dump output ", content, " into ", self.dump_file )
|
||||
end
|
||||
end
|
||||
|
||||
function BatteryStat:_debugOutput(event)
|
||||
self:dumpOrLog(event .. " @ " .. State:new():toString() ..
|
||||
", awake_state " .. self.awake_state:toString() ..
|
||||
", charging_state " .. self.charging_state:toString())
|
||||
end
|
||||
|
||||
function BatteryStat:onSuspend()
|
||||
self:debugOutput("onSuspend")
|
||||
self.was_suspending = false
|
||||
self:accumulate()
|
||||
end
|
||||
|
||||
function BatteryStat:onResume()
|
||||
self:debugOutput("onResume")
|
||||
self.was_suspending = true
|
||||
self:accumulate()
|
||||
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: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:accumulate()
|
||||
end
|
||||
|
||||
function BatteryStat:onCallback()
|
||||
self:initCurrentState()
|
||||
self:accumulate()
|
||||
local kv_pairs = self:dump()
|
||||
table.insert(kv_pairs, "----------")
|
||||
table.insert(kv_pairs, {_("Historical records are dumped to"), ""})
|
||||
table.insert(kv_pairs, {self.dump_file, ""})
|
||||
UIManager:show(KeyValuePage:new{
|
||||
title = _("Battery statistics"),
|
||||
kv_pairs = kv_pairs,
|
||||
})
|
||||
end
|
||||
|
||||
function BatteryStat:dumpToText()
|
||||
local kv_pairs = self:dump()
|
||||
local content = T(_("Dump at %1"), os.date("%c"))
|
||||
for _, pair in ipairs(kv_pairs) do
|
||||
content = content .. "\n" .. pair[1]
|
||||
if pair[2] ~= nil and pair[2] ~= "" then
|
||||
content = content .. "\t" .. pair[2]
|
||||
end
|
||||
end
|
||||
self:dumpOrLog(content .. "\n-=-=-=-=-=-\n")
|
||||
end
|
||||
|
||||
function BatteryStat:dump()
|
||||
local kv_pairs = {}
|
||||
table.insert(kv_pairs, {_("Awake since last charge"), ""})
|
||||
self.awake:dump(kv_pairs)
|
||||
self.awake:dumpRemaining(kv_pairs)
|
||||
table.insert(kv_pairs, {_("Sleeping since last charge"), ""})
|
||||
self.sleeping:dump(kv_pairs)
|
||||
self.sleeping:dumpRemaining(kv_pairs)
|
||||
table.insert(kv_pairs, {_("During last charge"), ""})
|
||||
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)
|
||||
return kv_pairs
|
||||
end
|
||||
|
||||
BatteryStat:init()
|
||||
|
||||
local BatteryStatWidget = WidgetContainer:new()
|
||||
|
||||
function BatteryStatWidget:init()
|
||||
self.ui.menu:registerToMainMenu(self)
|
||||
end
|
||||
|
||||
function BatteryStatWidget:addToMainMenu(tab_item_table)
|
||||
table.insert(tab_item_table.plugins, {
|
||||
text = _("Battery statistics"),
|
||||
callback = function()
|
||||
BatteryStat:onCallback()
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
function BatteryStatWidget:onFlushSettings()
|
||||
BatteryStat:onFlushSettings()
|
||||
end
|
||||
|
||||
function BatteryStatWidget:onSuspend()
|
||||
BatteryStat:onSuspend()
|
||||
end
|
||||
|
||||
function BatteryStatWidget:onResume()
|
||||
BatteryStat:onResume()
|
||||
end
|
||||
|
||||
function BatteryStatWidget:onCharging()
|
||||
BatteryStat:onCharging()
|
||||
end
|
||||
|
||||
function BatteryStatWidget:onNotCharging()
|
||||
BatteryStat:onNotCharging()
|
||||
end
|
||||
|
||||
return BatteryStatWidget
|
||||
BIN
plugins/kobolight.koplugin/demo.png
Normal file
BIN
plugins/kobolight.koplugin/demo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -1,20 +1,24 @@
|
||||
local Device = require("device")
|
||||
|
||||
if not ((Device:isKindle() or Device:isKobo()) and Device:hasFrontlight()) then
|
||||
local with_frontlight = (Device:isKindle() or Device:isKobo()) and Device:hasFrontlight()
|
||||
if not (with_frontlight or Device:isSDL()) then
|
||||
return { disabled = true, }
|
||||
end
|
||||
|
||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||
local Screen = Device.screen
|
||||
local UIManager = require("ui/uimanager")
|
||||
local ConfirmBox = require("ui/widget/confirmbox")
|
||||
local ImageWidget = require("ui/widget/imagewidget")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local Notification = require("ui/widget/notification")
|
||||
local PluginLoader = require("pluginloader")
|
||||
local Screen = require("device").screen
|
||||
local UIManager = require("ui/uimanager")
|
||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||
local T = require("ffi/util").template
|
||||
local _ = require("gettext")
|
||||
|
||||
local tap_touch_zone_ratio = { x = 0, y = 15/16, w = 1/10, h = 1/16, }
|
||||
local swipe_touch_zone_ratio = { x = 0, y = 1/8, w = 1/10, h = 7/8, }
|
||||
|
||||
|
||||
local KoboLight = WidgetContainer:new{
|
||||
name = 'kobolight',
|
||||
gestureScale = nil, -- initialized in self:resetLayout()
|
||||
@@ -28,6 +32,8 @@ function KoboLight:init()
|
||||
do
|
||||
self.steps[i] = math.ceil(self.steps[i] * scale)
|
||||
end
|
||||
|
||||
self.ui.menu:registerToMainMenu(self)
|
||||
end
|
||||
|
||||
function KoboLight:onReaderReady()
|
||||
@@ -35,8 +41,13 @@ function KoboLight:onReaderReady()
|
||||
self:resetLayout()
|
||||
end
|
||||
|
||||
function KoboLight:disabled()
|
||||
return G_reader_settings:isTrue("disable_kobolight")
|
||||
end
|
||||
|
||||
function KoboLight:setupTouchZones()
|
||||
if not Device:isTouchDevice() then return end
|
||||
if self:disabled() then return end
|
||||
local swipe_zone = {
|
||||
ratio_x = swipe_touch_zone_ratio.x, ratio_y = swipe_touch_zone_ratio.y,
|
||||
ratio_w = swipe_touch_zone_ratio.w, ratio_h = swipe_touch_zone_ratio.h,
|
||||
@@ -148,4 +159,39 @@ function KoboLight:onSwipe(_, ges)
|
||||
return true
|
||||
end
|
||||
|
||||
function KoboLight:addToMainMenu(tab_item_table)
|
||||
table.insert(tab_item_table.plugins, {
|
||||
text = _("Frontlight gesture controller"),
|
||||
callback = function()
|
||||
local image = ImageWidget:new{
|
||||
file = PluginLoader.plugin_path .. "/kobolight.koplugin/demo.png",
|
||||
height = Screen:getHeight(),
|
||||
width = Screen:getWidth(),
|
||||
scale_factor = 0,
|
||||
}
|
||||
UIManager:show(image)
|
||||
UIManager:show(ConfirmBox:new{
|
||||
text = T(_("Frontlight gesture controller can:\n- Turn on or off frontlight by tapping bottom left of the screen.\n- Change frontlight intensity by swiping up or down on the left of the screen.\n\nDo you want to %1 it?"),
|
||||
self:disabled() and _("enable") or _("disable")),
|
||||
ok_text = self:disabled() and _("Enable") or _("Disable"),
|
||||
ok_callback = function()
|
||||
UIManager:close(image)
|
||||
UIManager:setDirty("all", "full")
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = T(_("You have %1 the frontlight gesture controller. It will take effect on next restart."),
|
||||
self:disabled() and _("enabled") or _("disabled"))
|
||||
})
|
||||
G_reader_settings:flipTrue("disable_kobolight")
|
||||
end,
|
||||
cancel_text = _("Close"),
|
||||
cancel_callback = function()
|
||||
UIManager:close(image)
|
||||
UIManager:setDirty("all", "full")
|
||||
end,
|
||||
})
|
||||
UIManager:setDirty("all", "full")
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
return KoboLight
|
||||
|
||||
Reference in New Issue
Block a user