2017-04-15 12:45:56 +00:00
|
|
|
--[[--
|
|
|
|
This module handles generic settings as well as KOReader's global settings system.
|
|
|
|
]]
|
|
|
|
|
2016-06-12 18:28:44 +00:00
|
|
|
local dump = require("dump")
|
2019-12-10 22:00:08 +00:00
|
|
|
local ffiutil = require("ffi/util")
|
2018-01-21 17:44:15 +00:00
|
|
|
local lfs = require("libs/libkoreader-lfs")
|
|
|
|
local logger = require("logger")
|
2016-06-12 18:28:44 +00:00
|
|
|
|
|
|
|
local LuaSettings = {}
|
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
function LuaSettings:extend(o)
|
2017-10-07 20:13:46 +00:00
|
|
|
o = o or {}
|
|
|
|
setmetatable(o, self)
|
|
|
|
self.__index = self
|
|
|
|
return o
|
|
|
|
end
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
-- NOTE: Instances are created via open, so we do *NOT* implement a new method, to avoid confusion.
|
2017-10-07 20:13:46 +00:00
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Opens a settings file.
|
2016-06-12 18:28:44 +00:00
|
|
|
function LuaSettings:open(file_path)
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
local new = LuaSettings:extend{
|
|
|
|
file = file_path,
|
|
|
|
}
|
2016-06-12 18:28:44 +00:00
|
|
|
local ok, stored
|
|
|
|
|
2018-01-21 17:44:15 +00:00
|
|
|
-- File being absent and returning an empty table is a use case,
|
|
|
|
-- so logger.warn() only if there was an existing file
|
|
|
|
local existing = lfs.attributes(new.file, "mode") == "file"
|
|
|
|
|
2016-06-12 18:28:44 +00:00
|
|
|
ok, stored = pcall(dofile, new.file)
|
|
|
|
if ok and stored then
|
|
|
|
new.data = stored
|
|
|
|
else
|
2022-10-09 17:32:35 +00:00
|
|
|
if existing then logger.warn("LuaSettings: Failed reading", new.file, "(probably corrupted).") end
|
2018-01-21 17:44:15 +00:00
|
|
|
-- Fallback to .old if it exists
|
|
|
|
ok, stored = pcall(dofile, new.file..".old")
|
|
|
|
if ok and stored then
|
2022-10-09 17:32:35 +00:00
|
|
|
if existing then logger.warn("LuaSettings: read from backup file", new.file..".old") end
|
2018-01-21 17:44:15 +00:00
|
|
|
new.data = stored
|
|
|
|
else
|
2022-10-09 17:32:35 +00:00
|
|
|
if existing then logger.warn("LuaSettings: no usable backup file for", new.file, "to read from") end
|
2018-01-21 17:44:15 +00:00
|
|
|
new.data = {}
|
|
|
|
end
|
2016-06-12 18:28:44 +00:00
|
|
|
end
|
|
|
|
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
return new
|
2016-06-12 18:28:44 +00:00
|
|
|
end
|
|
|
|
|
2017-03-28 22:10:36 +00:00
|
|
|
function LuaSettings:wrap(data)
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
return self:extend{
|
|
|
|
data = type(data) == "table" and data or {},
|
|
|
|
}
|
2017-03-28 22:10:36 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--[[--Reads child settings.
|
|
|
|
|
|
|
|
@usage
|
|
|
|
|
|
|
|
Settings:saveSetting("key", {
|
|
|
|
a = "b",
|
2021-03-06 21:44:18 +00:00
|
|
|
c = true,
|
2017-04-15 12:45:56 +00:00
|
|
|
d = false,
|
|
|
|
})
|
|
|
|
|
|
|
|
local child = Settings:child("key")
|
|
|
|
|
|
|
|
child:readSetting("a")
|
|
|
|
-- result "b"
|
|
|
|
]]
|
2017-03-28 22:10:36 +00:00
|
|
|
function LuaSettings:child(key)
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
return self:wrap(self:readSetting(key))
|
2017-03-28 22:10:36 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--[[-- Reads a setting, optionally initializing it to a default.
|
|
|
|
|
|
|
|
If default is provided, and the key doesn't exist yet, it is initialized to default first.
|
|
|
|
This ensures both that the defaults are actually set if necessary,
|
|
|
|
and that the returned reference actually belongs to the LuaSettings object straight away,
|
|
|
|
without requiring further interaction (e.g., saveSetting) from the caller.
|
|
|
|
|
|
|
|
This is mainly useful if the data type you want to retrieve/store is assigned/returned/passed by reference (e.g., a table),
|
|
|
|
and you never actually break that reference by assigning another one to the same variable, (by e.g., assigning it a new object).
|
|
|
|
c.f., <https://www.lua.org/manual/5.1/manual.html#2.2>.
|
|
|
|
|
|
|
|
@param key The setting's key
|
|
|
|
@param default Initialization data (Optional)
|
|
|
|
]]
|
|
|
|
function LuaSettings:readSetting(key, default)
|
|
|
|
-- No initialization data: legacy behavior
|
|
|
|
if not default then
|
|
|
|
return self.data[key]
|
|
|
|
end
|
|
|
|
|
|
|
|
if not self:has(key) then
|
|
|
|
self.data[key] = default
|
|
|
|
end
|
2016-06-12 18:28:44 +00:00
|
|
|
return self.data[key]
|
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Saves a setting.
|
2016-06-12 18:28:44 +00:00
|
|
|
function LuaSettings:saveSetting(key, value)
|
|
|
|
self.data[key] = value
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2016-06-12 18:28:44 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Deletes a setting.
|
2016-06-12 18:28:44 +00:00
|
|
|
function LuaSettings:delSetting(key)
|
|
|
|
self.data[key] = nil
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2016-06-12 18:28:44 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Checks if setting exists.
|
2016-09-01 07:05:40 +00:00
|
|
|
function LuaSettings:has(key)
|
2021-03-06 21:44:18 +00:00
|
|
|
return self.data[key] ~= nil
|
2016-09-01 07:05:40 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Checks if setting does not exist.
|
2016-09-01 07:05:40 +00:00
|
|
|
function LuaSettings:hasNot(key)
|
2021-03-06 21:44:18 +00:00
|
|
|
return self.data[key] == nil
|
2016-09-01 07:05:40 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--- Checks if setting is `true` (boolean).
|
2016-09-01 07:05:40 +00:00
|
|
|
function LuaSettings:isTrue(key)
|
2021-03-06 21:44:18 +00:00
|
|
|
return self.data[key] == true
|
2016-09-01 07:05:40 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--- Checks if setting is `false` (boolean).
|
2017-03-28 22:10:36 +00:00
|
|
|
function LuaSettings:isFalse(key)
|
2021-03-06 21:44:18 +00:00
|
|
|
return self.data[key] == false
|
2017-03-28 22:10:36 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Checks if setting is `nil` or `true`.
|
2016-09-01 07:05:40 +00:00
|
|
|
function LuaSettings:nilOrTrue(key)
|
|
|
|
return self:hasNot(key) or self:isTrue(key)
|
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Checks if setting is `nil` or `false`.
|
2017-03-28 22:10:36 +00:00
|
|
|
function LuaSettings:nilOrFalse(key)
|
|
|
|
return self:hasNot(key) or self:isFalse(key)
|
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--- Flips `nil` or `true` to `false`, and `false` to `nil`.
|
|
|
|
--- e.g., a setting that defaults to true.
|
2016-09-01 07:05:40 +00:00
|
|
|
function LuaSettings:flipNilOrTrue(key)
|
|
|
|
if self:nilOrTrue(key) then
|
|
|
|
self:saveSetting(key, false)
|
|
|
|
else
|
|
|
|
self:delSetting(key)
|
|
|
|
end
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2016-09-01 07:05:40 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--- Flips `nil` or `false` to `true`, and `true` to `nil`.
|
|
|
|
--- e.g., a setting that defaults to false.
|
2017-03-28 22:10:36 +00:00
|
|
|
function LuaSettings:flipNilOrFalse(key)
|
|
|
|
if self:nilOrFalse(key) then
|
|
|
|
self:saveSetting(key, true)
|
|
|
|
else
|
|
|
|
self:delSetting(key)
|
|
|
|
end
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2017-03-28 22:10:36 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--- Flips a setting between `true` and `nil`.
|
2016-09-01 07:05:40 +00:00
|
|
|
function LuaSettings:flipTrue(key)
|
|
|
|
if self:isTrue(key) then
|
|
|
|
self:delSetting(key)
|
|
|
|
else
|
|
|
|
self:saveSetting(key, true)
|
|
|
|
end
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2016-09-01 07:05:40 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
--- Flips a setting between `false` and `nil`.
|
2017-03-28 22:10:36 +00:00
|
|
|
function LuaSettings:flipFalse(key)
|
|
|
|
if self:isFalse(key) then
|
|
|
|
self:delSetting(key)
|
|
|
|
else
|
2019-03-14 19:58:45 +00:00
|
|
|
self:saveSetting(key, false)
|
2017-03-28 22:10:36 +00:00
|
|
|
end
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2017-03-28 22:10:36 +00:00
|
|
|
end
|
|
|
|
|
2021-03-06 21:44:18 +00:00
|
|
|
-- Unconditionally makes a boolean setting `true`.
|
|
|
|
function LuaSettings:makeTrue(key)
|
|
|
|
self:saveSetting(key, true)
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Unconditionally makes a boolean setting `false`.
|
|
|
|
function LuaSettings:makeFalse(key)
|
|
|
|
self:saveSetting(key, false)
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Toggles a boolean setting
|
|
|
|
function LuaSettings:toggle(key)
|
|
|
|
if self:nilOrFalse(key) then
|
|
|
|
self:saveSetting(key, true)
|
|
|
|
else
|
|
|
|
self:saveSetting(key, false)
|
|
|
|
end
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
2020-12-24 08:07:27 +00:00
|
|
|
-- Initializes settings per extension with default values
|
|
|
|
function LuaSettings:initializeExtSettings(key, defaults, force_init)
|
|
|
|
local curr = self:readSetting(key)
|
|
|
|
if not curr or force_init then
|
|
|
|
self:saveSetting(key, defaults)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Returns saved setting for given extension
|
|
|
|
function LuaSettings:getSettingForExt(key, ext)
|
|
|
|
local saved_settings = self:readSetting(key) or {}
|
|
|
|
return saved_settings[ext]
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Sets setting for given extension
|
|
|
|
function LuaSettings:saveSettingForExt(key, value, ext)
|
|
|
|
local saved_settings = self:readSetting(key) or {}
|
|
|
|
saved_settings[ext] = value
|
|
|
|
self:saveSetting(key, saved_settings)
|
|
|
|
end
|
|
|
|
|
2017-10-07 20:13:46 +00:00
|
|
|
--- Adds item to table.
|
|
|
|
function LuaSettings:addTableItem(key, value)
|
|
|
|
local settings_table = self:has(key) and self:readSetting(key) or {}
|
|
|
|
table.insert(settings_table, value)
|
|
|
|
self:saveSetting(key, settings_table)
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Removes index from table.
|
|
|
|
function LuaSettings:removeTableItem(key, index)
|
|
|
|
local settings_table = self:has(key) and self:readSetting(key) or {}
|
|
|
|
table.remove(settings_table, index)
|
|
|
|
self:saveSetting(key, settings_table)
|
|
|
|
return self
|
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Replaces existing settings with table.
|
2017-03-24 06:36:15 +00:00
|
|
|
function LuaSettings:reset(table)
|
|
|
|
self.data = table
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2017-03-24 06:36:15 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Writes settings to disk.
|
2016-06-12 18:28:44 +00:00
|
|
|
function LuaSettings:flush()
|
2017-03-28 22:10:36 +00:00
|
|
|
if not self.file then return end
|
2019-12-10 22:00:08 +00:00
|
|
|
local directory_updated = false
|
2018-01-21 17:44:15 +00:00
|
|
|
if lfs.attributes(self.file, "mode") == "file" then
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
-- As an additional safety measure (to the ffiutil.fsync* calls used below),
|
|
|
|
-- we only backup the file to .old when it has not been modified in the last 60 seconds.
|
|
|
|
-- This should ensure in the case the fsync calls are not supported
|
|
|
|
-- that the OS may have itself sync'ed that file content in the meantime.
|
2019-12-10 22:00:08 +00:00
|
|
|
local mtime = lfs.attributes(self.file, "modification")
|
|
|
|
if mtime < os.time() - 60 then
|
|
|
|
os.rename(self.file, self.file .. ".old")
|
|
|
|
directory_updated = true -- fsync directory content too below
|
|
|
|
end
|
2018-01-21 17:44:15 +00:00
|
|
|
end
|
2016-06-12 18:28:44 +00:00
|
|
|
local f_out = io.open(self.file, "w")
|
|
|
|
if f_out ~= nil then
|
|
|
|
f_out:write("-- we can read Lua syntax here!\nreturn ")
|
2020-11-12 19:38:11 +00:00
|
|
|
f_out:write(dump(self.data, nil, true))
|
2016-06-12 18:28:44 +00:00
|
|
|
f_out:write("\n")
|
2019-12-10 22:00:08 +00:00
|
|
|
ffiutil.fsyncOpenedFile(f_out) -- force flush to the storage device
|
2016-06-12 18:28:44 +00:00
|
|
|
f_out:close()
|
|
|
|
end
|
2019-12-10 22:00:08 +00:00
|
|
|
if directory_updated then
|
|
|
|
-- Ensure the file renaming is flushed to storage device
|
|
|
|
ffiutil.fsyncDirectory(self.file)
|
|
|
|
end
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2016-06-12 18:28:44 +00:00
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Closes settings file.
|
2016-06-12 18:28:44 +00:00
|
|
|
function LuaSettings:close()
|
|
|
|
self:flush()
|
|
|
|
end
|
|
|
|
|
2017-04-15 12:45:56 +00:00
|
|
|
--- Purges settings file.
|
2016-06-12 18:28:44 +00:00
|
|
|
function LuaSettings:purge()
|
|
|
|
if self.file then
|
|
|
|
os.remove(self.file)
|
|
|
|
end
|
2017-06-14 17:32:16 +00:00
|
|
|
return self
|
2016-06-12 18:28:44 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return LuaSettings
|