Skip to content

Commit

Permalink
Improve reliability of EPUB pagination view (#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
mickael-menu authored Jan 29, 2025
1 parent d805e4e commit 9dc13a0
Showing 1 changed file with 43 additions and 14 deletions.
57 changes: 43 additions & 14 deletions Sources/Navigator/EPUB/EPUBNavigatorViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,9 @@ open class EPUBNavigatorViewController: UIViewController,
hasPositions: !positionsByReadingOrder.isEmpty
)

paginationView.frame = view.bounds
paginationView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
view.addSubview(paginationView)
paginationView!.frame = view.bounds
paginationView!.autoresizingMask = [.flexibleHeight, .flexibleWidth]
view.addSubview(paginationView!)

applySettings()

Expand Down Expand Up @@ -481,7 +481,10 @@ open class EPUBNavigatorViewController: UIViewController,

/// Goes to the next or previous page in the given scroll direction.
private func go(to direction: EPUBSpreadView.Direction, options: NavigatorGoOptions) async -> Bool {
guard on(.move(direction)) else {
guard
let paginationView = paginationView,
on(.move(direction))
else {
return false
}

Expand Down Expand Up @@ -515,7 +518,7 @@ open class EPUBNavigatorViewController: UIViewController,

// MARK: - Pagination and spreads

private var paginationView: PaginationView!
private var paginationView: PaginationView?

private func makePaginationView(hasPositions: Bool) -> PaginationView {
let view = PaginationView(
Expand All @@ -529,11 +532,20 @@ open class EPUBNavigatorViewController: UIViewController,
return view
}

private func invalidatePaginationView() async {
guard let paginationView = paginationView else {
return
}

paginationView.isScrollEnabled = isPaginationViewScrollingEnabled
await reloadSpreads(force: true)
}

private var spreads: [EPUBSpread] = []

/// Index of the currently visible spread.
private var currentSpreadIndex: Int {
paginationView.currentIndex
paginationView?.currentIndex ?? 0
}

// Reading order index of the left-most resource in the visible spread.
Expand Down Expand Up @@ -575,6 +587,7 @@ open class EPUBNavigatorViewController: UIViewController,
let locator = locator ?? currentLocation

guard
let paginationView = paginationView,
// Already loaded with the expected amount of spreads?
force || spreads.first?.spread != viewModel.spreadEnabled,
on(.load(locator))
Expand Down Expand Up @@ -607,7 +620,7 @@ open class EPUBNavigatorViewController: UIViewController,
}

private func loadedSpreadViewForHREF<T: URLConvertible>(_ href: T) -> EPUBSpreadView? {
paginationView.loadedViews
paginationView?.loadedViews
.compactMap { _, view in view as? EPUBSpreadView }
.first { $0.spread.links.firstWithHREF(href) != nil }
}
Expand Down Expand Up @@ -640,7 +653,7 @@ open class EPUBNavigatorViewController: UIViewController,
return pendingLocator
}

guard let spreadView = paginationView.currentView as? EPUBSpreadView else {
guard let spreadView = paginationView?.currentView as? EPUBSpreadView else {
return nil
}

Expand Down Expand Up @@ -670,7 +683,7 @@ open class EPUBNavigatorViewController: UIViewController,
}

public func firstVisibleElementLocator() async -> Locator? {
guard let spreadView = paginationView.currentView as? EPUBSpreadView else {
guard let spreadView = paginationView?.currentView as? EPUBSpreadView else {
return nil
}
return await spreadView.findFirstVisibleElementLocator()
Expand Down Expand Up @@ -705,6 +718,7 @@ open class EPUBNavigatorViewController: UIViewController,
let locator = publication.normalizeLocator(locator)

guard
let paginationView = paginationView,
let spreadIndex = spreads.firstIndexWithHREF(locator.href),
on(.jump(locator))
else {
Expand Down Expand Up @@ -759,6 +773,10 @@ open class EPUBNavigatorViewController: UIViewController,
}

public func clearSelection() {
guard let paginationView = paginationView else {
return
}

for (_, pageView) in paginationView.loadedViews {
(pageView as? EPUBSpreadView)?.webView.clearSelection()
}
Expand All @@ -779,6 +797,10 @@ open class EPUBNavigatorViewController: UIViewController,
Task {
await initialized()

guard let paginationView = paginationView else {
return
}

await withTaskGroup(of: Void.self) { tasks in
let source = self.decorations[group] ?? []
let target = decorations.map {
Expand Down Expand Up @@ -821,6 +843,10 @@ open class EPUBNavigatorViewController: UIViewController,
Task {
await initialized()

guard let paginationView = paginationView else {
return
}

await withTaskGroup(of: Void.self) { tasks in
for (_, view) in paginationView.loadedViews {
tasks.addTask {
Expand Down Expand Up @@ -854,7 +880,7 @@ open class EPUBNavigatorViewController: UIViewController,
}

view.backgroundColor = settings.effectiveBackgroundColor.uiColor
paginationView.isScrollEnabled = isPaginationViewScrollingEnabled
paginationView?.isScrollEnabled = isPaginationViewScrollingEnabled
}

// MARK: - User interactions
Expand All @@ -872,7 +898,7 @@ open class EPUBNavigatorViewController: UIViewController,
/// Evaluates the given JavaScript on the currently visible HTML resource.
@discardableResult
public func evaluateJavaScript(_ script: String) async -> Result<Any, Error> {
guard let spreadView = paginationView.currentView as? EPUBSpreadView else {
guard let spreadView = paginationView?.currentView as? EPUBSpreadView else {
return .failure(EPUBError.spreadNotLoaded)
}
return await spreadView.evaluateScript(script)
Expand Down Expand Up @@ -913,15 +939,18 @@ open class EPUBNavigatorViewController: UIViewController,
extension EPUBNavigatorViewController: EPUBNavigatorViewModelDelegate {
func epubNavigatorViewModelInvalidatePaginationView(_ viewModel: EPUBNavigatorViewModel) {
Task {
paginationView.isScrollEnabled = isPaginationViewScrollingEnabled
await reloadSpreads(force: true)
await invalidatePaginationView()
}
}

func epubNavigatorViewModel(_ viewModel: EPUBNavigatorViewModel, runScript script: String, in scope: EPUBScriptScope) {
Task {
await initialized()

guard let paginationView = paginationView else {
return
}

switch scope {
case .currentResource:
await (paginationView.currentView as? EPUBSpreadView)?.evaluateScript(script)
Expand Down Expand Up @@ -1159,7 +1188,7 @@ extension EPUBNavigatorViewController: EPUBSpreadViewDelegate {
}

func spreadViewPagesDidChange(_ spreadView: EPUBSpreadView) {
if paginationView.currentView == spreadView {
if paginationView?.currentView == spreadView {
updateCurrentLocation()
}
}
Expand Down

0 comments on commit 9dc13a0

Please sign in to comment.