2015-03-09 12:20:32 +00:00
|
|
|
local InputContainer = require("ui/widget/container/inputcontainer")
|
|
|
|
local LoginDialog = require("ui/widget/logindialog")
|
|
|
|
local InfoMessage = require("ui/widget/infomessage")
|
|
|
|
local ConfirmBox = require("ui/widget/confirmbox")
|
2016-06-26 00:53:08 +00:00
|
|
|
local NetworkMgr = require("ui/network/manager")
|
2015-03-09 12:20:32 +00:00
|
|
|
local UIManager = require("ui/uimanager")
|
2020-06-13 11:13:23 +00:00
|
|
|
local Device = require("device")
|
2015-03-09 12:20:32 +00:00
|
|
|
local Event = require("ui/event")
|
2015-03-10 07:09:42 +00:00
|
|
|
local Math = require("optmath")
|
2020-06-13 11:47:07 +00:00
|
|
|
local Screen = Device.screen
|
|
|
|
local logger = require("logger")
|
2020-07-21 21:25:46 +00:00
|
|
|
local md5 = require("ffi/sha2").md5
|
2016-08-11 09:12:55 +00:00
|
|
|
local random = require("random")
|
2020-06-13 11:47:07 +00:00
|
|
|
local T = require("ffi/util").template
|
|
|
|
local _ = require("gettext")
|
2016-08-11 09:12:55 +00:00
|
|
|
|
|
|
|
if not G_reader_settings:readSetting("device_id") then
|
|
|
|
G_reader_settings:saveSetting("device_id", random.uuid())
|
|
|
|
end
|
2015-03-09 12:20:32 +00:00
|
|
|
|
2020-01-01 11:27:51 +00:00
|
|
|
-- 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
|
|
|
|
|
2015-03-09 12:20:32 +00:00
|
|
|
local KOSync = InputContainer:new{
|
|
|
|
name = "kosync",
|
2016-12-20 07:19:54 +00:00
|
|
|
is_doc_only = true,
|
2016-03-28 01:50:23 +00:00
|
|
|
title = _("Register/login to KOReader server"),
|
2016-09-24 08:20:28 +00:00
|
|
|
|
|
|
|
page_update_times = 0,
|
|
|
|
last_page = -1,
|
|
|
|
last_page_turn_ticks = 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
local SYNC_STRATEGY = {
|
|
|
|
-- Forward and backward whisper sync settings are using different
|
|
|
|
-- default value, so none of following opinions should be zero.
|
|
|
|
PROMPT = 1,
|
|
|
|
WHISPER = 2,
|
|
|
|
DISABLE = 3,
|
|
|
|
|
|
|
|
DEFAULT_FORWARD = 1,
|
|
|
|
DEFAULT_BACKWARD = 3,
|
2015-03-09 12:20:32 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 07:04:44 +00:00
|
|
|
local function getNameStrategy(type)
|
|
|
|
if type == 1 then
|
|
|
|
return _("Prompt")
|
|
|
|
elseif type == 2 then
|
|
|
|
return _("Auto")
|
|
|
|
else
|
|
|
|
return _("Disable")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-24 08:20:28 +00:00
|
|
|
local function showSyncedMessage()
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Progress has been synchronized."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
local function promptLogin()
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Please register or login before using the progress synchronization feature."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
|
|
|
local function showSyncError()
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Something went wrong when syncing progress, please check your network connection and try again later."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2020-02-25 19:40:50 +00:00
|
|
|
local function validate(entry)
|
|
|
|
if not entry then return false end
|
|
|
|
if type(entry) == "string" then
|
|
|
|
if entry == "" or not entry:match("%S") then return false end
|
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
local function validateUser(user, pass)
|
|
|
|
local error_message = nil
|
|
|
|
local user_ok = validate(user)
|
|
|
|
local pass_ok = validate(pass)
|
|
|
|
if not user_ok and not pass_ok then
|
|
|
|
error_message = _("invalid username and password")
|
|
|
|
elseif not user_ok then
|
|
|
|
error_message = _("invalid username")
|
|
|
|
elseif not pass_ok then
|
|
|
|
error_message = _("invalid password")
|
|
|
|
end
|
|
|
|
|
|
|
|
if not error_message then
|
|
|
|
return user_ok and pass_ok
|
|
|
|
else
|
|
|
|
return user_ok and pass_ok, error_message
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-09-24 08:20:28 +00:00
|
|
|
function KOSync:onReaderReady()
|
2015-03-09 12:20:32 +00:00
|
|
|
local settings = G_reader_settings:readSetting("kosync") or {}
|
2015-09-17 15:27:19 +00:00
|
|
|
self.kosync_custom_server = settings.custom_server
|
2015-03-10 07:49:33 +00:00
|
|
|
self.kosync_username = settings.username
|
2015-03-09 12:20:32 +00:00
|
|
|
self.kosync_userkey = settings.userkey
|
2015-03-11 04:23:23 +00:00
|
|
|
self.kosync_auto_sync = not (settings.auto_sync == false)
|
2016-09-24 08:20:28 +00:00
|
|
|
self.kosync_whisper_forward = settings.whisper_forward or SYNC_STRATEGY.DEFAULT_FORWARD
|
|
|
|
self.kosync_whisper_backward = settings.whisper_backward or SYNC_STRATEGY.DEFAULT_BACKWARD
|
2016-07-30 00:38:02 +00:00
|
|
|
self.kosync_device_id = G_reader_settings:readSetting("device_id")
|
2016-08-11 09:12:55 +00:00
|
|
|
--assert(self.kosync_device_id)
|
2016-09-24 08:20:28 +00:00
|
|
|
if self.kosync_auto_sync then
|
|
|
|
self:_onResume()
|
|
|
|
end
|
|
|
|
self:registerEvents()
|
2015-03-09 12:20:32 +00:00
|
|
|
self.ui.menu:registerToMainMenu(self)
|
2016-07-30 00:38:02 +00:00
|
|
|
-- Make sure checksum has been calculated at the very first time a document has been opened, to
|
|
|
|
-- avoid document saving feature to impact the checksum, and eventually impact the document
|
|
|
|
-- identity in the progress sync feature.
|
2017-10-13 17:18:36 +00:00
|
|
|
self.view.document:fastDigest(self.ui.doc_settings)
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
2017-03-04 13:46:38 +00:00
|
|
|
function KOSync:addToMainMenu(menu_items)
|
|
|
|
menu_items.progress_sync = {
|
2015-03-10 07:12:44 +00:00
|
|
|
text = _("Progress sync"),
|
2015-03-09 12:20:32 +00:00
|
|
|
sub_item_table = {
|
|
|
|
{
|
|
|
|
text_func = function()
|
|
|
|
return self.kosync_userkey and (_("Logout"))
|
|
|
|
or _("Register") .. " / " .. _("Login")
|
|
|
|
end,
|
2018-09-04 21:55:58 +00:00
|
|
|
keep_menu_open = true,
|
2015-03-09 12:20:32 +00:00
|
|
|
callback_func = function()
|
2019-08-29 08:05:49 +00:00
|
|
|
if self.kosync_userkey then
|
|
|
|
return function(menu)
|
|
|
|
self._menu_to_update = menu
|
|
|
|
self:logout()
|
|
|
|
end
|
|
|
|
else
|
|
|
|
return function(menu)
|
|
|
|
self._menu_to_update = menu
|
|
|
|
self:login()
|
|
|
|
end
|
|
|
|
end
|
2015-03-09 12:20:32 +00:00
|
|
|
end,
|
|
|
|
},
|
2015-03-10 07:09:42 +00:00
|
|
|
{
|
2016-07-30 00:38:02 +00:00
|
|
|
text = _("Auto sync now and future"),
|
2015-03-10 07:09:42 +00:00
|
|
|
checked_func = function() return self.kosync_auto_sync end,
|
|
|
|
callback = function()
|
|
|
|
self.kosync_auto_sync = not self.kosync_auto_sync
|
2016-09-24 08:20:28 +00:00
|
|
|
self:registerEvents()
|
2016-07-30 00:38:02 +00:00
|
|
|
if self.kosync_auto_sync then
|
|
|
|
-- since we will update the progress when closing document, we should pull
|
|
|
|
-- current progress now to avoid to overwrite it silently.
|
|
|
|
self:getProgress(true)
|
|
|
|
else
|
|
|
|
-- since we won't update the progress when closing document, we should push
|
|
|
|
-- current progress now to avoid to lose it silently.
|
|
|
|
self:updateProgress(true)
|
|
|
|
end
|
2020-08-09 09:19:50 +00:00
|
|
|
self:saveSettings()
|
2015-03-10 07:09:42 +00:00
|
|
|
end,
|
|
|
|
},
|
2016-09-24 08:20:28 +00:00
|
|
|
{
|
|
|
|
text = _("Whisper sync"),
|
|
|
|
enabled_func = function() return self.kosync_auto_sync end,
|
|
|
|
sub_item_table = {
|
|
|
|
{
|
2020-04-25 07:04:44 +00:00
|
|
|
text_func = function()
|
|
|
|
return T(_("Sync to latest record (%1)"), getNameStrategy(self.kosync_whisper_forward))
|
2016-09-24 08:20:28 +00:00
|
|
|
end,
|
2020-04-25 07:04:44 +00:00
|
|
|
sub_item_table = {
|
|
|
|
{
|
|
|
|
text = _("Auto"),
|
|
|
|
checked_func = function()
|
|
|
|
return self.kosync_whisper_forward == SYNC_STRATEGY.WHISPER
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:setWhisperForward(SYNC_STRATEGY.WHISPER)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Prompt"),
|
|
|
|
checked_func = function()
|
|
|
|
return self.kosync_whisper_forward == SYNC_STRATEGY.PROMPT
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:setWhisperForward(SYNC_STRATEGY.PROMPT)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Disable"),
|
|
|
|
checked_func = function()
|
|
|
|
return self.kosync_whisper_forward == SYNC_STRATEGY.DISABLE
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:setWhisperForward(SYNC_STRATEGY.DISABLE)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
}
|
2016-09-24 08:20:28 +00:00
|
|
|
},
|
|
|
|
{
|
2020-04-25 07:04:44 +00:00
|
|
|
text_func = function()
|
|
|
|
return T(_("Sync to a previous record (%1)"), getNameStrategy(self.kosync_whisper_backward))
|
2016-09-24 08:20:28 +00:00
|
|
|
end,
|
2020-04-25 07:04:44 +00:00
|
|
|
sub_item_table = {
|
|
|
|
{
|
|
|
|
text = _("Auto"),
|
|
|
|
checked_func = function()
|
|
|
|
return self.kosync_whisper_backward == SYNC_STRATEGY.WHISPER
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:setWhisperBackward(SYNC_STRATEGY.WHISPER)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Prompt"),
|
|
|
|
checked_func = function()
|
|
|
|
return self.kosync_whisper_backward == SYNC_STRATEGY.PROMPT
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:setWhisperBackward(SYNC_STRATEGY.PROMPT)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Disable"),
|
|
|
|
checked_func = function()
|
|
|
|
return self.kosync_whisper_backward == SYNC_STRATEGY.DISABLE
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:setWhisperBackward(SYNC_STRATEGY.DISABLE)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
}
|
2016-09-24 08:20:28 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-03-10 07:09:42 +00:00
|
|
|
{
|
2016-07-30 00:38:02 +00:00
|
|
|
text = _("Push progress from this device"),
|
|
|
|
enabled_func = function()
|
|
|
|
return self.kosync_userkey ~= nil
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:updateProgress(true)
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Pull progress from other devices"),
|
2015-03-10 07:09:42 +00:00
|
|
|
enabled_func = function()
|
|
|
|
return self.kosync_userkey ~= nil
|
|
|
|
end,
|
|
|
|
callback = function()
|
|
|
|
self:getProgress(true)
|
|
|
|
end,
|
2015-09-17 15:27:19 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Custom sync server"),
|
2018-09-04 21:55:58 +00:00
|
|
|
keep_menu_open = true,
|
2017-03-28 22:47:18 +00:00
|
|
|
tap_input_func = function()
|
|
|
|
return {
|
2019-08-24 07:25:38 +00:00
|
|
|
-- @translators Server address defined by user for progress sync.
|
2017-03-28 22:47:18 +00:00
|
|
|
title = _("Custom progress sync server address"),
|
|
|
|
input = self.kosync_custom_server or "https://",
|
|
|
|
type = "text",
|
|
|
|
callback = function(input)
|
|
|
|
self:setCustomServer(input)
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
end,
|
2015-09-17 15:27:19 +00:00
|
|
|
},
|
2015-03-09 12:20:32 +00:00
|
|
|
}
|
2017-02-28 21:46:32 +00:00
|
|
|
}
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
2015-09-17 15:27:19 +00:00
|
|
|
function KOSync:setCustomServer(server)
|
2020-06-13 11:47:07 +00:00
|
|
|
logger.dbg("set custom server", server)
|
2015-09-17 15:27:19 +00:00
|
|
|
self.kosync_custom_server = server ~= "" and server or nil
|
2017-05-16 09:11:11 +00:00
|
|
|
self:saveSettings()
|
2015-09-17 15:27:19 +00:00
|
|
|
end
|
|
|
|
|
2017-08-08 06:29:57 +00:00
|
|
|
function KOSync:setWhisperForward(strategy)
|
|
|
|
self.kosync_whisper_forward = strategy
|
|
|
|
self:saveSettings()
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:setWhisperBackward(strategy)
|
|
|
|
self.kosync_whisper_backward = strategy
|
|
|
|
self:saveSettings()
|
|
|
|
end
|
|
|
|
|
2015-03-09 12:20:32 +00:00
|
|
|
function KOSync:login()
|
Various Wi-Fi QoL improvements (#6424)
* Revamped most actions that require an internet connection to a new/fixed backend that allows forwarding the initial action and running it automatically once connected. (i.e., it'll allow you to set "Action when Wi-Fi is off" to "turn_on", and whatch stuff connect and do what you wanted automatically without having to re-click anywhere instead of showing you a Wi-Fi prompt and then not doing anything without any other feedback).
* Speaking of, fixed the "turn_on" beforeWifi action to, well, actually work. It's no longer marked as experimental.
* Consistently use "Wi-Fi" everywhere.
* On Kobo/Cervantes/Sony, implemented a "Kill Wi-Fi connection when inactive" system that will automatically disconnect from Wi-Fi after sustained *network* inactivity (i.e., you can keep reading, it'll eventually turn off on its own). This should be smart and flexible enough not to murder Wi-Fi while you need it, while still not keeping it uselessly on and murdering your battery.
(i.e., enable that + turn Wi-Fi on when off and enjoy never having to bother about Wi-Fi ever again).
* Made sending `NetworkConnected` / `NetworkDisconnected` events consistent (they were only being sent... sometimes, which made relying on 'em somewhat problematic).
* restoreWifiAsync is now only run when really needed (i.e., we no longer stomp on an existing working connection just for the hell of it).
* We no longer attempt to kill a bogus non-existent Wi-Fi connection when going to suspend, we only do it when it's actually needed.
* Every method of enabling Wi-Fi will now properly tear down Wi-Fi on failure, instead of leaving it in an undefined state.
* Fixed an issue in the fancy crash screen on Kobo/reMarkable that could sometime lead to the log excerpt being missing.
* Worked-around a number of sneaky issues related to low-level Wi-Fi/DHCP/DNS handling on Kobo (see the lengthy comments [below](https://github.com/koreader/koreader/pull/6424#issuecomment-663881059) for details). Fix #6421
Incidentally, this should also fix the inconsistencies experienced re: Wi-Fi behavior in Nickel when toggling between KOReader and Nickel (use NM/KFMon, and run a current FW for best results).
* For developers, this involves various cleanups around NetworkMgr and NetworkListener. Documentation is in-line, above the concerned functions.
2020-07-27 01:39:06 +00:00
|
|
|
if NetworkMgr:willRerunWhenOnline(function() self:login() end) then
|
2019-11-06 20:02:41 +00:00
|
|
|
return
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
Various Wi-Fi QoL improvements (#6424)
* Revamped most actions that require an internet connection to a new/fixed backend that allows forwarding the initial action and running it automatically once connected. (i.e., it'll allow you to set "Action when Wi-Fi is off" to "turn_on", and whatch stuff connect and do what you wanted automatically without having to re-click anywhere instead of showing you a Wi-Fi prompt and then not doing anything without any other feedback).
* Speaking of, fixed the "turn_on" beforeWifi action to, well, actually work. It's no longer marked as experimental.
* Consistently use "Wi-Fi" everywhere.
* On Kobo/Cervantes/Sony, implemented a "Kill Wi-Fi connection when inactive" system that will automatically disconnect from Wi-Fi after sustained *network* inactivity (i.e., you can keep reading, it'll eventually turn off on its own). This should be smart and flexible enough not to murder Wi-Fi while you need it, while still not keeping it uselessly on and murdering your battery.
(i.e., enable that + turn Wi-Fi on when off and enjoy never having to bother about Wi-Fi ever again).
* Made sending `NetworkConnected` / `NetworkDisconnected` events consistent (they were only being sent... sometimes, which made relying on 'em somewhat problematic).
* restoreWifiAsync is now only run when really needed (i.e., we no longer stomp on an existing working connection just for the hell of it).
* We no longer attempt to kill a bogus non-existent Wi-Fi connection when going to suspend, we only do it when it's actually needed.
* Every method of enabling Wi-Fi will now properly tear down Wi-Fi on failure, instead of leaving it in an undefined state.
* Fixed an issue in the fancy crash screen on Kobo/reMarkable that could sometime lead to the log excerpt being missing.
* Worked-around a number of sneaky issues related to low-level Wi-Fi/DHCP/DNS handling on Kobo (see the lengthy comments [below](https://github.com/koreader/koreader/pull/6424#issuecomment-663881059) for details). Fix #6421
Incidentally, this should also fix the inconsistencies experienced re: Wi-Fi behavior in Nickel when toggling between KOReader and Nickel (use NM/KFMon, and run a current FW for best results).
* For developers, this involves various cleanups around NetworkMgr and NetworkListener. Documentation is in-line, above the concerned functions.
2020-07-27 01:39:06 +00:00
|
|
|
|
2015-03-09 12:20:32 +00:00
|
|
|
self.login_dialog = LoginDialog:new{
|
2015-03-10 07:49:33 +00:00
|
|
|
title = self.title,
|
2015-03-09 12:20:32 +00:00
|
|
|
username = self.kosync_username or "",
|
|
|
|
buttons = {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
text = _("Cancel"),
|
|
|
|
enabled = true,
|
|
|
|
callback = function()
|
|
|
|
self:closeDialog()
|
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Login"),
|
|
|
|
enabled = true,
|
|
|
|
callback = function()
|
|
|
|
local username, password = self:getCredential()
|
2020-02-25 19:40:50 +00:00
|
|
|
local ok, err = validateUser(username, password)
|
|
|
|
if not ok then
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = T(_("Cannot login: %1"), err),
|
|
|
|
timeout = 2,
|
|
|
|
})
|
|
|
|
else
|
|
|
|
self:closeDialog()
|
|
|
|
UIManager:scheduleIn(0.5, function()
|
|
|
|
self:doLogin(username, password)
|
|
|
|
end)
|
2015-03-09 12:20:32 +00:00
|
|
|
|
2020-02-25 19:40:50 +00:00
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Logging in. Please wait…"),
|
|
|
|
timeout = 1,
|
|
|
|
})
|
|
|
|
end
|
2015-03-09 12:20:32 +00:00
|
|
|
end,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
text = _("Register"),
|
2015-03-10 07:49:33 +00:00
|
|
|
enabled = true,
|
2015-03-09 12:20:32 +00:00
|
|
|
callback = function()
|
|
|
|
local username, password = self:getCredential()
|
2020-02-25 19:40:50 +00:00
|
|
|
local ok, err = validateUser(username, password)
|
|
|
|
if not ok then
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = T(_("Cannot register: %1"), err),
|
|
|
|
timeout = 2,
|
|
|
|
})
|
|
|
|
else
|
|
|
|
self:closeDialog()
|
|
|
|
UIManager:scheduleIn(0.5, function()
|
|
|
|
self:doRegister(username, password)
|
|
|
|
end)
|
2015-03-09 12:20:32 +00:00
|
|
|
|
2020-02-25 19:40:50 +00:00
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Registering. Please wait…"),
|
|
|
|
timeout = 1,
|
|
|
|
})
|
|
|
|
end
|
2015-03-09 12:20:32 +00:00
|
|
|
end,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2020-06-13 11:47:07 +00:00
|
|
|
width = math.floor(Screen:getWidth() * 0.8),
|
|
|
|
height = math.floor(Screen:getHeight() * 0.4),
|
2015-03-09 12:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UIManager:show(self.login_dialog)
|
2018-03-30 10:46:36 +00:00
|
|
|
self.login_dialog:onShowKeyboard()
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:closeDialog()
|
|
|
|
self.login_dialog:onClose()
|
|
|
|
UIManager:close(self.login_dialog)
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:getCredential()
|
|
|
|
return self.login_dialog:getCredential()
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:doRegister(username, password)
|
|
|
|
local KOSyncClient = require("KOSyncClient")
|
|
|
|
local client = KOSyncClient:new{
|
2015-09-17 15:27:19 +00:00
|
|
|
custom_url = self.kosync_custom_server,
|
2015-03-09 12:20:32 +00:00
|
|
|
service_spec = self.path .. "/api.json"
|
|
|
|
}
|
2020-06-13 11:47:07 +00:00
|
|
|
-- on Android to avoid ANR (no-op on other platforms)
|
2020-06-13 10:57:08 +00:00
|
|
|
Device:setIgnoreInput(true)
|
2020-07-21 21:25:46 +00:00
|
|
|
local userkey = md5(password)
|
2015-03-09 12:20:32 +00:00
|
|
|
local ok, status, body = pcall(client.register, client, username, userkey)
|
2016-09-24 08:20:28 +00:00
|
|
|
if not ok then
|
2015-03-09 12:20:32 +00:00
|
|
|
if status then
|
|
|
|
UIManager:show(InfoMessage:new{
|
2016-09-24 08:20:28 +00:00
|
|
|
text = _("An error occurred while registering:") ..
|
|
|
|
"\n" .. status,
|
2015-03-09 12:20:32 +00:00
|
|
|
})
|
|
|
|
else
|
|
|
|
UIManager:show(InfoMessage:new{
|
2016-09-24 08:20:28 +00:00
|
|
|
text = _("An unknown error occurred while registering."),
|
2015-03-09 12:20:32 +00:00
|
|
|
})
|
|
|
|
end
|
2016-09-24 08:20:28 +00:00
|
|
|
elseif status then
|
|
|
|
self.kosync_username = username
|
|
|
|
self.kosync_userkey = userkey
|
2019-08-29 08:05:49 +00:00
|
|
|
self._menu_to_update:updateItems()
|
2016-09-24 08:20:28 +00:00
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Registered to KOReader server."),
|
|
|
|
})
|
|
|
|
else
|
|
|
|
UIManager:show(InfoMessage:new{
|
2019-08-07 10:37:07 +00:00
|
|
|
text = body and body.message or _("Unknown server error"),
|
2016-09-24 08:20:28 +00:00
|
|
|
})
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
2020-06-13 10:57:08 +00:00
|
|
|
Device:setIgnoreInput(false)
|
2017-05-16 09:11:11 +00:00
|
|
|
self:saveSettings()
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:doLogin(username, password)
|
|
|
|
local KOSyncClient = require("KOSyncClient")
|
|
|
|
local client = KOSyncClient:new{
|
2015-09-17 15:27:19 +00:00
|
|
|
custom_url = self.kosync_custom_server,
|
2015-03-09 12:20:32 +00:00
|
|
|
service_spec = self.path .. "/api.json"
|
|
|
|
}
|
2020-06-13 10:57:08 +00:00
|
|
|
Device:setIgnoreInput(true)
|
2020-07-21 21:25:46 +00:00
|
|
|
local userkey = md5(password)
|
2015-03-09 12:20:32 +00:00
|
|
|
local ok, status, body = pcall(client.authorize, client, username, userkey)
|
2016-09-24 08:20:28 +00:00
|
|
|
if not ok then
|
2015-03-09 12:20:32 +00:00
|
|
|
if status then
|
|
|
|
UIManager:show(InfoMessage:new{
|
2016-09-24 08:20:28 +00:00
|
|
|
text = _("An error occurred while logging in:") ..
|
|
|
|
"\n" .. status,
|
2015-03-09 12:20:32 +00:00
|
|
|
})
|
|
|
|
else
|
|
|
|
UIManager:show(InfoMessage:new{
|
2016-09-24 08:20:28 +00:00
|
|
|
text = _("An unknown error occurred while logging in."),
|
2015-03-09 12:20:32 +00:00
|
|
|
})
|
|
|
|
end
|
2020-06-13 10:57:08 +00:00
|
|
|
Device:setIgnoreInput(false)
|
2016-09-24 08:20:28 +00:00
|
|
|
return
|
|
|
|
elseif status then
|
|
|
|
self.kosync_username = username
|
|
|
|
self.kosync_userkey = userkey
|
2019-08-29 08:05:49 +00:00
|
|
|
self._menu_to_update:updateItems()
|
2016-09-24 08:20:28 +00:00
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Logged in to KOReader server."),
|
|
|
|
})
|
|
|
|
else
|
|
|
|
UIManager:show(InfoMessage:new{
|
2019-08-07 10:37:07 +00:00
|
|
|
text = body and body.message or _("Unknown server error"),
|
2016-09-24 08:20:28 +00:00
|
|
|
})
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
2020-06-13 10:57:08 +00:00
|
|
|
Device:setIgnoreInput(false)
|
2017-05-16 09:11:11 +00:00
|
|
|
self:saveSettings()
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:logout()
|
|
|
|
self.kosync_userkey = nil
|
2015-03-10 07:09:42 +00:00
|
|
|
self.kosync_auto_sync = true
|
2019-08-29 08:05:49 +00:00
|
|
|
self._menu_to_update:updateItems()
|
2017-05-16 09:11:11 +00:00
|
|
|
self:saveSettings()
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:getLastPercent()
|
|
|
|
if self.ui.document.info.has_pages then
|
2020-04-15 10:50:13 +00:00
|
|
|
return Math.roundPercent(self.ui.paging:getLastPercent())
|
2015-03-09 12:20:32 +00:00
|
|
|
else
|
2020-04-15 10:50:13 +00:00
|
|
|
return Math.roundPercent(self.ui.rolling:getLastPercent())
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:getLastProgress()
|
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
return self.ui.paging:getLastProgress()
|
|
|
|
else
|
|
|
|
return self.ui.rolling:getLastProgress()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:syncToProgress(progress)
|
2020-06-13 11:47:07 +00:00
|
|
|
logger.dbg("sync to", progress)
|
2015-03-09 12:20:32 +00:00
|
|
|
if self.ui.document.info.has_pages then
|
|
|
|
self.ui:handleEvent(Event:new("GotoPage", tonumber(progress)))
|
|
|
|
else
|
|
|
|
self.ui:handleEvent(Event:new("GotoXPointer", progress))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-07-30 00:38:02 +00:00
|
|
|
function KOSync:updateProgress(manual)
|
2016-09-24 08:20:28 +00:00
|
|
|
if not self.kosync_username or not self.kosync_userkey then
|
|
|
|
if manual then
|
|
|
|
promptLogin()
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
2016-09-24 08:20:28 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local KOSyncClient = require("KOSyncClient")
|
|
|
|
local client = KOSyncClient:new{
|
|
|
|
custom_url = self.kosync_custom_server,
|
|
|
|
service_spec = self.path .. "/api.json"
|
|
|
|
}
|
|
|
|
local doc_digest = self.view.document:fastDigest()
|
|
|
|
local progress = self:getLastProgress()
|
|
|
|
local percentage = self:getLastPercent()
|
|
|
|
local ok, err = pcall(client.update_progress,
|
|
|
|
client,
|
|
|
|
self.kosync_username,
|
|
|
|
self.kosync_userkey,
|
|
|
|
doc_digest,
|
|
|
|
progress,
|
|
|
|
percentage,
|
2020-06-13 11:13:23 +00:00
|
|
|
Device.model,
|
2016-09-24 08:20:28 +00:00
|
|
|
self.kosync_device_id,
|
|
|
|
function(ok, body)
|
2020-06-13 11:47:07 +00:00
|
|
|
logger.dbg("update progress for", self.view.document.file, ok)
|
2016-09-24 08:20:28 +00:00
|
|
|
if manual then
|
|
|
|
if ok then
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Progress has been pushed."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
else
|
|
|
|
showSyncError()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
if not ok then
|
|
|
|
if manual then showSyncError() end
|
2020-06-13 11:47:07 +00:00
|
|
|
if err then logger.dbg("err:", err) end
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-10 07:09:42 +00:00
|
|
|
function KOSync:getProgress(manual)
|
2016-09-24 08:20:28 +00:00
|
|
|
if not self.kosync_username or not self.kosync_userkey then
|
|
|
|
if manual then
|
|
|
|
promptLogin()
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local KOSyncClient = require("KOSyncClient")
|
|
|
|
local client = KOSyncClient:new{
|
|
|
|
custom_url = self.kosync_custom_server,
|
|
|
|
service_spec = self.path .. "/api.json"
|
|
|
|
}
|
|
|
|
local doc_digest = self.view.document:fastDigest()
|
|
|
|
local ok, err = pcall(client.get_progress,
|
|
|
|
client,
|
|
|
|
self.kosync_username,
|
|
|
|
self.kosync_userkey,
|
|
|
|
doc_digest,
|
|
|
|
function(ok, body)
|
2020-06-13 11:47:07 +00:00
|
|
|
logger.dbg("get progress for", self.view.document.file, ok, body)
|
2016-09-24 08:20:28 +00:00
|
|
|
if not ok or not body then
|
|
|
|
if manual then
|
2016-07-30 00:38:02 +00:00
|
|
|
showSyncError()
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
2016-09-24 08:20:28 +00:00
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if not body.percentage then
|
|
|
|
if manual then
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("No progress found for this document."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2020-06-13 11:13:23 +00:00
|
|
|
if body.device == Device.model
|
2016-09-24 08:20:28 +00:00
|
|
|
and body.device_id == self.kosync_device_id then
|
|
|
|
if manual then
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("Latest progress is coming from this device."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2020-04-15 13:25:29 +00:00
|
|
|
body.percentage = Math.roundPercent(body.percentage)
|
2016-09-24 08:20:28 +00:00
|
|
|
local progress = self:getLastProgress()
|
|
|
|
local percentage = self:getLastPercent()
|
2020-06-13 11:47:07 +00:00
|
|
|
logger.dbg("current progress", percentage)
|
2016-09-24 08:20:28 +00:00
|
|
|
|
|
|
|
if percentage == body.percentage
|
|
|
|
or body.progress == progress then
|
|
|
|
if manual then
|
|
|
|
UIManager:show(InfoMessage:new{
|
|
|
|
text = _("The progress has already been synchronized."),
|
|
|
|
timeout = 3,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- The progress needs to be updated.
|
|
|
|
if manual then
|
|
|
|
-- If user actively pulls progress from other devices, we always update the
|
|
|
|
-- progress without further confirmation.
|
|
|
|
self:syncToProgress(body.progress)
|
|
|
|
showSyncedMessage()
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local self_older
|
|
|
|
if body.timestamp ~= nil then
|
|
|
|
self_older = (body.timestamp > self.last_page_turn_ticks)
|
|
|
|
else
|
|
|
|
-- If we are working with old sync server, we can only use
|
|
|
|
-- percentage field.
|
|
|
|
self_older = (body.percentage > percentage)
|
|
|
|
end
|
|
|
|
if self_older then
|
|
|
|
if self.kosync_whisper_forward == SYNC_STRATEGY.WHISPER then
|
|
|
|
self:syncToProgress(body.progress)
|
|
|
|
showSyncedMessage()
|
|
|
|
elseif self.kosync_whisper_forward == SYNC_STRATEGY.PROMPT then
|
|
|
|
UIManager:show(ConfirmBox:new{
|
2016-10-17 09:54:20 +00:00
|
|
|
text = T(_("Sync to latest location %1% from device '%2'?"),
|
2016-09-24 08:20:28 +00:00
|
|
|
Math.round(body.percentage * 100),
|
|
|
|
body.device),
|
|
|
|
ok_callback = function()
|
|
|
|
self:syncToProgress(body.progress)
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
else -- if not self_older then
|
|
|
|
if self.kosync_whisper_backward == SYNC_STRATEGY.WHISPER then
|
|
|
|
self:syncToProgress(body.progress)
|
|
|
|
showSyncedMessage()
|
|
|
|
elseif self.kosync_whisper_backward == SYNC_STRATEGY.PROMPT then
|
|
|
|
UIManager:show(ConfirmBox:new{
|
2016-10-17 09:54:20 +00:00
|
|
|
text = T(_("Sync to previous location %1% from device '%2'?"),
|
2016-09-24 08:20:28 +00:00
|
|
|
Math.round(body.percentage * 100),
|
|
|
|
body.device),
|
|
|
|
ok_callback = function()
|
|
|
|
self:syncToProgress(body.progress)
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
if not ok then
|
|
|
|
if manual then showSyncError() end
|
2020-06-13 11:47:07 +00:00
|
|
|
if err then logger.dbg("err:", err) end
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-05-16 09:11:11 +00:00
|
|
|
function KOSync:saveSettings()
|
2015-03-09 12:20:32 +00:00
|
|
|
local settings = {
|
2015-09-17 15:27:19 +00:00
|
|
|
custom_server = self.kosync_custom_server,
|
2015-03-09 12:20:32 +00:00
|
|
|
username = self.kosync_username,
|
|
|
|
userkey = self.kosync_userkey,
|
2015-03-10 07:09:42 +00:00
|
|
|
auto_sync = self.kosync_auto_sync,
|
2016-09-24 08:20:28 +00:00
|
|
|
whisper_forward =
|
|
|
|
(self.kosync_whisper_forward == SYNC_STRATEGY.DEFAULT_FORWARD
|
|
|
|
and nil
|
|
|
|
or self.kosync_whisper_forward),
|
|
|
|
whisper_backward =
|
|
|
|
(self.kosync_whisper_backward == SYNC_STRATEGY.DEFAULT_BACKWARD
|
|
|
|
and nil
|
|
|
|
or self.kosync_whisper_backward),
|
2015-03-09 12:20:32 +00:00
|
|
|
}
|
|
|
|
G_reader_settings:saveSetting("kosync", settings)
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:onCloseDocument()
|
2020-06-13 11:47:07 +00:00
|
|
|
logger.dbg("on close document")
|
2015-03-10 07:09:42 +00:00
|
|
|
if self.kosync_auto_sync then
|
|
|
|
self:updateProgress()
|
|
|
|
end
|
2015-03-09 12:20:32 +00:00
|
|
|
end
|
|
|
|
|
2016-09-24 08:20:28 +00:00
|
|
|
function KOSync:_onPageUpdate(page)
|
|
|
|
if page == nil then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if self.last_page == -1 then
|
|
|
|
self.last_page = page
|
|
|
|
elseif self.last_page ~= page then
|
|
|
|
self.last_page = page
|
|
|
|
self.last_page_turn_ticks = os.time()
|
|
|
|
self.page_update_times = self.page_update_times + 1
|
2020-01-01 11:27:51 +00:00
|
|
|
if SYNC_PAGING_COUNT ~= nil
|
|
|
|
and (SYNC_PAGING_COUNT <= 0
|
|
|
|
or self.page_update_times == SYNC_PAGING_COUNT) then
|
2016-09-24 08:20:28 +00:00
|
|
|
self.page_update_times = 0
|
|
|
|
UIManager:scheduleIn(1, function() self:updateProgress() end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:_onResume()
|
|
|
|
UIManager:scheduleIn(1, function() self:getProgress() end)
|
|
|
|
end
|
|
|
|
|
2016-10-23 22:27:39 +00:00
|
|
|
function KOSync:_onFlushSettings()
|
2017-05-21 06:36:41 +00:00
|
|
|
if self.ui == nil or self.ui.document == nil then return end
|
2016-10-23 22:27:39 +00:00
|
|
|
self:updateProgress()
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:_onNetworkConnected()
|
|
|
|
self:_onResume()
|
|
|
|
end
|
|
|
|
|
2020-05-05 16:51:02 +00:00
|
|
|
function KOSync:onKOSyncPushProgress()
|
|
|
|
if not self.kosync_userkey then return end
|
|
|
|
self:updateProgress(true)
|
|
|
|
end
|
|
|
|
|
|
|
|
function KOSync:onKOSyncPullProgress()
|
|
|
|
if not self.kosync_userkey then return end
|
|
|
|
self:getProgress(true)
|
|
|
|
end
|
|
|
|
|
2016-09-24 08:20:28 +00:00
|
|
|
function KOSync:registerEvents()
|
|
|
|
if self.kosync_auto_sync then
|
|
|
|
self.onPageUpdate = self._onPageUpdate
|
|
|
|
self.onResume = self._onResume
|
2016-10-23 22:27:39 +00:00
|
|
|
self.onFlushSettings = self._onFlushSettings
|
|
|
|
self.onNetworkConnected = self._onNetworkConnected
|
2016-09-24 08:20:28 +00:00
|
|
|
else
|
|
|
|
self.onPageUpdate = nil
|
|
|
|
self.onResume = nil
|
2016-10-23 22:27:39 +00:00
|
|
|
self.onFlushSettings = nil
|
|
|
|
self.onNetworkConnected = nil
|
2016-09-24 08:20:28 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-09 12:20:32 +00:00
|
|
|
return KOSync
|