Add EPUBNavigatorDelegate.navigatorDidLoadSpread(_:) - #838
Conversation
Add EPUBNavigatorDelegate.navigatorDidLoadSpread(_:), fired at the end of spreadViewDidLoad — one beat before the spread view's showSpread() stops the activity indicator and fades the content in. Default-empty extension impl so existing conformers are unaffected. Fires for the current spread only (spreadView === paginationView.currentView), not the adjacent spreads preloaded around it. PaginationView.loadNextPage resumes the current spread's `go` continuation before its trailing `delayed` settle sleep, so neighbours load concurrently with that tail; a short neighbour skips the delay and can reach spreadViewDidLoad first. Firing for it would let a host dismiss its loading cover a beat before the visible spread's showSpread() runs, briefly exposing that spread's activity indicator. Lets a host that shows its own loading cover dismiss it exactly when the visible content appears, rather than on locationDidChange (which fires while the spread is still loading, briefly exposing the navigator's own indicator and the scroll to the initial location). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mickael-menu
left a comment
There was a problem hiding this comment.
Thanks @raphi011
After a quick test, it looks like this is only called when the publication first loads, but not when navigating to other locations (e.g. from the table of contents). Was this the intended behavior? If so, we might want to consider a different name for it. There's also an opportunity to generalize it to VisualNavigatorDelegate.
Also, how does this behave when two resources are displayed side by side, such as with a fixed-layout EPUB in spread mode?
Currently we're focusing on migrating the toolkit to Swift 6 with strict concurrency support in the swift6 branch. We accept bug fixes but new features are frozen until this is done (we're almost there). I'm putting your PR as a draft for now.
Thank you for your understanding 🙏
There was a problem hiding this comment.
Pull request overview
Adds a new EPUB navigator delegate callback to let host apps know precisely when the currently visible spread has finished loading and is about to be revealed, enabling custom loading overlays to be dismissed without flashing the navigator’s own activity indicator.
Changes:
- Added
EPUBNavigatorDelegate.navigatorDidLoadSpread(_:)with a default empty implementation to preserve source compatibility. - Triggered the new callback at the end of the visible spread’s
spreadViewDidLoad, just before the spread is revealed. - Documented the new API in
CHANGELOG.mdunder Unreleased → Added → Navigator.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| Sources/Navigator/EPUB/EPUBNavigatorViewController.swift | Introduces the new delegate method and invokes it when the current spread finishes loading. |
| CHANGELOG.md | Adds an Unreleased changelog entry describing the new delegate callback and its intended use. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// Called when the current spread has finished loading and is about to be | ||
| /// revealed: once when the publication opens, and again after each page turn. | ||
| /// Only the visible spread triggers it, not the preloaded adjacent ones. | ||
| /// |
Summary
Adds a new
EPUBNavigatorDelegate.navigatorDidLoadSpread(_:)delegate method, called when the currently visible spread has finished loading its content and is about to be revealed (the navigator's per-spread activity indicator stops right after it returns).Motivation
A host app that shows its own loading cover currently has no precise signal for when the visible content is ready. Dismissing on
locationDidChangeis too early — it fires while the spread is still loading, briefly exposing the navigator's own activity indicator and the scroll to the initial location. This callback fires exactly when the visible content appears, so the host can dismiss its cover without any flash.Behavior
spreadViewDidLoad, one beat beforeshowSpread()stops the activity indicator and fades the content in.spreadView === paginationView.currentView), not the adjacent spreads preloaded around it. Adjacent spreads load concurrently with the current spread's trailing settle delay (seePaginationView.loadNextPage); a fast neighbour can otherwise reachspreadViewDidLoadfirst, and firing for it would let a host dismiss its cover a beat before the visible spread is actually revealed.API
Default empty implementation — existing conformers are unaffected, purely additive.
Testing
ReadiumNavigatorscheme →BUILD SUCCEEDED);make formatreports no changes.Notes