2 // FolioReaderFontsMenu.swift
5 // Created by Kevin Jantzer on 1/6/16.
6 // Copyright (c) 2016 Folio Reader. All rights reserved.
11 class FolioReaderPlayerMenu: UIViewController, SMSegmentViewDelegate, UIGestureRecognizerDelegate {
14 var playPauseBtn: UIButton!
15 var styleOptionBtns = [UIButton]()
16 var viewDidAppear = false
18 fileprivate var readerConfig: FolioReaderConfig
19 fileprivate var folioReader: FolioReader
21 init(folioReader: FolioReader, readerConfig: FolioReaderConfig) {
22 self.readerConfig = readerConfig
23 self.folioReader = folioReader
25 super.init(nibName: nil, bundle: nil)
28 required init?(coder aDecoder: NSCoder) {
29 fatalError("init(coder:) has not been implemented")
32 override func viewDidLoad() {
35 // Do any additional setup after loading the view.
36 self.view.backgroundColor = UIColor.clear
39 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(FolioReaderPlayerMenu.tapGesture))
40 tapGesture.numberOfTapsRequired = 1
41 tapGesture.delegate = self
42 view.addGestureRecognizer(tapGesture)
45 menuView = UIView(frame: CGRect(x: 0, y: view.frame.height-165, width: view.frame.width, height: view.frame.height))
46 menuView.backgroundColor = self.folioReader.isNight(self.readerConfig.nightModeMenuBackground, UIColor.white)
47 menuView.autoresizingMask = .flexibleWidth
48 menuView.layer.shadowColor = UIColor.black.cgColor
49 menuView.layer.shadowOffset = CGSize(width: 0, height: 0)
50 menuView.layer.shadowOpacity = 0.3
51 menuView.layer.shadowRadius = 6
52 menuView.layer.shadowPath = UIBezierPath(rect: menuView.bounds).cgPath
53 menuView.layer.rasterizationScale = UIScreen.main.scale
54 menuView.layer.shouldRasterize = true
55 view.addSubview(menuView)
57 let normalColor = UIColor(white: 0.5, alpha: 0.7)
58 let selectedColor = self.readerConfig.tintColor
61 // @NOTE: could this be improved/simplified with autolayout?
62 let gutterX = (Int(view.frame.width) - (size * 3 ) - (padX * 4) ) / 2
64 //let btnX = (Int(view.frame.width) - (size * 3)) / 4
67 let play = UIImage(readerImageNamed: "play-icon")
68 let pause = UIImage(readerImageNamed: "pause-icon")
69 let prev = UIImage(readerImageNamed: "prev-icon")
70 let next = UIImage(readerImageNamed: "next-icon")
71 let playSelected = play?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal)
72 let pauseSelected = pause?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal)
74 let prevNormal = prev?.imageTintColor(normalColor)?.withRenderingMode(.alwaysOriginal)
75 let nextNormal = next?.imageTintColor(normalColor)?.withRenderingMode(.alwaysOriginal)
76 let prevSelected = prev?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal)
77 let nextSelected = next?.imageTintColor(selectedColor)?.withRenderingMode(.alwaysOriginal)
80 let prevBtn = UIButton(frame: CGRect(x: gutterX + padX, y: 0, width: size, height: size))
81 prevBtn.setImage(prevNormal, for: UIControlState())
82 prevBtn.setImage(prevSelected, for: .selected)
83 prevBtn.addTarget(self, action: #selector(FolioReaderPlayerMenu.prevChapter(_:)), for: .touchUpInside)
84 menuView.addSubview(prevBtn)
86 // play / pause button
87 let playPauseBtn = UIButton(frame: CGRect(x: Int(prevBtn.frame.origin.x) + padX + size, y: 0, width: size, height: size))
88 playPauseBtn.setTitleColor(selectedColor, for: UIControlState())
89 playPauseBtn.setTitleColor(selectedColor, for: .selected)
90 playPauseBtn.setImage(playSelected, for: UIControlState())
91 playPauseBtn.setImage(pauseSelected, for: .selected)
92 playPauseBtn.titleLabel!.font = UIFont(name: "Avenir", size: 22)!
93 playPauseBtn.addTarget(self, action: #selector(FolioReaderPlayerMenu.togglePlay(_:)), for: .touchUpInside)
94 menuView.addSubview(playPauseBtn)
96 if let audioPlayer = self.folioReader.readerAudioPlayer , audioPlayer.isPlaying() {
97 playPauseBtn.isSelected = true
101 let nextBtn = UIButton(frame: CGRect(x: Int(playPauseBtn.frame.origin.x) + padX + size, y: 0, width: size, height: size))
102 nextBtn.setImage(nextNormal, for: UIControlState())
103 nextBtn.setImage(nextSelected, for: .selected)
104 nextBtn.addTarget(self, action: #selector(FolioReaderPlayerMenu.nextChapter(_:)), for: .touchUpInside)
105 menuView.addSubview(nextBtn)
109 let line = UIView(frame: CGRect(x: 0, y: playPauseBtn.frame.height+playPauseBtn.frame.origin.y, width: view.frame.width, height: 1))
110 line.backgroundColor = self.readerConfig.nightModeSeparatorColor
111 menuView.addSubview(line)
113 // audio playback rate adjust
114 let playbackRate = SMSegmentView(frame: CGRect(x: 15, y: line.frame.height+line.frame.origin.y, width: view.frame.width-30, height: 55),
115 separatorColour: UIColor.clear,
118 keySegmentOnSelectionColour: UIColor.clear,
119 keySegmentOffSelectionColour: UIColor.clear,
120 keySegmentOnSelectionTextColour: selectedColor,
121 keySegmentOffSelectionTextColour: normalColor,
122 keyContentVerticalMargin: 17 as AnyObject
124 playbackRate.delegate = self
126 playbackRate.addSegmentWithTitle("½x", onSelectionImage: nil, offSelectionImage: nil)
127 playbackRate.addSegmentWithTitle("1x", onSelectionImage: nil, offSelectionImage: nil)
128 playbackRate.addSegmentWithTitle("1½x", onSelectionImage: nil, offSelectionImage: nil)
129 playbackRate.addSegmentWithTitle("2x", onSelectionImage: nil, offSelectionImage: nil)
130 playbackRate.segmentTitleFont = UIFont(name: "Avenir-Light", size: 17)!
131 playbackRate.selectSegmentAtIndex(Int(self.folioReader.currentAudioRate))
132 menuView.addSubview(playbackRate)
136 let line2 = UIView(frame: CGRect(x: 0, y: playbackRate.frame.height+playbackRate.frame.origin.y, width: view.frame.width, height: 1))
137 line2.backgroundColor = self.readerConfig.nightModeSeparatorColor
138 menuView.addSubview(line2)
141 // Media overlay highlight styles
142 let style0 = UIButton(frame: CGRect(x: 0, y: line2.frame.height+line2.frame.origin.y, width: view.frame.width/3, height: 55))
143 style0.titleLabel!.textAlignment = .center
144 style0.titleLabel!.font = UIFont(name: "Avenir-Light", size: 17)
145 style0.setTitleColor(self.folioReader.isNight(self.readerConfig.nightModeMenuBackground, UIColor.white), for: UIControlState())
146 style0.setTitleColor(self.folioReader.isNight(self.readerConfig.nightModeMenuBackground, UIColor.white), for: .selected)
147 style0.setTitle(self.readerConfig.localizedPlayerMenuStyle, for: UIControlState())
148 menuView.addSubview(style0);
149 style0.titleLabel?.sizeToFit()
150 let style0Bgd = UIView(frame: style0.titleLabel!.frame)
151 style0Bgd.center = CGPoint(x: style0.frame.size.width / 2, y: style0.frame.size.height / 2);
152 style0Bgd.frame.size.width += 8
153 style0Bgd.frame.origin.x -= 4
154 style0Bgd.backgroundColor = normalColor;
155 style0Bgd.layer.cornerRadius = 3.0;
156 style0Bgd.isUserInteractionEnabled = false
157 style0.insertSubview(style0Bgd, belowSubview: style0.titleLabel!)
159 let style1 = UIButton(frame: CGRect(x: view.frame.width/3, y: line2.frame.height+line2.frame.origin.y, width: view.frame.width/3, height: 55))
160 style1.titleLabel!.textAlignment = .center
161 style1.titleLabel!.font = UIFont(name: "Avenir-Light", size: 17)
162 style1.setTitleColor(normalColor, for: UIControlState())
163 style1.setAttributedTitle(NSAttributedString(string: "Style", attributes: [
164 NSAttributedStringKey.foregroundColor: normalColor,
165 NSAttributedStringKey.underlineStyle: NSUnderlineStyle.patternDot.rawValue|NSUnderlineStyle.styleSingle.rawValue,
166 NSAttributedStringKey.underlineColor: normalColor
167 ]), for: UIControlState())
168 style1.setAttributedTitle(NSAttributedString(string: self.readerConfig.localizedPlayerMenuStyle, attributes: [
169 NSAttributedStringKey.foregroundColor: self.folioReader.isNight(UIColor.white, UIColor.black),
170 NSAttributedStringKey.underlineStyle: NSUnderlineStyle.patternDot.rawValue|NSUnderlineStyle.styleSingle.rawValue,
171 NSAttributedStringKey.underlineColor: selectedColor
173 menuView.addSubview(style1);
175 let style2 = UIButton(frame: CGRect(x: view.frame.width/1.5, y: line2.frame.height+line2.frame.origin.y, width: view.frame.width/3, height: 55))
176 style2.titleLabel!.textAlignment = .center
177 style2.titleLabel!.font = UIFont(name: "Avenir-Light", size: 17)
178 style2.setTitleColor(normalColor, for: UIControlState())
179 style2.setTitleColor(selectedColor, for: .selected)
180 style2.setTitle(self.readerConfig.localizedPlayerMenuStyle, for: UIControlState())
181 menuView.addSubview(style2);
183 // add line dividers between style buttons
184 let style1line = UIView(frame: CGRect(x: style1.frame.origin.x, y: style1.frame.origin.y, width: 1, height: style1.frame.height))
185 style1line.backgroundColor = self.readerConfig.nightModeSeparatorColor
186 menuView.addSubview(style1line)
187 let style2line = UIView(frame: CGRect(x: style2.frame.origin.x, y: style2.frame.origin.y, width: 1, height: style2.frame.height))
188 style2line.backgroundColor = self.readerConfig.nightModeSeparatorColor
189 menuView.addSubview(style2line)
191 // select the current style
192 style0.isSelected = (self.folioReader.currentMediaOverlayStyle == .default)
193 style1.isSelected = (self.folioReader.currentMediaOverlayStyle == .underline)
194 style2.isSelected = (self.folioReader.currentMediaOverlayStyle == .textColor)
195 if style0.isSelected { style0Bgd.backgroundColor = selectedColor }
197 // hook up button actions
198 style0.tag = MediaOverlayStyle.default.rawValue
199 style1.tag = MediaOverlayStyle.underline.rawValue
200 style2.tag = MediaOverlayStyle.textColor.rawValue
201 style0.addTarget(self, action: #selector(FolioReaderPlayerMenu.changeStyle(_:)), for: .touchUpInside)
202 style1.addTarget(self, action: #selector(FolioReaderPlayerMenu.changeStyle(_:)), for: .touchUpInside)
203 style2.addTarget(self, action: #selector(FolioReaderPlayerMenu.changeStyle(_:)), for: .touchUpInside)
205 // store ref to buttons
206 styleOptionBtns.append(style0)
207 styleOptionBtns.append(style1)
208 styleOptionBtns.append(style2)
212 override func viewDidAppear(_ animated: Bool) {
216 override func viewDidDisappear(_ animated: Bool) {
217 viewDidAppear = false
220 override func didReceiveMemoryWarning() {
221 super.didReceiveMemoryWarning()
222 // Dispose of any resources that can be recreated.
225 // MARK: - Status Bar
227 override var prefersStatusBarHidden : Bool {
228 return (self.readerConfig.shouldHideNavigationOnTap == true)
231 // MARK: - SMSegmentView delegate
233 func segmentView(_ segmentView: SMSegmentView, didSelectSegmentAtIndex index: Int) {
234 guard viewDidAppear else { return }
236 if let audioPlayer = self.folioReader.readerAudioPlayer, (segmentView.tag == 2) {
237 audioPlayer.setRate(index)
238 self.folioReader.currentAudioRate = index
242 @objc func prevChapter(_ sender: UIButton!) {
243 self.folioReader.readerAudioPlayer?.playPrevChapter()
246 @objc func nextChapter(_ sender: UIButton!) {
247 self.folioReader.readerAudioPlayer?.playNextChapter()
250 @objc func togglePlay(_ sender: UIButton!) {
251 sender.isSelected = sender.isSelected != true
252 self.folioReader.readerAudioPlayer?.togglePlay()
256 @objc func changeStyle(_ sender: UIButton!) {
257 self.folioReader.currentMediaOverlayStyle = MediaOverlayStyle(rawValue: sender.tag)!
259 // select the proper style button
260 for btn in styleOptionBtns {
261 btn.isSelected = btn == sender
263 if btn.tag == MediaOverlayStyle.default.rawValue {
264 btn.subviews.first?.backgroundColor = (btn.isSelected ? self.readerConfig.tintColor : UIColor(white: 0.5, alpha: 0.7))
268 // update the current page style
269 if let currentPage = self.folioReader.readerCenter?.currentPage {
270 currentPage.webView?.js("setMediaOverlayStyle(\"\(self.folioReader.currentMediaOverlayStyle.className())\")")
277 if (self.readerConfig.shouldHideNavigationOnTap == false) {
278 self.folioReader.readerCenter?.showBars()
284 @objc func tapGesture() {
289 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
290 if gestureRecognizer is UITapGestureRecognizer && touch.view == view {