From f47f81a69ab31d1f91a4f831f9b98a3180f7c04d Mon Sep 17 00:00:00 2001 From: Warren Burton Date: Wed, 23 Jan 2019 15:09:45 +0000 Subject: [PATCH 1/6] Changes to build for Swift 4.2 --- ABVideoRangeSlider/Classes/ABBorder.swift | 2 +- ABVideoRangeSlider/Classes/ABEndIndicator.swift | 2 +- ABVideoRangeSlider/Classes/ABProgressIndicator.swift | 2 +- ABVideoRangeSlider/Classes/ABStartIndicator.swift | 2 +- ABVideoRangeSlider/Classes/ABThumbnailsManager.swift | 6 +++--- ABVideoRangeSlider/Classes/ABTimeView.swift | 2 +- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ABVideoRangeSlider/Classes/ABBorder.swift b/ABVideoRangeSlider/Classes/ABBorder.swift index fae2746..c5299d6 100644 --- a/ABVideoRangeSlider/Classes/ABBorder.swift +++ b/ABVideoRangeSlider/Classes/ABBorder.swift @@ -20,7 +20,7 @@ class ABBorder: UIView { imageView.frame = self.bounds imageView.image = image - imageView.contentMode = UIViewContentMode.scaleToFill + imageView.contentMode = .scaleToFill self.addSubview(imageView) } diff --git a/ABVideoRangeSlider/Classes/ABEndIndicator.swift b/ABVideoRangeSlider/Classes/ABEndIndicator.swift index 2286644..b97e50b 100644 --- a/ABVideoRangeSlider/Classes/ABEndIndicator.swift +++ b/ABVideoRangeSlider/Classes/ABEndIndicator.swift @@ -21,7 +21,7 @@ class ABEndIndicator: UIView { imageView.frame = self.bounds imageView.image = image - imageView.contentMode = UIViewContentMode.scaleToFill + imageView.contentMode = .scaleToFill self.addSubview(imageView) } diff --git a/ABVideoRangeSlider/Classes/ABProgressIndicator.swift b/ABVideoRangeSlider/Classes/ABProgressIndicator.swift index 5eef82a..a1ff468 100644 --- a/ABVideoRangeSlider/Classes/ABProgressIndicator.swift +++ b/ABVideoRangeSlider/Classes/ABProgressIndicator.swift @@ -19,7 +19,7 @@ class ABProgressIndicator: UIView { let image = UIImage(named: "ProgressIndicator", in: bundle, compatibleWith: nil) imageView.frame = self.bounds imageView.image = image - imageView.contentMode = UIViewContentMode.scaleToFill + imageView.contentMode = .scaleToFill self.addSubview(imageView) } diff --git a/ABVideoRangeSlider/Classes/ABStartIndicator.swift b/ABVideoRangeSlider/Classes/ABStartIndicator.swift index b85c29b..3db1270 100644 --- a/ABVideoRangeSlider/Classes/ABStartIndicator.swift +++ b/ABVideoRangeSlider/Classes/ABStartIndicator.swift @@ -21,7 +21,7 @@ class ABStartIndicator: UIView { imageView.frame = self.bounds imageView.image = image - imageView.contentMode = UIViewContentMode.scaleToFill + imageView.contentMode = .scaleToFill self.addSubview(imageView) } diff --git a/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift b/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift index b2cdda9..fc3075a 100644 --- a/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift +++ b/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift @@ -28,7 +28,7 @@ class ABThumbnailsManager: NSObject { let imageView = UIImageView(image: image) imageView.alpha = 0 - imageView.contentMode = UIViewContentMode.scaleAspectFill + imageView.contentMode = .scaleAspectFill imageView.clipsToBounds = true imageView.frame = CGRect(x: xPos, y: 0.0, @@ -41,7 +41,7 @@ class ABThumbnailsManager: NSObject { UIView.animate(withDuration: 0.2, animations: {() -> Void in imageView.alpha = 1.0 }) - view.sendSubview(toBack: imageView) + view.sendSubviewToBack(imageView) xPos = xPos + view.frame.size.height } } @@ -75,7 +75,7 @@ class ABThumbnailsManager: NSObject { for i in 0.. Date: Wed, 23 Jan 2019 15:13:52 +0000 Subject: [PATCH 2/6] swiftlint (0.30.0) autocorrect --- ABVideoRangeSlider/Classes/ABBorder.swift | 10 +- .../Classes/ABEndIndicator.swift | 12 +- .../Classes/ABProgressIndicator.swift | 14 +- .../Classes/ABStartIndicator.swift | 8 +- .../Classes/ABThumbnailsManager.swift | 41 ++--- ABVideoRangeSlider/Classes/ABTimeView.swift | 22 +-- .../Classes/ABVideoHelper.swift | 14 +- .../Classes/ABVideoRangeSlider.swift | 170 +++++++++--------- Example/ABVideoRangeSlider/AppDelegate.swift | 3 - .../ABVideoRangeSlider/ViewController.swift | 22 ++- Example/Tests/Tests.swift | 12 +- 11 files changed, 158 insertions(+), 170 deletions(-) diff --git a/ABVideoRangeSlider/Classes/ABBorder.swift b/ABVideoRangeSlider/Classes/ABBorder.swift index c5299d6..97208a8 100644 --- a/ABVideoRangeSlider/Classes/ABBorder.swift +++ b/ABVideoRangeSlider/Classes/ABBorder.swift @@ -11,23 +11,23 @@ import UIKit class ABBorder: UIView { var imageView = UIImageView() - + override init(frame: CGRect) { super.init(frame: frame) - + let bundle = Bundle(for: ABStartIndicator.self) let image = UIImage(named: "BorderLine", in: bundle, compatibleWith: nil) - + imageView.frame = self.bounds imageView.image = image imageView.contentMode = .scaleToFill self.addSubview(imageView) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func layoutSubviews() { super.layoutSubviews() imageView.frame = self.bounds diff --git a/ABVideoRangeSlider/Classes/ABEndIndicator.swift b/ABVideoRangeSlider/Classes/ABEndIndicator.swift index b97e50b..c10ebed 100644 --- a/ABVideoRangeSlider/Classes/ABEndIndicator.swift +++ b/ABVideoRangeSlider/Classes/ABEndIndicator.swift @@ -9,24 +9,24 @@ import UIKit class ABEndIndicator: UIView { - + public var imageView = UIImageView() - + override init(frame: CGRect) { super.init(frame: frame) self.isUserInteractionEnabled = true - + let bundle = Bundle(for: ABStartIndicator.self) let image = UIImage(named: "EndIndicator", in: bundle, compatibleWith: nil) - + imageView.frame = self.bounds imageView.image = image imageView.contentMode = .scaleToFill self.addSubview(imageView) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + } diff --git a/ABVideoRangeSlider/Classes/ABProgressIndicator.swift b/ABVideoRangeSlider/Classes/ABProgressIndicator.swift index a1ff468..6b1caaf 100644 --- a/ABVideoRangeSlider/Classes/ABProgressIndicator.swift +++ b/ABVideoRangeSlider/Classes/ABProgressIndicator.swift @@ -9,12 +9,12 @@ import UIKit class ABProgressIndicator: UIView { - + var imageView = UIImageView() - + override init(frame: CGRect) { super.init(frame: frame) - + let bundle = Bundle(for: ABStartIndicator.self) let image = UIImage(named: "ProgressIndicator", in: bundle, compatibleWith: nil) imageView.frame = self.bounds @@ -22,11 +22,11 @@ class ABProgressIndicator: UIView { imageView.contentMode = .scaleToFill self.addSubview(imageView) } - + required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func layoutSubviews() { super.layoutSubviews() imageView.frame = self.bounds @@ -37,9 +37,9 @@ class ABProgressIndicator: UIView { y: 0, width: self.frame.size.width * 2, height: self.frame.size.height) - if frame.contains(point){ + if frame.contains(point) { return self - }else{ + } else { return nil } } diff --git a/ABVideoRangeSlider/Classes/ABStartIndicator.swift b/ABVideoRangeSlider/Classes/ABStartIndicator.swift index 3db1270..648b439 100644 --- a/ABVideoRangeSlider/Classes/ABStartIndicator.swift +++ b/ABVideoRangeSlider/Classes/ABStartIndicator.swift @@ -9,16 +9,16 @@ import UIKit class ABStartIndicator: UIView { - + var imageView = UIImageView() - + override init(frame: CGRect) { super.init(frame: frame) self.isUserInteractionEnabled = true - + let bundle = Bundle(for: ABStartIndicator.self) let image = UIImage(named: "StartIndicator", in: bundle, compatibleWith: nil) - + imageView.frame = self.bounds imageView.image = image imageView.contentMode = .scaleToFill diff --git a/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift b/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift index fc3075a..409149f 100644 --- a/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift +++ b/ABVideoRangeSlider/Classes/ABThumbnailsManager.swift @@ -10,22 +10,22 @@ import UIKit import AVFoundation class ABThumbnailsManager: NSObject { - + var thumbnailViews = [UIImageView]() - private func addImagesToView(images: [UIImage], view: UIView){ - + private func addImagesToView(images: [UIImage], view: UIView) { + self.thumbnailViews.removeAll() var xPos: CGFloat = 0.0 var width: CGFloat = 0.0 - for image in images{ + for image in images { DispatchQueue.main.async { - if xPos + view.frame.size.height < view.frame.width{ + if xPos + view.frame.size.height < view.frame.width { width = view.frame.size.height - }else{ + } else { width = view.frame.size.width - xPos } - + let imageView = UIImageView(image: image) imageView.alpha = 0 imageView.contentMode = .scaleAspectFill @@ -35,8 +35,7 @@ class ABThumbnailsManager: NSObject { width: width, height: view.frame.size.height) self.thumbnailViews.append(imageView) - - + view.addSubview(imageView) UIView.animate(withDuration: 0.2, animations: {() -> Void in imageView.alpha = 1.0 @@ -46,34 +45,32 @@ class ABThumbnailsManager: NSObject { } } } - + private func thumbnailCount(inView: UIView) -> Int { - - var num : Double = 0; - + + var num: Double = 0 + DispatchQueue.main.sync { num = Double(inView.frame.size.width) / Double(inView.frame.size.height) } return Int(ceil(num)) } - - func updateThumbnails(view: UIView, videoURL: URL, duration: Float64) -> [UIImageView]{ + + func updateThumbnails(view: UIView, videoURL: URL, duration: Float64) -> [UIImageView] { var thumbnails = [UIImage]() var offset: Float64 = 0 - - for view in self.thumbnailViews{ - DispatchQueue.main.sync - { + for view in self.thumbnailViews { + DispatchQueue.main.sync { view.removeFromSuperview() } } - + let imagesCount = self.thumbnailCount(inView: view) - - for i in 0.. UIImage{ + static func thumbnailFromVideo(videoUrl: URL, time: CMTime) -> UIImage { let asset: AVAsset = AVAsset(url: videoUrl) as AVAsset let imgGenerator = AVAssetImageGenerator(asset: asset) imgGenerator.appliesPreferredTrackTransform = true - do{ + do { let cgImage = try imgGenerator.copyCGImage(at: time, actualTime: nil) let uiImage = UIImage(cgImage: cgImage) return uiImage - }catch{ - + } catch { + } return UIImage() } - - static func videoDuration(videoURL: URL) -> Float64{ + + static func videoDuration(videoURL: URL) -> Float64 { let source = AVURLAsset(url: videoURL) return CMTimeGetSeconds(source.duration) } - + } diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 75a272b..148e7e5 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -11,7 +11,7 @@ import UIKit @objc public protocol ABVideoRangeSliderDelegate: class { func didChangeValue(videoRangeSlider: ABVideoRangeSlider, startTime: Float64, endTime: Float64) func indicatorDidChangePosition(videoRangeSlider: ABVideoRangeSlider, position: Float64) - + @objc optional func sliderGesturesBegan() @objc optional func sliderGesturesEnded() } @@ -22,8 +22,8 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { case start case end } - - public weak var delegate: ABVideoRangeSliderDelegate? = nil + + public weak var delegate: ABVideoRangeSliderDelegate? var startIndicator = ABStartIndicator() var endIndicator = ABEndIndicator() @@ -50,14 +50,14 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { public var minSpace: Float = 1 // In Seconds public var maxSpace: Float = 0 // In Seconds - + public var isProgressIndicatorSticky: Bool = false public var isProgressIndicatorDraggable: Bool = true - + var isUpdatingThumbnails = false var isReceivingGesture: Bool = false - - public enum ABTimeViewPosition{ + + public enum ABTimeViewPosition { case top case bottom } @@ -76,11 +76,11 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { super.init(coder: aDecoder) } - private func setup(){ + private func setup() { self.isUserInteractionEnabled = true // Setup Start Indicator - let startDrag = UIPanGestureRecognizer(target:self, + let startDrag = UIPanGestureRecognizer(target: self, action: #selector(startDragged(recognizer:))) startIndicator = ABStartIndicator(frame: CGRect(x: 0, @@ -93,7 +93,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // Setup End Indicator - let endDrag = UIPanGestureRecognizer(target:self, + let endDrag = UIPanGestureRecognizer(target: self, action: #selector(endDragged(recognizer:))) endIndicator = ABEndIndicator(frame: CGRect(x: 0, @@ -104,7 +104,6 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { endIndicator.addGestureRecognizer(endDrag) self.addSubview(endIndicator) - // Setup Top and bottom line topLine = ABBorder(frame: CGRect(x: 0, @@ -126,7 +125,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // Setup Progress Indicator - let progressDrag = UIPanGestureRecognizer(target:self, + let progressDrag = UIPanGestureRecognizer(target: self, action: #selector(progressDragged(recognizer:))) progressIndicator = ABProgressIndicator(frame: CGRect(x: 0, @@ -138,7 +137,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // Setup Draggable View - let viewDrag = UIPanGestureRecognizer(target:self, + let viewDrag = UIPanGestureRecognizer(target: self, action: #selector(viewDragged(recognizer:))) draggableView.addGestureRecognizer(viewDrag) @@ -157,7 +156,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { self.addSubview(endTimeView) } - public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "bounds"{ self.updateThumbnails() } @@ -165,22 +164,22 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // MARK: Public functions - public func setProgressIndicatorImage(image: UIImage){ + public func setProgressIndicatorImage(image: UIImage) { self.progressIndicator.imageView.image = image } - public func hideProgressIndicator(){ + public func hideProgressIndicator() { self.progressIndicator.isHidden = true } - public func showProgressIndicator(){ + public func showProgressIndicator() { self.progressIndicator.isHidden = false } - public func updateProgressIndicator(seconds: Float64){ + public func updateProgressIndicator(seconds: Float64) { if !isReceivingGesture { let endSeconds = secondsFromValue(value: self.endPercentage) - + if seconds >= endSeconds { self.resetProgressPosition() } else { @@ -191,25 +190,25 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } - public func setStartIndicatorImage(image: UIImage){ + public func setStartIndicatorImage(image: UIImage) { self.startIndicator.imageView.image = image } - public func setEndIndicatorImage(image: UIImage){ + public func setEndIndicatorImage(image: UIImage) { self.endIndicator.imageView.image = image } - public func setBorderImage(image: UIImage){ + public func setBorderImage(image: UIImage) { self.topLine.imageView.image = image self.bottomLine.imageView.image = image } - public func setTimeView(view: ABTimeView){ + public func setTimeView(view: ABTimeView) { self.startTimeView = view self.endTimeView = view } - public func setTimeViewPosition(position: ABTimeViewPosition){ + public func setTimeViewPosition(position: ABTimeViewPosition) { switch position { case .top: @@ -220,15 +219,15 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } - public func setVideoURL(videoURL: URL){ + public func setVideoURL(videoURL: URL) { self.duration = ABVideoHelper.videoDuration(videoURL: videoURL) self.videoURL = videoURL self.superview?.layoutSubviews() self.updateThumbnails() } - public func updateThumbnails(){ - if !isUpdatingThumbnails{ + public func updateThumbnails() { + if !isUpdatingThumbnails { self.isUpdatingThumbnails = true let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background, target: nil) backgroundQueue.async { @@ -238,12 +237,12 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } - public func setStartPosition(seconds: Float){ + public func setStartPosition(seconds: Float) { self.startPercentage = self.valueFromSeconds(seconds: seconds) layoutSubviews() } - public func setEndPosition(seconds: Float){ + public func setEndPosition(seconds: Float) { self.endPercentage = self.valueFromSeconds(seconds: seconds) layoutSubviews() } @@ -251,7 +250,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // MARK: - Private functions // MARK: - Crop Handle Drag Functions - @objc private func startDragged(recognizer: UIPanGestureRecognizer){ + @objc private func startDragged(recognizer: UIPanGestureRecognizer) { self.processHandleDrag( recognizer: recognizer, drag: .start, @@ -259,8 +258,8 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { currentIndicator: self.startIndicator ) } - - @objc private func endDragged(recognizer: UIPanGestureRecognizer){ + + @objc private func endDragged(recognizer: UIPanGestureRecognizer) { self.processHandleDrag( recognizer: recognizer, drag: .end, @@ -275,17 +274,17 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { currentPositionPercentage: CGFloat, currentIndicator: UIView ) { - + self.updateGestureStatus(recognizer: recognizer) - + let translation = recognizer.translation(in: self) - + var position: CGFloat = positionFromValue(value: currentPositionPercentage) // self.startPercentage or self.endPercentage - + position = position + translation.x - + if position < 0 { position = 0 } - + if position > self.frame.size.width { position = self.frame.size.width } @@ -304,29 +303,29 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } } - + recognizer.setTranslation(CGPoint.zero, in: self) - - currentIndicator.center = CGPoint(x: position , y: currentIndicator.center.y) - + + currentIndicator.center = CGPoint(x: position, y: currentIndicator.center.y) + let percentage = currentIndicator.center.x * 100 / self.frame.width - + let startSeconds = secondsFromValue(value: self.startPercentage) let endSeconds = secondsFromValue(value: self.endPercentage) - + self.delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) - + var progressPosition: CGFloat = 0.0 - + if drag == .start { self.startPercentage = percentage } else { self.endPercentage = percentage } - + if drag == .start { progressPosition = positionFromValue(value: self.startPercentage) - + } else { if recognizer.state != .ended { progressPosition = positionFromValue(value: self.endPercentage) @@ -334,27 +333,27 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { progressPosition = positionFromValue(value: self.startPercentage) } } - - progressIndicator.center = CGPoint(x: progressPosition , y: progressIndicator.center.y) + + progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) let progressPercentage = progressIndicator.center.x * 100 / self.frame.width - + if self.progressPercentage != progressPercentage { let progressSeconds = secondsFromValue(value: progressPercentage) self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) } - + self.progressPercentage = progressPercentage - + layoutSubviews() } - - @objc func progressDragged(recognizer: UIPanGestureRecognizer){ + + @objc func progressDragged(recognizer: UIPanGestureRecognizer) { if !isProgressIndicatorDraggable { return } - + updateGestureStatus(recognizer: recognizer) - + let translation = recognizer.translation(in: self) let positionLimitStart = positionFromValue(value: self.startPercentage) @@ -373,7 +372,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { recognizer.setTranslation(CGPoint.zero, in: self) - progressIndicator.center = CGPoint(x: position , y: progressIndicator.center.y) + progressIndicator.center = CGPoint(x: position, y: progressIndicator.center.y) let percentage = progressIndicator.center.x * 100 / self.frame.width @@ -386,9 +385,9 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { layoutSubviews() } - @objc func viewDragged(recognizer: UIPanGestureRecognizer){ + @objc func viewDragged(recognizer: UIPanGestureRecognizer) { updateGestureStatus(recognizer: recognizer) - + let translation = recognizer.translation(in: self) var progressPosition = positionFromValue(value: self.progressPercentage) @@ -405,7 +404,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { progressPosition = progressPosition - translation.x } - if endPosition > self.frame.size.width{ + if endPosition > self.frame.size.width { endPosition = self.frame.size.width startPosition = startPosition - translation.x progressPosition = progressPosition - translation.x @@ -413,9 +412,9 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { recognizer.setTranslation(CGPoint.zero, in: self) - progressIndicator.center = CGPoint(x: progressPosition , y: progressIndicator.center.y) - startIndicator.center = CGPoint(x: startPosition , y: startIndicator.center.y) - endIndicator.center = CGPoint(x: endPosition , y: endIndicator.center.y) + progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) + startIndicator.center = CGPoint(x: startPosition, y: startIndicator.center.y) + endIndicator.center = CGPoint(x: endPosition, y: endIndicator.center.y) let startPercentage = startIndicator.center.x * 100 / self.frame.width let endPercentage = endIndicator.center.x * 100 / self.frame.width @@ -426,7 +425,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { self.delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) - if self.progressPercentage != progressPercentage{ + if self.progressPercentage != progressPercentage { let progressSeconds = secondsFromValue(value: progressPercentage) self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) } @@ -437,13 +436,13 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { layoutSubviews() } - + // MARK: - Drag Functions Helpers - private func positionFromValue(value: CGFloat) -> CGFloat{ + private func positionFromValue(value: CGFloat) -> CGFloat { let position = value * self.frame.size.width / 100 return position } - + private func getPositionLimits(with drag: DragHandleChoice) -> (min: CGFloat, max: CGFloat) { if drag == .start { return ( @@ -457,7 +456,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { ) } } - + private func checkEdgeCasesForPosition(with position: CGFloat, and positionLimit: CGFloat, and drag: DragHandleChoice) -> CGFloat { if drag == .start { if Float(self.duration) < self.minSpace { @@ -476,36 +475,36 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } } - + return position } - - private func secondsFromValue(value: CGFloat) -> Float64{ + + private func secondsFromValue(value: CGFloat) -> Float64 { return duration * Float64((value / 100)) } - private func valueFromSeconds(seconds: Float) -> CGFloat{ + private func valueFromSeconds(seconds: Float) -> CGFloat { return CGFloat(seconds * 100) / CGFloat(duration) } - + private func updateGestureStatus(recognizer: UIGestureRecognizer) { if recognizer.state == .began { - + self.isReceivingGesture = true self.delegate?.sliderGesturesBegan?() - + } else if recognizer.state == .ended { - + self.isReceivingGesture = false self.delegate?.sliderGesturesEnded?() } } - + private func resetProgressPosition() { self.progressPercentage = self.startPercentage let progressPosition = positionFromValue(value: self.progressPercentage) - progressIndicator.center = CGPoint(x: progressPosition , y: progressIndicator.center.y) - + progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) + let startSeconds = secondsFromValue(value: self.progressPercentage) self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: startSeconds) } @@ -530,7 +529,6 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { width: endIndicator.frame.origin.x - startIndicator.frame.origin.x - endIndicator.frame.size.width, height: self.frame.height) - topLine.frame = CGRect(x: startIndicator.frame.origin.x + startIndicator.frame.width, y: -topBorderHeight, width: endIndicator.frame.origin.x - startIndicator.frame.origin.x - endIndicator.frame.size.width, @@ -546,7 +544,6 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { endTimeView.center = CGPoint(x: endIndicator.center.x, y: endTimeView.center.y) } - override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool { let extendedBounds = CGRect(x: -startIndicator.frame.size.width, y: -topLine.frame.size.height, @@ -555,11 +552,10 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { return extendedBounds.contains(point) } - - private func secondsToFormattedString(totalSeconds: Float64) -> String{ - let hours:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 86400) / 3600) - let minutes:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 3600) / 60) - let seconds:Int = Int(totalSeconds.truncatingRemainder(dividingBy: 60)) + private func secondsToFormattedString(totalSeconds: Float64) -> String { + let hours: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 86400) / 3600) + let minutes: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 3600) / 60) + let seconds: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 60)) if hours > 0 { return String(format: "%i:%02i:%02i", hours, minutes, seconds) diff --git a/Example/ABVideoRangeSlider/AppDelegate.swift b/Example/ABVideoRangeSlider/AppDelegate.swift index 719e288..15b0aaf 100644 --- a/Example/ABVideoRangeSlider/AppDelegate.swift +++ b/Example/ABVideoRangeSlider/AppDelegate.swift @@ -13,7 +13,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true @@ -41,6 +40,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - } - diff --git a/Example/ABVideoRangeSlider/ViewController.swift b/Example/ABVideoRangeSlider/ViewController.swift index bbd4c5a..a4ed4af 100644 --- a/Example/ABVideoRangeSlider/ViewController.swift +++ b/Example/ABVideoRangeSlider/ViewController.swift @@ -18,9 +18,9 @@ class ViewController: UIViewController, ABVideoRangeSliderDelegate { @IBOutlet var lblStart: UILabel! @IBOutlet var lblEnd: UILabel! @IBOutlet var lblMinSpace: UILabel! - - let path = Bundle.main.path(forResource: "test", ofType:"mp4") - + + let path = Bundle.main.path(forResource: "test", ofType: "mp4") + override func viewDidLoad() { super.viewDidLoad() } @@ -33,7 +33,7 @@ class ViewController: UIViewController, ABVideoRangeSliderDelegate { playerViewController.player!.play() } } - + override func viewWillAppear(_ animated: Bool) { videoRangeSlider.setVideoURL(videoURL: URL(fileURLWithPath: path!)) videoRangeSlider.delegate = self @@ -41,13 +41,13 @@ class ViewController: UIViewController, ABVideoRangeSliderDelegate { // videoRangeSlider.maxSpace = 180.0 lblMinSpace.text = "\(videoRangeSlider.minSpace)" - + // Set initial position of Start Indicator videoRangeSlider.setStartPosition(seconds: 50.0) - + // Set initial position of End Indicator videoRangeSlider.setEndPosition(seconds: 150.0) - + /* Uncomment to customize the Video Range Slider */ /* let customStartIndicator = UIImage(named: "CustomStartIndicator") @@ -63,8 +63,6 @@ class ViewController: UIViewController, ABVideoRangeSliderDelegate { videoRangeSlider.setProgressIndicatorImage(image: customProgressIndicator!) */ - - // Customize starTimeView let customView = UIView(frame: CGRect(x: 0, y: 0, @@ -80,14 +78,14 @@ class ViewController: UIViewController, ABVideoRangeSliderDelegate { videoRangeSlider.startTimeView.marginRight = 2.0 videoRangeSlider.startTimeView.timeLabel.textColor = .white } - + // MARK: ABVideoRangeSlider Delegate - Returns time in seconds - + func didChangeValue(videoRangeSlider: ABVideoRangeSlider, startTime: Float64, endTime: Float64) { lblStart.text = "\(startTime)" lblEnd.text = "\(endTime)" } - + func indicatorDidChangePosition(videoRangeSlider: ABVideoRangeSlider, position: Float64) { print("position of indicator: \(position)") } diff --git a/Example/Tests/Tests.swift b/Example/Tests/Tests.swift index 5c87877..bb2bd8f 100644 --- a/Example/Tests/Tests.swift +++ b/Example/Tests/Tests.swift @@ -3,27 +3,27 @@ import XCTest import ABVideoRangeSlider class Tests: XCTestCase { - + override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - + override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } - + func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } - + func testPerformanceExample() { // This is an example of a performance test case. - self.measure() { + self.measure { // Put the code you want to measure the time of here. } } - + } From 14ff9f5e22cef0929e24dc002a027a9577539eea Mon Sep 17 00:00:00 2001 From: Warren Burton Date: Wed, 30 Jan 2019 10:47:16 +0000 Subject: [PATCH 3/6] open access to initWithFrame --- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 148e7e5..ceb2aa8 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -67,7 +67,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { self.setup() } - override init(frame: CGRect) { + override public init(frame: CGRect) { super.init(frame: frame) self.setup() } From 5efbfdd4340c56800537131baffa785865e59d23 Mon Sep 17 00:00:00 2001 From: Warren Burton Date: Wed, 30 Jan 2019 10:48:47 +0000 Subject: [PATCH 4/6] fix crash if using setStartPosition/setEndPostion methods before setting URL --- ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index ceb2aa8..6d19ef1 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -484,7 +484,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } private func valueFromSeconds(seconds: Float) -> CGFloat { - return CGFloat(seconds * 100) / CGFloat(duration) + return duration > 0 ? CGFloat(seconds * 100) / CGFloat(duration):0 } private func updateGestureStatus(recognizer: UIGestureRecognizer) { From 5b1863a30290d975032ccfaed949382dc7341365 Mon Sep 17 00:00:00 2001 From: Warren Burton Date: Wed, 20 Feb 2019 12:59:37 +0000 Subject: [PATCH 5/6] - Fix handle touch unavailability at 0 and End - Allow subsecond accuracy in trimmer handles --- ABVideoRangeSlider.podspec | 7 +++--- .../Classes/ABVideoRangeSlider.swift | 23 ++++++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ABVideoRangeSlider.podspec b/ABVideoRangeSlider.podspec index 6b6b74a..2439c9d 100644 --- a/ABVideoRangeSlider.podspec +++ b/ABVideoRangeSlider.podspec @@ -8,8 +8,8 @@ Pod::Spec.new do |s| s.name = 'ABVideoRangeSlider' - s.version = '0.1.5' - s.summary = 'A simple range slider for trimming videos written in Swift 3. Includes a Progress Indicator.' + s.version = '0.1.6' + s.summary = 'A simple range slider for trimming videos written in Swift 4. Includes a Progress Indicator.' # This description is used to generate tags and improve search results. # * Think: What does it do? Why did you write it? What is the focus? @@ -20,13 +20,12 @@ Pod::Spec.new do |s| s.description = 'Display thumbnails and a slider for trimming videos in iOS. Includes a Progress Indicator' s.homepage = 'https://github.com/AppsBoulevard/ABVideoRangeSlider' - # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'Oscar J. Irun' => 'oscarjiv91@gmail.com' } s.source = { :git => 'https://github.com/AppsBoulevard/ABVideoRangeSlider.git', :tag => s.version.to_s } s.social_media_url = 'https://twitter.com/AppsBoulevard' - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '12.0' s.source_files = 'ABVideoRangeSlider/Classes/**/*', 'ABVideoRangeSlider/Assets/*' diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 6d19ef1..368be6d 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -87,7 +87,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { y: -topBorderHeight, width: 20, height: self.frame.size.height + bottomBorderHeight + topBorderHeight)) - startIndicator.layer.anchorPoint = CGPoint(x: 1, y: 0.5) + startIndicator.layer.anchorPoint = CGPoint(x: 0, y: 0.5) startIndicator.addGestureRecognizer(startDrag) self.addSubview(startIndicator) @@ -100,7 +100,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { y: -topBorderHeight, width: indicatorWidth, height: self.frame.size.height + bottomBorderHeight + topBorderHeight)) - endIndicator.layer.anchorPoint = CGPoint(x: 0, y: 0.5) + endIndicator.layer.anchorPoint = CGPoint(x: 1, y: 0.5) endIndicator.addGestureRecognizer(endDrag) self.addSubview(endIndicator) @@ -159,8 +159,19 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "bounds"{ self.updateThumbnails() + self.updateHandles() } } + + private func updateHandles() { + var newStart = startIndicator.frame + newStart.size.height = bounds.height + startIndicator.frame = newStart + + var newEnd = endIndicator.frame + newEnd.size.height = bounds.height + endIndicator.frame = newEnd + } // MARK: Public functions @@ -553,14 +564,14 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } private func secondsToFormattedString(totalSeconds: Float64) -> String { - let hours: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 86400) / 3600) let minutes: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 3600) / 60) let seconds: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 60)) + let subseconds: Int = Int(totalSeconds.truncatingRemainder(dividingBy: 1) * 10) - if hours > 0 { - return String(format: "%i:%02i:%02i", hours, minutes, seconds) + if minutes > 0 { + return String(format: "%i:%02i.%i", minutes, seconds, subseconds) } else { - return String(format: "%02i:%02i", minutes, seconds) + return String(format: "%i.%i", seconds, subseconds) } } From 71fcb6e9b92abed57825be523ac64867e8ebee4d Mon Sep 17 00:00:00 2001 From: Warren Burton Date: Thu, 21 Feb 2019 12:29:05 +0000 Subject: [PATCH 6/6] Strip many `.self` uses Add customisations for: - progress indictor doesn't track start end indicators - reset handles --- ABVideoRangeSlider/Classes/ABTimeView.swift | 5 +- .../Classes/ABVideoRangeSlider.swift | 312 +++++++++--------- 2 files changed, 163 insertions(+), 154 deletions(-) diff --git a/ABVideoRangeSlider/Classes/ABTimeView.swift b/ABVideoRangeSlider/Classes/ABTimeView.swift index 681185f..01f8b33 100644 --- a/ABVideoRangeSlider/Classes/ABTimeView.swift +++ b/ABVideoRangeSlider/Classes/ABTimeView.swift @@ -46,13 +46,14 @@ open class ABTimeView: UIView { // Add Background View self.backgroundView.frame = self.bounds - self.backgroundView.backgroundColor = UIColor.yellow + self.backgroundView.backgroundColor = .yellow + self.backgroundView.layer.cornerRadius = 3.0 self.addSubview(self.backgroundView) // Add time label self.timeLabel = UILabel() self.timeLabel.textAlignment = .center - self.timeLabel.textColor = UIColor.lightGray + self.timeLabel.textColor = .lightGray self.addSubview(self.timeLabel) } diff --git a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift index 368be6d..afbee91 100644 --- a/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift +++ b/ABVideoRangeSlider/Classes/ABVideoRangeSlider.swift @@ -18,7 +18,7 @@ import UIKit public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { - private enum DragHandleChoice { + private enum DragHandle { case start case end } @@ -34,25 +34,29 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { public var startTimeView = ABTimeView() public var endTimeView = ABTimeView() + + let thumbnailsManager = ABThumbnailsManager() var duration: Float64 = 0.0 var videoURL = URL(fileURLWithPath: "") - var progressPercentage: CGFloat = 0 // Represented in percentage - var startPercentage: CGFloat = 0 // Represented in percentage - var endPercentage: CGFloat = 100 // Represented in percentage + var progressPercentage: CGFloat = 0 /// Represented in percentage (0-100) + var startPercentage: CGFloat = 0 /// Represented in percentage (0-100) + var endPercentage: CGFloat = 100 /// Represented in percentage (0-100) let topBorderHeight: CGFloat = 5 let bottomBorderHeight: CGFloat = 5 + let timeviewHeight:CGFloat = 25 let indicatorWidth: CGFloat = 20.0 public var minSpace: Float = 1 // In Seconds public var maxSpace: Float = 0 // In Seconds - public var isProgressIndicatorSticky: Bool = false - public var isProgressIndicatorDraggable: Bool = true + public var isProgressIndicatorDraggable = false + public var rangeHandleChangeResetsProgress = false /// range handle change will effect progress indicator + public var rangeHandlesConstrainProgress = false /// progress indicator is bounded by start/end range var isUpdatingThumbnails = false var isReceivingGesture: Bool = false @@ -64,12 +68,12 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { override public func awakeFromNib() { super.awakeFromNib() - self.setup() + setup() } override public init(frame: CGRect) { super.init(frame: frame) - self.setup() + setup() } required public init?(coder aDecoder: NSCoder) { @@ -77,7 +81,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } private func setup() { - self.isUserInteractionEnabled = true + isUserInteractionEnabled = true // Setup Start Indicator let startDrag = UIPanGestureRecognizer(target: self, @@ -86,10 +90,10 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { startIndicator = ABStartIndicator(frame: CGRect(x: 0, y: -topBorderHeight, width: 20, - height: self.frame.size.height + bottomBorderHeight + topBorderHeight)) + height: frame.size.height + bottomBorderHeight + topBorderHeight)) startIndicator.layer.anchorPoint = CGPoint(x: 0, y: 0.5) startIndicator.addGestureRecognizer(startDrag) - self.addSubview(startIndicator) + addSubview(startIndicator) // Setup End Indicator @@ -99,10 +103,10 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { endIndicator = ABEndIndicator(frame: CGRect(x: 0, y: -topBorderHeight, width: indicatorWidth, - height: self.frame.size.height + bottomBorderHeight + topBorderHeight)) + height: frame.size.height + bottomBorderHeight + topBorderHeight)) endIndicator.layer.anchorPoint = CGPoint(x: 1, y: 0.5) endIndicator.addGestureRecognizer(endDrag) - self.addSubview(endIndicator) + addSubview(endIndicator) // Setup Top and bottom line @@ -110,15 +114,15 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { y: -topBorderHeight, width: indicatorWidth, height: topBorderHeight)) - self.addSubview(topLine) + addSubview(topLine) bottomLine = ABBorder(frame: CGRect(x: 0, - y: self.frame.size.height, + y: frame.size.height, width: indicatorWidth, height: bottomBorderHeight)) - self.addSubview(bottomLine) + addSubview(bottomLine) - self.addObserver(self, + addObserver(self, forKeyPath: "bounds", options: NSKeyValueObservingOptions(rawValue: 0), context: nil) @@ -131,9 +135,9 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { progressIndicator = ABProgressIndicator(frame: CGRect(x: 0, y: -topBorderHeight, width: 10, - height: self.frame.size.height + bottomBorderHeight + topBorderHeight)) + height: frame.size.height + bottomBorderHeight + topBorderHeight)) progressIndicator.addGestureRecognizer(progressDrag) - self.addSubview(progressIndicator) + addSubview(progressIndicator) // Setup Draggable View @@ -141,25 +145,25 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { action: #selector(viewDragged(recognizer:))) draggableView.addGestureRecognizer(viewDrag) - self.draggableView.backgroundColor = .clear - self.addSubview(draggableView) - self.sendSubviewToBack(draggableView) + draggableView.backgroundColor = .clear + addSubview(draggableView) + sendSubviewToBack(draggableView) // Setup time labels - startTimeView = ABTimeView(size: CGSize(width: 60, height: 30), position: 1) + startTimeView = ABTimeView(size: CGSize(width: 60, height: 25), position: 1) startTimeView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) - self.addSubview(startTimeView) + addSubview(startTimeView) - endTimeView = ABTimeView(size: CGSize(width: 60, height: 30), position: 1) + endTimeView = ABTimeView(size: CGSize(width: 60, height: 25), position: 1) endTimeView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5) - self.addSubview(endTimeView) + addSubview(endTimeView) } public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "bounds"{ - self.updateThumbnails() - self.updateHandles() + updateThumbnails() + updateHandles() } } @@ -176,25 +180,26 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // MARK: Public functions public func setProgressIndicatorImage(image: UIImage) { - self.progressIndicator.imageView.image = image + progressIndicator.imageView.image = image } public func hideProgressIndicator() { - self.progressIndicator.isHidden = true + progressIndicator.isHidden = true } public func showProgressIndicator() { - self.progressIndicator.isHidden = false + progressIndicator.isHidden = false } public func updateProgressIndicator(seconds: Float64) { if !isReceivingGesture { - let endSeconds = secondsFromValue(value: self.endPercentage) - - if seconds >= endSeconds { - self.resetProgressPosition() + + let endSeconds = secondsFromValue(value: endPercentage) + let shouldReset = seconds >= endSeconds && rangeHandlesConstrainProgress + if shouldReset { + resetProgressPosition() } else { - self.progressPercentage = self.valueFromSeconds(seconds: Float(seconds)) + progressPercentage = valueFromSeconds(seconds: Float(seconds)) } layoutSubviews() @@ -202,21 +207,21 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } public func setStartIndicatorImage(image: UIImage) { - self.startIndicator.imageView.image = image + startIndicator.imageView.image = image } public func setEndIndicatorImage(image: UIImage) { - self.endIndicator.imageView.image = image + endIndicator.imageView.image = image } public func setBorderImage(image: UIImage) { - self.topLine.imageView.image = image - self.bottomLine.imageView.image = image + topLine.imageView.image = image + bottomLine.imageView.image = image } public func setTimeView(view: ABTimeView) { - self.startTimeView = view - self.endTimeView = view + startTimeView = view + endTimeView = view } public func setTimeViewPosition(position: ABTimeViewPosition) { @@ -231,15 +236,15 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } public func setVideoURL(videoURL: URL) { - self.duration = ABVideoHelper.videoDuration(videoURL: videoURL) + duration = ABVideoHelper.videoDuration(videoURL: videoURL) self.videoURL = videoURL - self.superview?.layoutSubviews() - self.updateThumbnails() + superview?.layoutSubviews() + updateThumbnails() } public func updateThumbnails() { if !isUpdatingThumbnails { - self.isUpdatingThumbnails = true + isUpdatingThumbnails = true let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background, target: nil) backgroundQueue.async { _ = self.thumbnailsManager.updateThumbnails(view: self, videoURL: self.videoURL, duration: self.duration) @@ -249,12 +254,18 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } public func setStartPosition(seconds: Float) { - self.startPercentage = self.valueFromSeconds(seconds: seconds) + startPercentage = valueFromSeconds(seconds: seconds) layoutSubviews() } public func setEndPosition(seconds: Float) { - self.endPercentage = self.valueFromSeconds(seconds: seconds) + endPercentage = valueFromSeconds(seconds: seconds) + layoutSubviews() + } + + public func resetHandles() { + startPercentage = 0 + endPercentage = 100 layoutSubviews() } @@ -262,49 +273,46 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { // MARK: - Crop Handle Drag Functions @objc private func startDragged(recognizer: UIPanGestureRecognizer) { - self.processHandleDrag( + processHandleDrag( recognizer: recognizer, - drag: .start, - currentPositionPercentage: self.startPercentage, - currentIndicator: self.startIndicator + handle: .start, + currentPositionPercentage: startPercentage, + currentIndicator: startIndicator ) } @objc private func endDragged(recognizer: UIPanGestureRecognizer) { - self.processHandleDrag( + processHandleDrag( recognizer: recognizer, - drag: .end, - currentPositionPercentage: self.endPercentage, - currentIndicator: self.endIndicator + handle: .end, + currentPositionPercentage: endPercentage, + currentIndicator: endIndicator ) } private func processHandleDrag( recognizer: UIPanGestureRecognizer, - drag: DragHandleChoice, + handle: DragHandle, currentPositionPercentage: CGFloat, currentIndicator: UIView ) { - self.updateGestureStatus(recognizer: recognizer) - + updateGestureStatus(recognizer: recognizer) let translation = recognizer.translation(in: self) - - var position: CGFloat = positionFromValue(value: currentPositionPercentage) // self.startPercentage or self.endPercentage - + + var position: CGFloat = positionFromValue(value: currentPositionPercentage) // startPercentage or endPercentage position = position + translation.x - if position < 0 { position = 0 } - if position > self.frame.size.width { - position = self.frame.size.width + if position > frame.size.width { + position = frame.size.width } - let positionLimits = getPositionLimits(with: drag) - position = checkEdgeCasesForPosition(with: position, and: positionLimits.min, and: drag) + let positionLimits = getPositionLimits(with: handle) + position = checkEdgeCasesForPosition(with: position, and: positionLimits.min, and: handle) - if Float(self.duration) > self.maxSpace && self.maxSpace > 0 { - if drag == .start { + if Float(duration) > maxSpace && maxSpace > 0 { + if handle == .start { if position < positionLimits.max { position = positionLimits.max } @@ -316,47 +324,51 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } recognizer.setTranslation(CGPoint.zero, in: self) - currentIndicator.center = CGPoint(x: position, y: currentIndicator.center.y) + let percentage = currentIndicator.center.x * 100 / frame.width + let startSeconds = secondsFromValue(value: startPercentage) + let endSeconds = secondsFromValue(value: endPercentage) - let percentage = currentIndicator.center.x * 100 / self.frame.width - - let startSeconds = secondsFromValue(value: self.startPercentage) - let endSeconds = secondsFromValue(value: self.endPercentage) - - self.delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) - - var progressPosition: CGFloat = 0.0 + delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) - if drag == .start { - self.startPercentage = percentage + if handle == .start { + startPercentage = percentage } else { - self.endPercentage = percentage + endPercentage = percentage } - if drag == .start { - progressPosition = positionFromValue(value: self.startPercentage) + if rangeHandleChangeResetsProgress { + resetProgressIndicatorForHandle(handle, recognizer: recognizer) + } + layoutSubviews() + } + + private func resetProgressIndicatorForHandle(_ drag: DragHandle, recognizer: UIGestureRecognizer) { + + var progressPosition: CGFloat = 0.0 + + if drag == .start { + progressPosition = positionFromValue(value: startPercentage) } else { if recognizer.state != .ended { - progressPosition = positionFromValue(value: self.endPercentage) + progressPosition = positionFromValue(value: endPercentage) } else { - progressPosition = positionFromValue(value: self.startPercentage) + progressPosition = positionFromValue(value: startPercentage) } } - + progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) - let progressPercentage = progressIndicator.center.x * 100 / self.frame.width - - if self.progressPercentage != progressPercentage { + let progressPercentage = progressIndicator.center.x * 100 / frame.width + + if progressPercentage != progressPercentage { let progressSeconds = secondsFromValue(value: progressPercentage) - self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) + delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) } - + self.progressPercentage = progressPercentage - - layoutSubviews() } + @objc func progressDragged(recognizer: UIPanGestureRecognizer) { if !isProgressIndicatorDraggable { @@ -367,10 +379,10 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { let translation = recognizer.translation(in: self) - let positionLimitStart = positionFromValue(value: self.startPercentage) - let positionLimitEnd = positionFromValue(value: self.endPercentage) + let positionLimitStart = positionFromValue(value: startPercentage) + let positionLimitEnd = positionFromValue(value: endPercentage) - var position = positionFromValue(value: self.progressPercentage) + var position = positionFromValue(value: progressPercentage) position = position + translation.x if position < positionLimitStart { @@ -382,17 +394,11 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } recognizer.setTranslation(CGPoint.zero, in: self) - progressIndicator.center = CGPoint(x: position, y: progressIndicator.center.y) - - let percentage = progressIndicator.center.x * 100 / self.frame.width - + let percentage = progressIndicator.center.x * 100 / frame.width let progressSeconds = secondsFromValue(value: progressPercentage) - - self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) - - self.progressPercentage = percentage - + delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) + progressPercentage = percentage layoutSubviews() } @@ -401,9 +407,9 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { let translation = recognizer.translation(in: self) - var progressPosition = positionFromValue(value: self.progressPercentage) - var startPosition = positionFromValue(value: self.startPercentage) - var endPosition = positionFromValue(value: self.endPercentage) + var progressPosition = positionFromValue(value: progressPercentage) + var startPosition = positionFromValue(value: startPercentage) + var endPosition = positionFromValue(value: endPercentage) startPosition = startPosition + translation.x endPosition = endPosition + translation.x @@ -415,62 +421,64 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { progressPosition = progressPosition - translation.x } - if endPosition > self.frame.size.width { - endPosition = self.frame.size.width + if endPosition > frame.size.width { + endPosition = frame.size.width startPosition = startPosition - translation.x progressPosition = progressPosition - translation.x } recognizer.setTranslation(CGPoint.zero, in: self) - progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) startIndicator.center = CGPoint(x: startPosition, y: startIndicator.center.y) endIndicator.center = CGPoint(x: endPosition, y: endIndicator.center.y) - let startPercentage = startIndicator.center.x * 100 / self.frame.width - let endPercentage = endIndicator.center.x * 100 / self.frame.width - let progressPercentage = progressIndicator.center.x * 100 / self.frame.width - + let startPercentage = startIndicator.center.x * 100 / frame.width + let endPercentage = endIndicator.center.x * 100 / frame.width + let startSeconds = secondsFromValue(value: startPercentage) let endSeconds = secondsFromValue(value: endPercentage) - - self.delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) - - if self.progressPercentage != progressPercentage { - let progressSeconds = secondsFromValue(value: progressPercentage) - self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) - } - + + delegate?.didChangeValue(videoRangeSlider: self, startTime: startSeconds, endTime: endSeconds) + self.startPercentage = startPercentage self.endPercentage = endPercentage - self.progressPercentage = progressPercentage - + + if rangeHandleChangeResetsProgress { + progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) + let progressPercentage = progressIndicator.center.x * 100 / frame.width + if progressPercentage != progressPercentage { + let progressSeconds = secondsFromValue(value: progressPercentage) + delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: progressSeconds) + } + self.progressPercentage = progressPercentage + } + layoutSubviews() } // MARK: - Drag Functions Helpers private func positionFromValue(value: CGFloat) -> CGFloat { - let position = value * self.frame.size.width / 100 + let position = value * frame.size.width / 100 return position } - private func getPositionLimits(with drag: DragHandleChoice) -> (min: CGFloat, max: CGFloat) { + private func getPositionLimits(with drag: DragHandle) -> (min: CGFloat, max: CGFloat) { if drag == .start { return ( - positionFromValue(value: self.endPercentage - valueFromSeconds(seconds: self.minSpace)), - positionFromValue(value: self.endPercentage - valueFromSeconds(seconds: self.maxSpace)) + positionFromValue(value: endPercentage - valueFromSeconds(seconds: minSpace)), + positionFromValue(value: endPercentage - valueFromSeconds(seconds: maxSpace)) ) } else { return ( - positionFromValue(value: self.startPercentage + valueFromSeconds(seconds: self.minSpace)), - positionFromValue(value: self.startPercentage + valueFromSeconds(seconds: self.maxSpace)) + positionFromValue(value: startPercentage + valueFromSeconds(seconds: minSpace)), + positionFromValue(value: startPercentage + valueFromSeconds(seconds: maxSpace)) ) } } - private func checkEdgeCasesForPosition(with position: CGFloat, and positionLimit: CGFloat, and drag: DragHandleChoice) -> CGFloat { + private func checkEdgeCasesForPosition(with position: CGFloat, and positionLimit: CGFloat, and drag: DragHandle) -> CGFloat { if drag == .start { - if Float(self.duration) < self.minSpace { + if Float(duration) < minSpace { return 0 } else { if position > positionLimit { @@ -478,8 +486,8 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { } } } else { - if Float(self.duration) < self.minSpace { - return self.frame.size.width + if Float(duration) < minSpace { + return frame.size.width } else { if position < positionLimit { return positionLimit @@ -501,23 +509,23 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { private func updateGestureStatus(recognizer: UIGestureRecognizer) { if recognizer.state == .began { - self.isReceivingGesture = true - self.delegate?.sliderGesturesBegan?() + isReceivingGesture = true + delegate?.sliderGesturesBegan?() } else if recognizer.state == .ended { - self.isReceivingGesture = false - self.delegate?.sliderGesturesEnded?() + isReceivingGesture = false + delegate?.sliderGesturesEnded?() } } private func resetProgressPosition() { - self.progressPercentage = self.startPercentage - let progressPosition = positionFromValue(value: self.progressPercentage) + progressPercentage = startPercentage + let progressPosition = positionFromValue(value: progressPercentage) progressIndicator.center = CGPoint(x: progressPosition, y: progressIndicator.center.y) - let startSeconds = secondsFromValue(value: self.progressPercentage) - self.delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: startSeconds) + let startSeconds = secondsFromValue(value: progressPercentage) + delegate?.indicatorDidChangePosition(videoRangeSlider: self, position: startSeconds) } // MARK: - @@ -525,12 +533,12 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { override public func layoutSubviews() { super.layoutSubviews() - startTimeView.timeLabel.text = self.secondsToFormattedString(totalSeconds: secondsFromValue(value: self.startPercentage)) - endTimeView.timeLabel.text = self.secondsToFormattedString(totalSeconds: secondsFromValue(value: self.endPercentage)) + startTimeView.timeLabel.text = secondsToFormattedString(totalSeconds: secondsFromValue(value: startPercentage)) + endTimeView.timeLabel.text = secondsToFormattedString(totalSeconds: secondsFromValue(value: endPercentage)) - let startPosition = positionFromValue(value: self.startPercentage) - let endPosition = positionFromValue(value: self.endPercentage) - let progressPosition = positionFromValue(value: self.progressPercentage) + let startPosition = positionFromValue(value: startPercentage) + let endPosition = positionFromValue(value: endPercentage) + let progressPosition = positionFromValue(value: progressPercentage) startIndicator.center = CGPoint(x: startPosition, y: startIndicator.center.y) endIndicator.center = CGPoint(x: endPosition, y: endIndicator.center.y) @@ -538,7 +546,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { draggableView.frame = CGRect(x: startIndicator.frame.origin.x + startIndicator.frame.size.width, y: 0, width: endIndicator.frame.origin.x - startIndicator.frame.origin.x - endIndicator.frame.size.width, - height: self.frame.height) + height: frame.height) topLine.frame = CGRect(x: startIndicator.frame.origin.x + startIndicator.frame.width, y: -topBorderHeight, @@ -546,7 +554,7 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { height: topBorderHeight) bottomLine.frame = CGRect(x: startIndicator.frame.origin.x + startIndicator.frame.width, - y: self.frame.size.height, + y: frame.size.height, width: endIndicator.frame.origin.x - startIndicator.frame.origin.x - endIndicator.frame.size.width, height: bottomBorderHeight) @@ -558,8 +566,8 @@ public class ABVideoRangeSlider: UIView, UIGestureRecognizerDelegate { override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool { let extendedBounds = CGRect(x: -startIndicator.frame.size.width, y: -topLine.frame.size.height, - width: self.frame.size.width + startIndicator.frame.size.width + endIndicator.frame.size.width, - height: self.frame.size.height + topLine.frame.size.height + bottomLine.frame.size.height) + width: frame.size.width + startIndicator.frame.size.width + endIndicator.frame.size.width, + height: frame.size.height + topLine.frame.size.height + bottomLine.frame.size.height) return extendedBounds.contains(point) }