Skip to content

Commit

Permalink
IOS-578 Suppress Readium 2.5 PublicationServer deprecation warnings
Browse files Browse the repository at this point in the history
The switch from `PublicationServer` to `GCDHTTPServer` in Readium 2.5.0 caused some regressions when browsing ePubs with VoiceOver:
- rendering issues while browsing (swift L/R) when scroll mode is not set
- no automatic scroll when continuous reading mode is enabled.

This silences the many deprecation warnings that are now emitted while still using the old PublicationServer.

It also fixes a few other Xcode 14.3 warnings.
  • Loading branch information
ettore committed Oct 19, 2023
1 parent 6596d36 commit d4ead68
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 27 deletions.
2 changes: 1 addition & 1 deletion Simplified/Network/NYPLNetworkQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ final class NetworkQueue: NSObject {
let methodString = method.rawValue
let dateCreated = NSKeyedArchiver.archivedData(withRootObject: Date())
// left for backward compatibility
let headerData = NSKeyedArchiver.archivedData(withRootObject: [:])
let headerData: Data? = nil

guard let db = self.startDatabaseConnection() else { return }

Expand Down
4 changes: 2 additions & 2 deletions Simplified/Reader2/Networking/NYPLAnnotations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,8 @@ final class NYPLAnnotations: NSObject, NYPLAnnotationSyncing {
Log.error(#file, "Error updating sync settings, server returned: \(httpStatus)")
if NetworkQueue.StatusCodes.contains(error.code) {
NYPLAnnotations.addRequestToOfflineQueue(httpMethod: .PUT,
url: url,
parameters: parameters)
url: url,
parameters: parameters)
}
completion(false)
return
Expand Down
55 changes: 49 additions & 6 deletions Simplified/Reader2/ReaderStackConfiguration/LibraryService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,43 @@ import UIKit
import R2Shared
import R2Streamer

// =============================================================================
// MARK: - Workaround for VoiceOver Issues

/// Temporary workaround to continue using the old Readium `PublicationServer`.
///
/// Readium 2.5.0 deprecates `PublicationServer` and introduces
/// `GCDHTTPServer` in its place. However, this causes significant scrolling
/// and book content navigation issues with VoiceOver. By casting your
/// `PublicationServer` references to `PublicationServing`, this workaround
/// silences the deprecation warnings until we find an official solution.
protocol PublicationServing: ResourcesServer {
func add(_ publication: Publication) throws
func removeAll()
}

extension PublicationServer: PublicationServing {
@available(*, deprecated, message: "To suppress this warning, cast to PublicationServing protocol")
func add(_ publication: Publication) throws {
try add(publication, at: UUID().uuidString)
}
}

private protocol PublicationServerMaking {
func make() -> PublicationServing?
}

private class PublicationServerFactory: PublicationServerMaking {
@available(*, deprecated, message: "To suppress this warning, cast to PublicationServerMaking protocol")
func make() -> PublicationServing? {
PublicationServer()
}
}


// =============================================================================
// MARK: -

/// The LibraryService makes a book ready for presentation without dealing
/// with the specifics of how a book should be presented.
///
Expand All @@ -24,14 +61,20 @@ import R2Streamer
final class LibraryService: Loggable {

private let streamer: Streamer
private let publicationServer: PublicationServer
let publicationServer: PublicationServing
private var drmLibraryServices = [DRMLibraryService]()

private lazy var documentDirectory = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

init(publicationServer: PublicationServer) {
self.publicationServer = publicationServer

init() {
guard let server = (PublicationServerFactory() as PublicationServerMaking).make() else {
/// FIXME: we should recover properly if the publication server can't
/// start, maybe this should only forbid opening a publication?
fatalError("Can't start publication server")
}

self.publicationServer = server

#if FEATURE_DRM_CONNECTOR
drmLibraryServices.append(AdobeDRMLibraryService())
#endif
Expand Down Expand Up @@ -91,7 +134,7 @@ final class LibraryService: Loggable {
}
.eraseToAnyError()
}

private func preparePresentation(of publication: Publication) {
// What we want to avoid here it to add a webPub to the publication server,
// because there's no need to do that if it is loaded remotely from a URL.
Expand All @@ -106,7 +149,7 @@ final class LibraryService: Loggable {
guard publication.baseURL == nil else {
return
}

publicationServer.removeAll()
do {
try publicationServer.add(publication)
Expand Down
13 changes: 4 additions & 9 deletions Simplified/Reader2/ReaderStackConfiguration/NYPLR2Owner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,18 @@ import R2Streamer
/// modules' delegates.
@objc public final class NYPLR2Owner: NSObject {

var libraryService: LibraryService! = nil
var libraryService: LibraryService
var readerModule: ReaderModuleAPI! = nil

init(bookRegistry: NYPLBookRegistryProvider,
annotationsSynchronizer: NYPLAnnotationSyncing) {
super.init()
guard let server = PublicationServer() else {
/// FIXME: we should recover properly if the publication server can't
/// start, maybe this should only forbid opening a publication?
fatalError("Can't start publication server")
}
libraryService = LibraryService()

libraryService = LibraryService(publicationServer: server)
super.init()

readerModule = ReaderModule(
delegate: self,
resourcesServer: server,
resourcesServer: libraryService.publicationServer,
bookRegistry: bookRegistry,
annotationsSynchronizer: annotationsSynchronizer)

Expand Down
61 changes: 54 additions & 7 deletions Simplified/Reader2/UI/NYPLEPUBViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,50 @@ import UIKit
import R2Shared
import R2Navigator

// =============================================================================
// MARK: - Workaround for VoiceOver Issues

/// Temporary workaround to continue using old UserSettings APIs in Readium.
///
/// Upgrading to the newer Preferences API requires also upgrading the
/// HTTP server from `PublicationServer` to `GCDHTTPServer`, but this exposes
/// some scrolling and navigating book content issues with VoiceOver.
/// By providing a way to cast to a non-deprecated protocol when access to the
/// deprecated apis is required, this workaround allows to silence the
/// deprecation warnings from Readium.
private protocol SettingsAccessing {
var userSettings: UserSettings {get}
func updateUserSettingStyle()
}

extension EPUBNavigatorViewController: SettingsAccessing {
}

fileprivate protocol EPUBNavigatorViewControllerMaking {
func make(publication: Publication,
initialLocation: Locator?,
resourcesServer: ResourcesServer,
config: EPUBNavigatorViewController.Configuration) -> EPUBNavigatorViewController
}

fileprivate class EPUBNavigatorViewControllerFactory: EPUBNavigatorViewControllerMaking {
@available(*, deprecated, message: "To suppress this warning, cast to EPUBNavigatorViewControllerMaking protocol")
fileprivate
func make(publication: Publication,
initialLocation: Locator?,
resourcesServer: ResourcesServer,
config: EPUBNavigatorViewController.Configuration) -> EPUBNavigatorViewController {
EPUBNavigatorViewController(publication: publication,
initialLocation: initialLocation,
resourcesServer: resourcesServer,
config: config)
}
}


// =============================================================================
// MARK: -

class NYPLEPUBViewController: NYPLBaseReaderViewController {

var popoverUserconfigurationAnchor: UIBarButtonItem?
Expand Down Expand Up @@ -48,17 +92,20 @@ class NYPLEPUBViewController: NYPLBaseReaderViewController {
preloadNextPositionCount: 0,
debugState: true)

let navigator = EPUBNavigatorViewController(publication: publication,
initialLocation: initialLocation,
resourcesServer: resourcesServer,
config: config)
userSettings = NYPLR1R2UserSettings(r2UserSettings: navigator.userSettings)
// when changing the type of the navigator, also change `epubNavigator` getter
let factory: EPUBNavigatorViewControllerMaking = EPUBNavigatorViewControllerFactory()
let navigator = factory.make(publication: publication,
initialLocation: initialLocation,
resourcesServer: resourcesServer,
config: config)
let navUserSettings = (navigator as SettingsAccessing).userSettings
userSettings = NYPLR1R2UserSettings(r2UserSettings: navUserSettings)

// EPUBNavigatorViewController::init creates a UserSettings object and sets
// it into the publication. However, that UserSettings object will have the
// defaults options for the various user properties (fonts etc), so we need
// to re-set that to reflect our ad-hoc configuration.
publication.userProperties = navigator.userSettings.userProperties
publication.userProperties = navUserSettings.userProperties

super.init(navigator: navigator,
publication: publication,
Expand All @@ -69,7 +116,7 @@ class NYPLEPUBViewController: NYPLBaseReaderViewController {
navigator.delegate = self
}

var epubNavigator: EPUBNavigatorViewController {
fileprivate var epubNavigator: SettingsAccessing {
return navigator as! EPUBNavigatorViewController
}

Expand Down
2 changes: 1 addition & 1 deletion adept-ios
2 changes: 1 addition & 1 deletion readium-sdk

0 comments on commit d4ead68

Please sign in to comment.