Compare commits
2
Commits
4ea3966e37
...
656505eda7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
656505eda7 | ||
|
|
9467bdb2bd |
@@ -126,6 +126,13 @@ function BookhoardAPI:syncProgress(book_data, sync_mode)
|
|||||||
}, PROGRESS_TIMEOUTS)
|
}, PROGRESS_TIMEOUTS)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Read-only SHA-256 → book UUID lookup. Used to link a freshly downloaded
|
||||||
|
-- book WITHOUT pushing progress (a push would transmit the device's
|
||||||
|
-- first-page position and clobber/conflict with real server progress).
|
||||||
|
function BookhoardAPI:resolveBook(sha256)
|
||||||
|
return self:_request("GET", "/api/sync/koreader/resolve?sha256=" .. sha256, nil, PROGRESS_TIMEOUTS)
|
||||||
|
end
|
||||||
|
|
||||||
function BookhoardAPI:getMetadata(uuid)
|
function BookhoardAPI:getMetadata(uuid)
|
||||||
return self:_request("GET", "/api/sync/koreader/metadata/" .. uuid, nil, PROGRESS_TIMEOUTS)
|
return self:_request("GET", "/api/sync/koreader/metadata/" .. uuid, nil, PROGRESS_TIMEOUTS)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -121,17 +121,13 @@ end
|
|||||||
function Bookhoard:onReaderReady()
|
function Bookhoard:onReaderReady()
|
||||||
if self.settings.auto_sync then
|
if self.settings.auto_sync then
|
||||||
UIManager:nextTick(function()
|
UIManager:nextTick(function()
|
||||||
-- On the first open of a freshly downloaded book there is no cached
|
-- Pull-first on every open. A freshly downloaded book has no cached
|
||||||
-- bookhoard UUID yet (it is only learned from a successful push
|
-- bookhoard UUID yet; getProgress resolves it by SHA-256 with a
|
||||||
-- response). Pulling now would just fail with "Push progress first".
|
-- read-only lookup (no progress push). The previous push-to-
|
||||||
-- Instead, push once to bootstrap identity: the server resolves the
|
-- bootstrap strategy transmitted the device's first-page position
|
||||||
-- book by SHA-256 (format-aware) and returns the UUID, which we then
|
-- to the server on books already mid-read elsewhere, creating a
|
||||||
-- cache. After that, push and pull both work without ordering.
|
-- sync conflict before the first pull could ever happen.
|
||||||
if not self:getBookhoardUUID() then
|
self:getProgress(true, false)
|
||||||
self:updateProgress(true, false)
|
|
||||||
else
|
|
||||||
self:getProgress(true, false)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
self:registerEvents()
|
self:registerEvents()
|
||||||
@@ -994,7 +990,15 @@ function Bookhoard:updateProgress(ensure_networking, interactive)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self.settings.sync_progress then return end
|
if not self.settings.sync_progress then
|
||||||
|
if interactive then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("Reading progress sync is disabled (see What to sync)."),
|
||||||
|
timeout = 3,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if not self.ui.document then
|
if not self.ui.document then
|
||||||
if interactive then
|
if interactive then
|
||||||
@@ -1011,9 +1015,19 @@ function Bookhoard:updateProgress(ensure_networking, interactive)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if ensure_networking
|
if ensure_networking then
|
||||||
and NetworkMgr:willRerunWhenOnline(function() self:updateProgress(ensure_networking, interactive) end) then
|
-- Same silent-drop case as getProgress: connected but no internet
|
||||||
return
|
-- means willRerunWhenOnline neither reruns nor shows any UI.
|
||||||
|
if interactive and NetworkMgr:isConnected() and not NetworkMgr:isOnline() then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("No internet connection. Progress was not pushed."),
|
||||||
|
timeout = 3,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if NetworkMgr:willRerunWhenOnline(function() self:updateProgress(ensure_networking, interactive) end) then
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
UIManager:scheduleIn(0.5, function()
|
UIManager:scheduleIn(0.5, function()
|
||||||
@@ -1082,30 +1096,53 @@ function Bookhoard:getProgress(ensure_networking, interactive)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self.settings.sync_progress then return end
|
if not self.settings.sync_progress then
|
||||||
|
if interactive then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("Reading progress sync is disabled (see What to sync)."),
|
||||||
|
timeout = 3,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local now = UIManager:getElapsedTimeSinceBoot()
|
local now = UIManager:getElapsedTimeSinceBoot()
|
||||||
if not interactive and now - self.pull_timestamp <= API_CALL_DEBOUNCE_DELAY then
|
if not interactive and now - self.pull_timestamp <= API_CALL_DEBOUNCE_DELAY then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if ensure_networking
|
if ensure_networking then
|
||||||
and NetworkMgr:willRerunWhenOnline(function() self:getProgress(ensure_networking, interactive) end) then
|
-- willRerunWhenOnline silently drops the action (no rerun, no UI)
|
||||||
return
|
-- when the device is connected at the IP level but has no internet
|
||||||
|
-- access: it only guarantees isConnected, and in that state the
|
||||||
|
-- framework re-connects without ever invoking the callback. Catch
|
||||||
|
-- that state up front so an interactive pull never no-ops silently.
|
||||||
|
if interactive and NetworkMgr:isConnected() and not NetworkMgr:isOnline() then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("No internet connection. Progress was not pulled."),
|
||||||
|
timeout = 3,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if NetworkMgr:willRerunWhenOnline(function() self:getProgress(ensure_networking, interactive) end) then
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local book_uuid = self:getBookhoardUUID()
|
local book_uuid = self:getBookhoardUUID()
|
||||||
if not book_uuid then
|
if not book_uuid then
|
||||||
-- No cached UUID yet (first open of a freshly downloaded book). Bootstrap
|
-- No cached UUID yet (first open of a freshly downloaded book). Link
|
||||||
-- it by pushing once: the server resolves the book by SHA-256 and returns
|
-- the book with a read-only SHA-256 lookup, then pull. Progress is
|
||||||
-- the UUID, which the push handler caches. Then retry the pull.
|
-- never pushed here: the device sits on the first page of a book the
|
||||||
|
-- server may hold mid-read, and pushing that would overwrite/server-
|
||||||
|
-- conflict the real progress before the pull could deliver it.
|
||||||
if interactive then
|
if interactive then
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Linking this book to Bookhoard first…"),
|
text = _("Linking this book to Bookhoard first…"),
|
||||||
timeout = 3,
|
timeout = 3,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
self:_bootstrapUUIDThenPull(interactive)
|
self:_linkBookThenPull(interactive)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1116,9 +1153,70 @@ function Bookhoard:getProgress(ensure_networking, interactive)
|
|||||||
self.pull_timestamp = now
|
self.pull_timestamp = now
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Establish the bookhoard UUID for the current document by pushing once, then
|
-- Link the current document to Bookhoard WITHOUT pushing progress, then run
|
||||||
-- (once cached) perform the originally-requested pull. Used when a pull is
|
-- the pull. The UUID is learned via a read-only SHA-256 resolve; only when
|
||||||
-- requested before any push has run on a newly downloaded book.
|
-- the server does not know the hash at all (sideloaded book) do we fall back
|
||||||
|
-- to the legacy push-bootstrap, and only for background (non-interactive)
|
||||||
|
-- flows — a user-initiated pull must never push this device's position.
|
||||||
|
function Bookhoard:_linkBookThenPull(interactive)
|
||||||
|
local file_sha256 = self:getFileSHA256()
|
||||||
|
if not file_sha256 then
|
||||||
|
if interactive then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("Could not read this file to link it with Bookhoard."),
|
||||||
|
timeout = 3,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
UIManager:scheduleIn(0.5, function()
|
||||||
|
local api = self:getAPI()
|
||||||
|
local ok, result = api:resolveBook(file_sha256)
|
||||||
|
|
||||||
|
UIManager:nextTick(function()
|
||||||
|
if not self.ui.doc_settings then return end
|
||||||
|
|
||||||
|
if ok and type(result) == "table" and result.book_uuid then
|
||||||
|
self.ui.doc_settings:saveSetting("bookhoard_uuid", result.book_uuid)
|
||||||
|
self.ui.doc_settings:flush()
|
||||||
|
logger.dbg("Bookhoard: linked book by SHA-256 to", result.book_uuid)
|
||||||
|
self:_doGetProgress(interactive)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if result and result.status == 404 then
|
||||||
|
-- Genuinely unknown to the server (sideloaded book). The
|
||||||
|
-- legacy push-bootstrap only ever linked such books via fuzzy
|
||||||
|
-- title/author matching; keep that as a background attempt,
|
||||||
|
-- but tell interactive users to push explicitly.
|
||||||
|
if interactive then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("This book is not in your Bookhoard library yet. Push progress to link it."),
|
||||||
|
timeout = 4,
|
||||||
|
})
|
||||||
|
else
|
||||||
|
self:_bootstrapUUIDThenPull(interactive)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
logger.warn("Bookhoard: failed to resolve book by SHA-256")
|
||||||
|
if interactive then
|
||||||
|
UIManager:show(InfoMessage:new{
|
||||||
|
text = _("Could not reach Bookhoard. Check your network connection and try again."),
|
||||||
|
timeout = 4,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Legacy fallback: establish the bookhoard UUID for the current document by
|
||||||
|
-- pushing once, then (once cached) perform the originally-requested pull.
|
||||||
|
-- Only reached from background flows when the SHA-256 resolve reported the
|
||||||
|
-- book as unknown to the server; the push mainly serves fuzzy title/author
|
||||||
|
-- linking and device alias registration for sideloaded books.
|
||||||
function Bookhoard:_bootstrapUUIDThenPull(interactive)
|
function Bookhoard:_bootstrapUUIDThenPull(interactive)
|
||||||
self:updateProgress(false, false)
|
self:updateProgress(false, false)
|
||||||
UIManager:scheduleIn(2, function()
|
UIManager:scheduleIn(2, function()
|
||||||
@@ -1144,7 +1242,7 @@ function Bookhoard:_doGetProgress(interactive)
|
|||||||
if not ok or not result then
|
if not ok or not result then
|
||||||
if interactive then
|
if interactive then
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Failed to pull progress."),
|
text = _("Failed to pull progress. Check your network connection."),
|
||||||
timeout = 3,
|
timeout = 3,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user