2 // FolioReaderConfig.swift
5 // Created by Heberti Almeida on 08/04/15.
6 // Copyright (c) 2015 Folio Reader. All rights reserved.
13 // MARK: - FolioReaderScrollDirection
15 /// Defines the Reader scrolling direction
17 /// - vertical: Section and content scroll on vertical.
18 /// - horizontal: Section and content scroll on horizontal.
19 /// - horizontalWithVerticalContent: Sections scroll horizontal and content scroll on vertical.
20 /// - defaultVertical: The default scroll direction, if not overridden; works as .vertical.
21 public enum FolioReaderScrollDirection: Int {
24 case horizontalWithVerticalContent
27 /// The current scroll direction
29 /// - Returns: Returns `UICollectionViewScrollDirection`
30 func collectionViewScrollDirection() -> UICollectionViewScrollDirection {
32 case .vertical, .defaultVertical:
34 case .horizontal, .horizontalWithVerticalContent:
40 // MARK: - ClassBasedOnClickListener
43 A `ClassBasedOnClickListener` takes a closure which is performed if a given html `class` is clicked. The closure will reveice the content of the specified parameter.
45 Eg. A ClassBasedOnClickListener with the className `quote` and parameterName `id` with the given epub html content `<section class="quote" id="12345">` would call the given closure on a click on this section with the String `12345` as parameter.
47 public struct ClassBasedOnClickListener {
49 /// The name of the URL scheme which should be used. Note: Make sure that the given `String` is a valid as scheme name.
50 public var schemeName: String
52 /// The query selector for the elements which the listener should be added to. See https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector for further information about query selectors.
53 public var querySelector: String
55 /// The name of the attribute whose content should be passed to the `onClickAction` action.
56 public var attributeName: String
58 /// Whether the listener should be added to all found elements or only to the first one. See https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll for further information. The default value is `true`.
59 public var selectAll: Bool
61 /// The closure which will be called if the specified class was clicked. `attributeContent` contains the string content of the specified attribute and `touchPointRelativeToWebView` reprsents the touch point relative to the web view.
62 public var onClickAction: ((_ attributeContent: String?, _ touchPointRelativeToWebView: CGPoint) -> Void)
65 Initializes a `ClassBasedOnClickListener` instance. Append it to the `classBasedOnClickListeners` property from the `FolioReaderConfig` to receive on click events. The default `selectAll` value is `true`.
67 - parameter schemeName: The name of the URL scheme which should be used. Note: Make sure that the given `String` is a valid as scheme name.
68 - parameter querySelector: The query selector for the elements which the listener should be added to. See https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector for further information about query selectors.
69 - parameter attributeName: The name of the attribute whose content should be passed to the `onClickAction` action.
70 - parameter selectAll: Whether the listener should be added to all found elements or only to the first one. See https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll for further information. The default value is `true`.
71 - parameter onClickAction: The closure which will be called if the specified class was clicked. `attributeContent` contains the string content of the specified attribute and `touchPointRelativeToWebView` reprsents the touch point relative to the web view.
73 public init(schemeName: String, querySelector: String, attributeName: String, selectAll: Bool = true, onClickAction: @escaping ((_ attributeContent: String?, _ touchPointRelativeToWebView: CGPoint) -> Void)) {
74 self.schemeName = schemeName.lowercased()
75 self.querySelector = querySelector
76 self.attributeName = attributeName
77 self.selectAll = selectAll
78 self.onClickAction = onClickAction
82 // MARK: - FolioReaderConfig
85 Defines the Reader custom configuration
87 open class FolioReaderConfig: NSObject {
89 // MARK: ClassBasedOnClickListener
92 Array of `ClassBasedOnClickListener` objects. A `ClassBasedOnClickListener` takes a closure which is performed if a given html `class` is clicked. The closure will reveice the content of the specified parameter.
94 Eg. A ClassBasedOnClickListener with the className `quote` and parameterName `id` with the given epub html content `<section class="quote" id="12345">` would call the given closure on a click on this section with the String `12345` as parameter.
96 open var classBasedOnClickListeners = [ClassBasedOnClickListener]()
100 /// Base header custom TintColor
101 open var tintColor = UIColor(rgba: "#6ACC50")
103 /// Menu background color
104 open var menuBackgroundColor = UIColor.white
106 /// Menu separator Color
107 open var menuSeparatorColor = UIColor(rgba: "#D7D7D7")
110 open var menuTextColor = UIColor(rgba: "#767676")
112 /// Night mode background color
113 open var nightModeBackground = UIColor(rgba: "#131313")
115 /// Night mode menu background color
116 open var nightModeMenuBackground = UIColor(rgba: "#1E1E1E")
118 /// Night mode separator color
119 open var nightModeSeparatorColor = UIColor(white: 0.5, alpha: 0.2)
121 /// Media overlay or TTS selection color
122 open lazy var mediaOverlayColor: UIColor! = self.tintColor
124 // MARK: Custom actions
126 /// hide the navigation bar and the bottom status view
127 open var hideBars = false
129 /// If `canChangeScrollDirection` is `true` it will be overrided by user's option.
130 open var scrollDirection: FolioReaderScrollDirection = .defaultVertical
132 /// Enable or disable hability to user change scroll direction on menu.
133 open var canChangeScrollDirection = true
135 /// Should hide navigation bar on user tap
136 open var shouldHideNavigationOnTap = true
138 /// Allow sharing option, if `false` will hide all sharing icons and options
139 open var allowSharing = true
141 /// Enable TTS (Text To Speech)
142 open var enableTTS = true
144 /// Display book title in navbar
145 open var displayTitle = false
147 /// Hide the page indicator
148 open var hidePageIndicator = false
150 /// Go to saved position when open a book
151 open var loadSavedPositionForCurrentBook = true
153 // MARK: Quote image share
155 /// Custom Quote logo
156 open var quoteCustomLogoImage = UIImage(readerImageNamed: "icon-logo")
158 /// Add custom backgrounds and font colors to Quote Images
159 open var quoteCustomBackgrounds = [QuoteImage]()
161 /// Enable or disable default Quote Image backgrounds
162 open var quotePreserveDefaultBackgrounds = true
166 /// Realm configuration for storing highlights
167 open var realmConfiguration = Realm.Configuration()
169 // MARK: Localized strings
171 /// Localizes Highlight title
172 open var localizedHighlightsTitle = NSLocalizedString("Highlights", comment: "")
174 /// Localizes Content title
175 open var localizedContentsTitle = NSLocalizedString("Contents", comment: "")
177 /// Use the readers `UIMenuController` which enables the highlighting etc. The default is `true`. If set to false it's possible to modify the shared `UIMenuController` for yourself. Note: This doesn't disable the text selection in the web view.
178 open var useReaderMenuController = true
180 /// Used to distinguish between multiple or different reader instances. The content of the user defaults (font settings etc.) depends on this identifier. The default is `nil`.
181 open var identifier: String?
183 /// Localizes Highlight date format. This is a `dateFormat` from `NSDateFormatter`, so be careful 🤔
184 open var localizedHighlightsDateFormat = "MMM dd, YYYY | HH:mm"
185 open var localizedHighlightMenu = NSLocalizedString("Highlight", comment: "")
186 open var localizedDefineMenu = NSLocalizedString("Define", comment: "")
187 open var localizedPlayMenu = NSLocalizedString("Play", comment: "")
188 open var localizedPauseMenu = NSLocalizedString("Pause", comment: "")
189 open var localizedFontMenuNight = NSLocalizedString("Night", comment: "")
190 open var localizedPlayerMenuStyle = NSLocalizedString("Style", comment: "")
191 open var localizedFontMenuDay = NSLocalizedString("Day", comment: "")
192 open var localizedLayoutHorizontal = NSLocalizedString("Horizontal", comment: "")
193 open var localizedLayoutVertical = NSLocalizedString("Vertical", comment: "")
194 open var localizedReaderOnePageLeft = NSLocalizedString("1 page left", comment: "")
195 open var localizedReaderManyPagesLeft = NSLocalizedString("pages left", comment: "")
196 open var localizedReaderManyMinutes = NSLocalizedString("minutes", comment: "")
197 open var localizedReaderOneMinute = NSLocalizedString("1 minute", comment: "")
198 open var localizedReaderLessThanOneMinute = NSLocalizedString("Less than a minute", comment: "")
199 open var localizedShareWebLink: URL? = nil
200 open var localizedShareChapterSubject = NSLocalizedString("Check out this chapter from", comment: "")
201 open var localizedShareHighlightSubject = NSLocalizedString("Notes from", comment: "")
202 open var localizedShareAllExcerptsFrom = NSLocalizedString("All excerpts from", comment: "")
203 open var localizedShareBy = NSLocalizedString("by", comment: "")
204 open var localizedCancel = NSLocalizedString("Cancel", comment: "")
205 open var localizedShare = NSLocalizedString("Share", comment: "")
206 open var localizedChooseExisting = NSLocalizedString("Choose existing", comment: "")
207 open var localizedTakePhoto = NSLocalizedString("Take Photo", comment: "")
208 open var localizedShareImageQuote = NSLocalizedString("Share image quote", comment: "")
209 open var localizedShareTextQuote = NSLocalizedString("Share text quote", comment: "")
211 public convenience init(withIdentifier identifier: String) {
214 self.identifier = identifier
218 Simplify attibution of values based on direction, basically is to avoid too much usage of `switch`,
219 `if` and `else` statements to check. So basically this is like a shorthand version of the `switch` verification.
223 let pageOffsetPoint = readerConfig.isDirection(CGPoint(x: 0, y: pageOffset), CGPoint(x: pageOffset, y: 0), CGPoint(x: 0, y: pageOffset))
226 As usually the `vertical` direction and `horizontalContentVertical` has similar statements you can basically hide the last
227 value and it will assume the value from `vertical` as fallback.
229 let pageOffsetPoint = readerConfig.isDirection(CGPoint(x: 0, y: pageOffset), CGPoint(x: pageOffset, y: 0))
232 - parameter vertical: Value for `vertical` direction
233 - parameter horizontal: Value for `horizontal` direction
234 - parameter horizontalContentVertical: Value for `horizontalWithVerticalContent` direction, if nil will fallback to `vertical` value
236 - returns: The right value based on direction.
238 func isDirection<T> (_ vertical: T, _ horizontal: T, _ horizontalContentVertical: T) -> T {
239 switch self.scrollDirection {
240 case .vertical, .defaultVertical: return vertical
241 case .horizontal: return horizontal
242 case .horizontalWithVerticalContent: return horizontalContentVertical