2 // FolioReaderContainer.swift
5 // Created by Heberti Almeida on 15/04/15.
6 // Copyright (c) 2015 Folio Reader. All rights reserved.
13 open class FolioReaderContainer: UIViewController {
14 var shouldHideStatusBar = true
15 var shouldRemoveEpub = true
17 // Mark those property as public so they can accessed from other classes/subclasses.
18 public var epubPath: String
19 public var unzipPath: String?
20 public var book: FRBook
22 public var centerNavigationController: UINavigationController?
23 public var centerViewController: FolioReaderCenter?
24 public var audioPlayer: FolioReaderAudioPlayer?
26 public var readerConfig: FolioReaderConfig
27 public var folioReader: FolioReader
29 fileprivate var errorOnLoad = false
33 /// Init a Folio Reader Container
36 /// - config: Current Folio Reader configuration
37 /// - folioReader: Current instance of the FolioReader kit.
38 /// - path: The ePub path on system. Must not be nil nor empty string.
39 /// - unzipPath: Path to unzip the compressed epub.
40 /// - removeEpub: Should delete the original file after unzip? Default to `true` so the ePub will be unziped only once.
41 public init(withConfig config: FolioReaderConfig, folioReader: FolioReader, epubPath path: String, unzipPath: String? = nil, removeEpub: Bool = true) {
42 self.readerConfig = config
43 self.folioReader = folioReader
45 self.unzipPath = unzipPath
46 self.shouldRemoveEpub = removeEpub
49 super.init(nibName: nil, bundle: Bundle.frameworkBundle())
51 // Configure the folio reader.
52 self.folioReader.readerContainer = self
54 // Initialize the default reader options.
55 if self.epubPath != "" {
60 required public init?(coder aDecoder: NSCoder) {
61 // When a FolioReaderContainer object is instantiated from the storyboard this function is called before.
62 // At this moment, we need to initialize all non-optional objects with default values.
63 // The function `setupConfig(config:epubPath:removeEpub:)` MUST be called afterward.
64 // See the ExampleFolioReaderContainer.swift for more information?
65 self.readerConfig = FolioReaderConfig()
66 self.folioReader = FolioReader()
68 self.shouldRemoveEpub = false
71 super.init(coder: aDecoder)
73 // Configure the folio reader.
74 self.folioReader.readerContainer = self
77 /// Common Initialization
78 fileprivate func initialization() {
79 // Register custom fonts
80 FontBlaster.blast(bundle: Bundle.frameworkBundle())
82 // Register initial defaults
83 self.folioReader.register(defaults: [
84 kCurrentFontFamily: FolioReaderFont.andada.rawValue,
87 kCurrentMarginSize: 2,
88 kCurrentInterlineSize: 2,
90 kCurrentHighlightStyle: 0,
92 kCurrentMediaOverlayStyle: MediaOverlayStyle.default.rawValue,
93 kCurrentScrollDirection: FolioReaderScrollDirection.defaultVertical.rawValue
97 /// Set the `FolioReaderConfig` and epubPath.
100 /// - config: Current Folio Reader configuration
101 /// - path: The ePub path on system. Must not be nil nor empty string.
102 /// - unzipPath: Path to unzip the compressed epub.
103 /// - removeEpub: Should delete the original file after unzip? Default to `true` so the ePub will be unziped only once.
104 open func setupConfig(_ config: FolioReaderConfig, epubPath path: String, unzipPath: String? = nil, removeEpub: Bool = true) {
105 self.readerConfig = config
106 self.folioReader = FolioReader()
107 self.folioReader.readerContainer = self
109 self.unzipPath = unzipPath
110 self.shouldRemoveEpub = removeEpub
113 // MARK: - View life cicle
115 override open func viewDidLoad() {
118 let canChangeScrollDirection = self.readerConfig.canChangeScrollDirection
119 self.readerConfig.canChangeScrollDirection = self.readerConfig.isDirection(canChangeScrollDirection, canChangeScrollDirection, false)
121 // If user can change scroll direction use the last saved
122 if self.readerConfig.canChangeScrollDirection == true {
123 var scrollDirection = FolioReaderScrollDirection(rawValue: self.folioReader.currentScrollDirection) ?? .vertical
124 if (scrollDirection == .defaultVertical && self.readerConfig.scrollDirection != .defaultVertical) {
125 scrollDirection = self.readerConfig.scrollDirection
128 self.readerConfig.scrollDirection = scrollDirection
131 let hideBars = readerConfig.hideBars
132 self.readerConfig.shouldHideNavigationOnTap = ((hideBars == true) ? true : self.readerConfig.shouldHideNavigationOnTap)
134 self.centerViewController = FolioReaderCenter(withContainer: self)
136 if let rootViewController = self.centerViewController {
137 self.centerNavigationController = UINavigationController(rootViewController: rootViewController)
140 self.centerNavigationController?.setNavigationBarHidden(self.readerConfig.shouldHideNavigationOnTap, animated: false)
141 if let _centerNavigationController = self.centerNavigationController {
142 self.view.addSubview(_centerNavigationController.view)
143 self.addChildViewController(_centerNavigationController)
145 self.centerNavigationController?.didMove(toParentViewController: self)
147 if (self.readerConfig.hideBars == true) {
148 self.readerConfig.shouldHideNavigationOnTap = false
149 self.navigationController?.navigationBar.isHidden = true
150 self.centerViewController?.pageIndicatorHeight = 0
154 guard (self.epubPath.isEmpty == false) else {
155 print("Epub path is nil.")
156 self.errorOnLoad = true
160 DispatchQueue.global(qos: .userInitiated).async {
163 let parsedBook = try FREpubParser().readEpub(epubPath: self.epubPath, removeEpub: self.shouldRemoveEpub, unzipPath: self.unzipPath)
164 self.book = parsedBook
165 self.folioReader.isReaderOpen = true
168 DispatchQueue.main.async {
169 // Add audio player if needed
170 if self.book.hasAudio || self.readerConfig.enableTTS {
171 self.addAudioPlayer()
173 self.centerViewController?.reloadData()
174 self.folioReader.isReaderReady = true
175 self.folioReader.delegate?.folioReader?(self.folioReader, didFinishedLoading: self.book)
178 self.errorOnLoad = true
179 self.alert(message: error.localizedDescription)
184 override open func viewDidAppear(_ animated: Bool) {
185 super.viewDidAppear(animated)
187 if (self.errorOnLoad == true) {
193 Initialize the media player
195 func addAudioPlayer() {
196 self.audioPlayer = FolioReaderAudioPlayer(withFolioReader: self.folioReader, book: self.book)
197 self.folioReader.readerAudioPlayer = audioPlayer
200 // MARK: - Status Bar
202 override open var prefersStatusBarHidden: Bool {
203 return (self.readerConfig.shouldHideNavigationOnTap == false ? false : self.shouldHideStatusBar)
206 override open var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
207 return UIStatusBarAnimation.slide
210 override open var preferredStatusBarStyle: UIStatusBarStyle {
211 return .lightContent // self.folioReader.isNight(.lightContent, .default)
215 extension FolioReaderContainer {
216 func alert(message: String) {
217 let alertController = UIAlertController(
220 preferredStyle: UIAlertControllerStyle.alert
222 let action = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel) { [weak self]
223 (result : UIAlertAction) -> Void in
226 alertController.addAction(action)
227 self.present(alertController, animated: true, completion: nil)