diff --git a/main.lua b/main.lua index cdc401c..a04d9fb 100644 --- a/main.lua +++ b/main.lua @@ -737,6 +737,9 @@ function Bookhoard:getLastProgress() end function Bookhoard:getFileSHA256() + -- Reached from deferred flows too (e.g. _linkBookThenPull after a + -- network-connected event); callers already handle nil. + if not (self.ui and self.ui.doc_settings and self.ui.document) then return nil end local cached = self.ui.doc_settings:readSetting("bookhoard_sha256") if cached then return cached end @@ -1208,6 +1211,12 @@ function Bookhoard:updateProgress(ensure_networking, interactive) end function Bookhoard:_doUpdateProgress(interactive) + -- Every push runs deferred (scheduleIn(0.5) in updateProgress), so it + -- can fire after the ReaderUI released its document (close/teardown + -- race, e.g. "attempt to index field 'document'" killing the app) or + -- before a slow async load attached it (the CRE full-render window). + -- Bail silently; the next real page turn re-pushes. + if not (self.ui and self.ui.document) then return end local book_data = self:collectBookData() if not book_data then return end @@ -1441,6 +1450,9 @@ function Bookhoard:_bootstrapUUIDThenPull(interactive) end function Bookhoard:_doGetProgress(interactive) + -- Pulls are deferred too (see _doUpdateProgress): the document can be + -- gone — or not yet attached — by the time the timer fires. + if not (self.ui and self.ui.document) then return end local book_uuid = self:getBookhoardUUID() if not book_uuid then return end @@ -1448,6 +1460,9 @@ function Bookhoard:_doGetProgress(interactive) local ok, result = api:getMetadata(book_uuid) UIManager:nextTick(function() + -- The HTTP reply landed after the defer; re-validate before the + -- document-dependent body below (applyServerAnnotations, sync). + if not (self.ui and self.ui.document) then return end if not ok or not result then if interactive then UIManager:show(InfoMessage:new{