Cloud-based sync for 2 plugins: reading statistics and vocabulary builder (#9709)

This commit adds cross-device sync ability for two plugins: reading statistics and vocabulary builder. It relies on user setting up a Cloud server (DropBox and WebDAV but not FTP though) and designating a path. Behind the curtains sqlite databases are being passed around and updated.

UI-wise, for the statistics plugin, two new menu items Synchronize now and Cloud sync to set it up (might not be the best wording) are added. As for vocabulary builder, a similar Cloud sync button is added to the menu and a shortcut icon button to Synchronize now is pinned at the bottom corner.

CloudStorage new features: WebDAV creating folders and uploading files. And a new widget-like sync server chooser. In the end I decided not to add automatic sync, as the SQL commands part seem a bit much.
This commit is contained in:
weijiuqiao
2022-11-11 22:53:06 +08:00
committed by GitHub
parent 4f3000e882
commit 8500fdd519
8 changed files with 727 additions and 19 deletions

View File

@@ -59,7 +59,7 @@ function WebDavApi:urlEncode(url_data)
return url_data
end
function WebDavApi:listFolder(address, user, pass, folder_path)
function WebDavApi:listFolder(address, user, pass, folder_path, folder_mode)
local path = self:urlEncode( folder_path )
local webdav_list = {}
local webdav_file = {}
@@ -169,6 +169,14 @@ function WebDavApi:listFolder(address, user, pass, folder_path)
type = files.type,
})
end
if folder_mode then
table.insert(webdav_list, 1, {
text = _("Long-press to choose current folder"),
url = folder_path,
type = "folder_long_press",
bold = true
})
end
return webdav_list
end
@@ -187,7 +195,42 @@ function WebDavApi:downloadFile(file_url, user, pass, local_path)
logger.warn("WebDavApi: Download failure:", status or code or "network unreachable")
logger.dbg("WebDavApi: Response headers:", headers)
end
return code, (headers or {}).etag
end
function WebDavApi:uploadFile(file_url, user, pass, local_path, etag)
socketutil:set_timeout(socketutil.FILE_BLOCK_TIMEOUT, socketutil.FILE_TOTAL_TIMEOUT)
local code, _, status = socket.skip(1, http.request{
url = file_url,
method = "PUT",
source = ltn12.source.file(io.open(local_path, "r")),
user = user,
password = pass,
headers = {
["If-Match"] = etag
}
})
socketutil:reset_timeout()
if code < 200 or code > 299 then
logger.warn("WebDavApi: upload failure:", status or code or "network unreachable")
end
return code
end
function WebDavApi:createFolder(folder_url, user, pass, folder_name)
socketutil:set_timeout(socketutil.FILE_BLOCK_TIMEOUT, socketutil.FILE_TOTAL_TIMEOUT)
local code, _, status = socket.skip(1, http.request{
url = folder_url,
method = "MKCOL",
user = user,
password = pass,
})
socketutil:reset_timeout()
if code ~= 201 then
logger.warn("WebDavApi: create folder failure:", status or code or "network unreachable")
end
return code
end
return WebDavApi