Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ All notable changes to this project will be documented in this file. Take a look

* The LCP License Document is now accessible via `publication.lcpLicense?.license`, even if the license validation fails with a status error or missing passphrase. This is useful for checking the end date of an expired license or renew a license.

### Fixed

#### Navigator

* The safe area insets strategy was adjusted to take into account changes in iOS/iPadOS 26.


## [3.4.0]

Expand Down
7 changes: 4 additions & 3 deletions Sources/Navigator/EPUB/EPUBFixedSpreadView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ final class EPUBFixedSpreadView: EPUBSpreadView {
return
}

// Insets the bounds by the notch area (eg. iPhone X) to make sure that
// the content is not overlapped by the screen notch.
var insets = notchAreaInsets
// We use the window's safeAreaInsets instead of the view's because we
// only want to take into account the device notch and status bar, not
// the application's bars.
var insets = window?.safeAreaInsets ?? .zero

// Use the same insets on the left and right side (the largest one) to
// keep the pages centered on the screen even if the notches are not
Expand Down
14 changes: 10 additions & 4 deletions Sources/Navigator/EPUB/EPUBReflowableSpreadView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,15 @@ final class EPUBReflowableSpreadView: EPUBSpreadView {
}

private func updateContentInset() {
// We use the window's safeAreaInsets instead of the view's because we
// only want to take into account the device notch and status bar, not
// the application's bars.
let safeAreaInsets = window?.safeAreaInsets ?? .zero

if viewModel.scroll {
topConstraint.constant = 0
bottomConstraint.constant = 0
scrollView.contentInset = UIEdgeInsets(top: notchAreaInsets.top, left: 0, bottom: notchAreaInsets.bottom, right: 0)
scrollView.contentInset = UIEdgeInsets(top: safeAreaInsets.top, left: 0, bottom: safeAreaInsets.bottom, right: 0)

} else {
let contentInset = viewModel.config.contentInset
Expand All @@ -98,9 +103,10 @@ final class EPUBReflowableSpreadView: EPUBSpreadView {
?? contentInset[.unspecified]
?? (top: 0, bottom: 0)

// Increases the insets by the notch area (eg. iPhone X) to make sure that the content is not overlapped by the screen notch.
insets.top += notchAreaInsets.top
insets.bottom += notchAreaInsets.bottom
// Increases the insets by the window's safe area insets area to
// make sure that the content is not overlapped by the screen notch.
insets.top += safeAreaInsets.top
insets.bottom += safeAreaInsets.bottom

topConstraint.constant = insets.top
bottomConstraint.constant = -insets.bottom
Expand Down
10 changes: 7 additions & 3 deletions Sources/Navigator/PDF/PDFDocumentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ public final class PDFDocumentView: PDFView {
}

private func updateContentInset() {
// Setting the horizontal values triggers shifts the content incorrectly, somehow.
firstScrollView?.contentInset.top = notchAreaInsets.top
firstScrollView?.contentInset.bottom = notchAreaInsets.bottom
// We use the window's safeAreaInsets instead of the view's because we
// only want to take into account the device notch and status bar, not
// the application's bars.
let insets = window?.safeAreaInsets ?? .zero

firstScrollView?.contentInset.top = insets.top
firstScrollView?.contentInset.bottom = insets.bottom
}

override public func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
Expand Down
37 changes: 0 additions & 37 deletions Sources/Navigator/Toolkit/Extensions/UIView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,6 @@ import Foundation
import UIKit

extension UIView {
/// Returns the safe area insets taking only into account the device screen notches (eg. on
/// iPhone X), ignoring any UX safe area insets (eg. status bar, navigation bar).
///
/// This can be used to layout the content in a way that makes sure it's not under the physical
/// notches, but at the same time is under the status and navigation bars (which is usually what
/// we want for a reader app).
///
/// We use that instead of pinning the content directly to the safe area layout guides to avoid
/// the view shifting when the status bar is toggled.
var notchAreaInsets: UIEdgeInsets {
guard let window = window else {
return safeAreaInsets
}

var windowSafeAreaInsets = window.safeAreaInsets

// Trick to ignore the status bar on devices without notches (pre iPhone X).
// Notch height is usually at least 44pts tall.
let statusBarSize = window.windowScene?.statusBarManager?.statusBarFrame.size ?? .zero
// The frame is in the coordinate space of the window, so it might be swapped in landscape.
let statusBarHeight = min(statusBarSize.width, statusBarSize.height)
if statusBarHeight < 44, windowSafeAreaInsets.top == statusBarHeight {
windowSafeAreaInsets.top = 0
}

// We take the smallest value between the view's safeAreaInsets and the window's
// safeAreaInsets in case the view is not pinned to the screen edges. In which case, its
// safeAreaInsets will likely be empty and we don't want to take into account the screen
// notch.
return UIEdgeInsets(
top: min(windowSafeAreaInsets.top, safeAreaInsets.top),
left: min(windowSafeAreaInsets.left, safeAreaInsets.left),
bottom: min(windowSafeAreaInsets.bottom, safeAreaInsets.bottom),
right: min(windowSafeAreaInsets.right, safeAreaInsets.right)
)
}

// Finds the first `UIScrollView` in the view hierarchy.
//
// https://medium.com/@wailord/the-particulars-of-the-safe-area-and-contentinsetadjustmentbehavior-in-ios-11-9b842018eeaa#077b
Expand Down