ReadViewSDK/Sources/RDReaderView/EPUBUI/ReaderController/RDEPUBReaderRuntime.swift

325 lines
11 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import UIKit
/// EPUB
///
/// Facade
final class RDEPUBReaderRuntime {
private unowned let context: RDEPUBReaderContext
lazy var loadCoordinator = RDEPUBReaderLoadCoordinator(context: context)
lazy var paginationCoordinator = RDEPUBReaderPaginationCoordinator(context: context)
lazy var locationCoordinator = RDEPUBReaderLocationCoordinator(context: context)
lazy var searchCoordinator = RDEPUBReaderSearchCoordinator(context: context)
lazy var chromeCoordinator = RDEPUBReaderChromeCoordinator(context: context)
lazy var annotationCoordinator = RDEPUBReaderAnnotationCoordinator(context: context)
lazy var viewportMonitor = RDEPUBReaderViewportMonitor(context: context)
init(context: RDEPUBReaderContext) {
self.context = context
}
///
func makeTopToolView() -> RDEPUBReaderTopToolView {
chromeCoordinator.makeTopToolView()
}
///
func makeBottomToolView() -> RDEPUBReaderBottomToolView {
chromeCoordinator.makeBottomToolView()
}
///
func startInitialLoadIfNeeded() {
loadCoordinator.startInitialLoadIfNeeded()
}
///
func reloadBook() {
guard let readerView = context.readerView else { return }
context.didStartInitialLoad = false
context.parser = nil
context.publication = nil
context.clearActiveSnapshot()
context.readingSession = nil
context.textBook = nil
context.activeBookmarks = []
context.activeHighlights = []
context.searchState = nil
viewportMonitor.resetForReload()
annotationCoordinator.updateCurrentSelection(nil)
readerView.reloadData()
startInitialLoadIfNeeded()
}
///
/// - Parameters:
/// - location:
/// - animated:
/// - Returns:
func go(to location: RDEPUBLocation, animated: Bool = false) -> Bool {
locationCoordinator.restoreReadingLocation(location, animated: animated)
}
///
/// - Parameters:
/// - pageNumber: 1
/// - animated:
/// - Returns:
@discardableResult
func go(toPageNumber pageNumber: Int, animated: Bool = false) -> Bool {
guard let controller = context.controller,
let readerView = context.readerView,
pageNumber > 0 else {
return false
}
if context.textBook != nil {
guard let location = controller.resolvedTextLocation(forPageNumber: pageNumber) else {
return false
}
return locationCoordinator.restoreReadingLocation(location, animated: animated)
}
guard context.activePages.indices.contains(pageNumber - 1) else {
return false
}
readerView.transitionToPage(pageNum: pageNumber - 1, animated: animated)
if let location = locationCoordinator.currentVisibleLocation() {
context.persist(location: location)
}
return true
}
///
func clearSelection() {
annotationCoordinator.updateCurrentSelection(nil)
}
func bookmark(withID id: String) -> RDEPUBBookmark? {
annotationCoordinator.bookmark(withID: id)
}
func highlight(withID id: String) -> RDEPUBHighlight? {
annotationCoordinator.highlight(withID: id)
}
@discardableResult
func addHighlight(
from selection: RDEPUBSelection? = nil,
color: String = "#F8E16C",
note: String? = nil
) -> RDEPUBHighlight? {
annotationCoordinator.addHighlight(from: selection, color: color, note: note)
}
@discardableResult
func addAnnotation(
from selection: RDEPUBSelection? = nil,
style: RDEPUBHighlightStyle,
color: String = "#F8E16C",
note: String? = nil
) -> RDEPUBHighlight? {
annotationCoordinator.addAnnotation(from: selection, style: style, color: color, note: note)
}
@discardableResult
func upsertHighlight(_ highlight: RDEPUBHighlight) -> RDEPUBHighlight? {
annotationCoordinator.upsertHighlight(highlight)
}
@discardableResult
func removeHighlight(id: String) -> RDEPUBHighlight? {
annotationCoordinator.removeHighlight(id: id)
}
@discardableResult
func updateHighlightNote(id: String, note: String?) -> RDEPUBHighlight? {
annotationCoordinator.updateHighlightNote(id: id, note: note)
}
@discardableResult
func go(toHighlightID id: String, animated: Bool = true) -> Bool {
annotationCoordinator.go(toHighlightID: id, animated: animated)
}
func removeAllHighlights() {
annotationCoordinator.removeAllHighlights()
}
@discardableResult
func addBookmark(note: String? = nil) -> RDEPUBBookmark? {
annotationCoordinator.addBookmark(note: note)
}
@discardableResult
func toggleBookmark(note: String? = nil) -> RDEPUBBookmark? {
annotationCoordinator.toggleBookmark(note: note)
}
@discardableResult
func removeBookmark(id: String) -> RDEPUBBookmark? {
annotationCoordinator.removeBookmark(id: id)
}
@discardableResult
func go(toBookmarkID id: String, animated: Bool = true) -> Bool {
annotationCoordinator.go(toBookmarkID: id, animated: animated)
}
func updateBookmarkChrome() {
annotationCoordinator.updateBookmarkChrome()
}
func presentBookmarksManager() {
annotationCoordinator.presentBookmarksManager()
}
func presentHighlightsManager() {
annotationCoordinator.presentHighlightsManager()
}
func presentAnnotationCreation() {
annotationCoordinator.presentAnnotationCreation()
}
func presentHighlightActions(for highlight: RDEPUBHighlight, sourceView: UIView, sourceRect: CGRect) {
annotationCoordinator.presentHighlightActions(for: highlight, sourceView: sourceView, sourceRect: sourceRect)
}
func handleSelectionMenuAction(_ action: RDEPUBAnnotationMenuAction, selection: RDEPUBSelection?) {
annotationCoordinator.handleSelectionMenuAction(action, selection: selection)
}
///
func search(keyword: String) {
searchCoordinator.search(keyword: keyword)
}
///
@discardableResult
func searchNext() -> Bool {
searchCoordinator.searchNext()
}
///
@discardableResult
func searchPrevious() -> Bool {
searchCoordinator.searchPrevious()
}
///
func clearSearch() {
searchCoordinator.clearSearch()
}
func searchPresentation(for page: EPUBPage) -> RDEPUBSearchPresentation? {
searchCoordinator.searchPresentation(for: page)
}
///
func updateReaderChrome() {
chromeCoordinator.updateReaderChrome()
}
///
func presentSettings() {
chromeCoordinator.presentSettings()
}
///
func presentTableOfContents() {
chromeCoordinator.presentTableOfContents()
}
///
func handleBackAction() {
chromeCoordinator.handleBackAction()
}
/// Publication
func loadPublication() {
loadCoordinator.loadPublication()
}
/// Publication
func applyParsedPublication(
parser: RDEPUBParser,
publication: RDEPUBPublication,
bookIdentifier: String,
restoreLocation: RDEPUBLocation?,
bookmarks: [RDEPUBBookmark],
highlights: [RDEPUBHighlight]
) {
loadCoordinator.applyParsedPublication(
parser: parser,
publication: publication,
bookIdentifier: bookIdentifier,
restoreLocation: restoreLocation,
bookmarks: bookmarks,
highlights: highlights
)
}
/// Publication
func paginatePublication(restoreLocation: RDEPUBLocation?) {
paginationCoordinator.paginatePublication(restoreLocation: restoreLocation)
}
/// TextBook
func applyTextBook(_ textBook: RDEPUBTextBook, restoreLocation: RDEPUBLocation?) {
paginationCoordinator.applyTextBook(textBook, restoreLocation: restoreLocation)
}
///
func applyPaginationSnapshot(
_ snapshot: (pages: [EPUBPage], chapters: [EPUBChapterInfo]),
restoreLocation: RDEPUBLocation?
) {
paginationCoordinator.applyPaginationSnapshot(snapshot, restoreLocation: restoreLocation)
}
///
func finishPagination(restoreLocation: RDEPUBLocation?) {
paginationCoordinator.finishPagination(restoreLocation: restoreLocation)
}
///
func repaginatePreservingCurrentLocation() {
paginationCoordinator.repaginatePreservingCurrentLocation()
}
///
func refreshVisibleContentPreservingLocation() {
paginationCoordinator.refreshVisibleContentPreservingLocation()
}
/// TextBook
func rebuildExternalTextBook() {
paginationCoordinator.rebuildExternalTextBook()
}
///
@discardableResult
func restoreReadingLocation(_ location: RDEPUBLocation, animated: Bool = false) -> Bool {
locationCoordinator.restoreReadingLocation(location, animated: animated)
}
///
func currentVisibleLocation() -> RDEPUBLocation? {
locationCoordinator.currentVisibleLocation()
}
///
func currentViewportSignature() -> RDEPUBViewportSignature? {
viewportMonitor.currentViewportSignature()
}
///
func handleViewportChangeIfNeeded(
reason: RDEPUBViewportChangeReason,
viewportSignature: RDEPUBViewportSignature? = nil
) {
viewportMonitor.handleViewportChangeIfNeeded(reason: reason, viewportSignature: viewportSignature)
}
}