From 9290e40a2a9a9c9d3268670ec8ebc2209d7b7758 Mon Sep 17 00:00:00 2001 From: vasavk Date: Thu, 21 Mar 2024 21:32:04 +0530 Subject: [PATCH] Digital ACT-191 ONEAPP-6830 story: refactored code --- .../CarouselScrollbar/CarouselScrollbar.swift | 93 ++++++++----------- 1 file changed, 39 insertions(+), 54 deletions(-) diff --git a/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift b/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift index b0337120..6a072ccd 100644 --- a/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift +++ b/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift @@ -35,14 +35,10 @@ open class CarouselScrollbar: View { // MARK: - Public Properties //-------------------------------------------------- /// Used to set total number of slides within carousel - open var numberOfSlides: Int? { + open var numberOfSlides: Int { get { return _numberOfSlides } set { - if let newValue { - _numberOfSlides = newValue - } else { - _numberOfSlides = 1 - } + _numberOfSlides = newValue setThumbWidth() scrollThumbToPosition(position) setNeedsUpdate() @@ -95,15 +91,11 @@ open class CarouselScrollbar: View { } /// Used to set the position of the thumb(scrubber). This is used when the carousel container changes position, it will align the position of thumb(scrubber). - open var position: Int? { + open var position: Int { get { return _position } set { - if let newValue { - checkPositions() - _position = (newValue > totalPositions ?? 1) ? totalPositions : newValue - } else { - _position = 1 - } + checkPositions() + _position = (newValue > totalPositions) ? totalPositions : newValue scrollThumbToPosition(position) setNeedsUpdate() } @@ -121,9 +113,9 @@ open class CarouselScrollbar: View { // Sizes are from InVision design specs. internal var containerSize: CGSize { CGSize(width: 45, height: 44) } internal var _selectedLayout: Layout = .oneUP - internal var _numberOfSlides: Int? = 1 - internal var totalPositions: Int? = 1 - internal var _position: Int? = 1 + internal var _numberOfSlides: Int = 1 + internal var totalPositions: Int = 1 + internal var _position: Int = 1 internal var trayOriginalCenter: CGPoint! private let trackViewWidth = 96 @@ -131,11 +123,13 @@ open class CarouselScrollbar: View { private let minThumbWidth: Float = 16.0 private var thumbWidth: Float = 16.0 private var computedWidth: Float = 0.0 - private let cornerRadius: CGFloat = 4.0 + private let cornerRadius: CGFloat = 2.0 private let activeOpacity: Float = 0.15 private let defaultOpacity: Float = 1 - internal var containerView = View() + internal var containerView = View().with { + $0.clipsToBounds = true + } internal var trackView = View() internal var leftActiveOverlay = View() internal var rightActiveOverlay = View() @@ -182,7 +176,7 @@ open class CarouselScrollbar: View { leftActiveOverlay.frame = CGRectMake(trackView.frame.origin.x, 0, CGFloat(trackViewWidth), containerSize.height) leftActiveOverlay.isUserInteractionEnabled = true leftActiveOverlay.backgroundColor = .clear - let leftPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.onThumbTouchStart(_:))) + let leftPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(onLeftViewLongPressRecognizer(_:))) leftPressRecognizer.minimumPressDuration = 0 leftActiveOverlay.addGestureRecognizer(leftPressRecognizer) containerView.addSubview(leftActiveOverlay) @@ -195,7 +189,7 @@ open class CarouselScrollbar: View { rightActiveOverlay.frame = CGRectMake(thumbView.frame.origin.x + thumbView.frame.size.width, 0, CGFloat(trackViewWidth), containerSize.height) rightActiveOverlay.isUserInteractionEnabled = true rightActiveOverlay.backgroundColor = .clear - let rightPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.onThumbTouchEnd(_:))) + let rightPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(onRightViewLongPressRecognizer(_:))) rightPressRecognizer.minimumPressDuration = 0 rightActiveOverlay.addGestureRecognizer(rightPressRecognizer) containerView.addSubview(rightActiveOverlay) @@ -207,7 +201,7 @@ open class CarouselScrollbar: View { //Thumbview thumbView.frame = CGRectMake(0, 0, CGFloat(thumbWidth), containerSize.height) thumbView.backgroundColor = .clear - thumbView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action:(#selector(self.onScrubberDrag(_:))))) + thumbView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action:(#selector(onScrubberDrag(_:))))) containerView.addSubview(thumbView) updateActiveOverlays() @@ -240,18 +234,18 @@ open class CarouselScrollbar: View { // MARK: - Private Methods //-------------------------------------------------- func onMoveBackward() { - position = (position ?? 1) - 1 + position = position - 1 scrollThumbToPosition(position) } func onMoveForward() { - position = (position ?? 1) + 1 + position = position + 1 scrollThumbToPosition(position) } // Compute track width and should maintain minimum thumb width if needed private func setThumbWidth() { - let width = (Float(trackViewWidth) / Float(numberOfSlides ?? 1)) * Float(_selectedLayout.value) + let width = (Float(trackViewWidth) / Float(numberOfSlides)) * Float(_selectedLayout.value) computedWidth = (width > Float(trackViewWidth)) ? Float(trackViewWidth) : width thumbWidth = (width <= Float(trackViewWidth) && width > minThumbWidth) ? width : ((width > Float(trackViewWidth)) ? Float(trackViewWidth) : minThumbWidth) thumbView.frame.size.width = CGFloat(thumbWidth) @@ -284,12 +278,12 @@ open class CarouselScrollbar: View { } private func checkPositions() { - totalPositions = Int (ceil (Double(numberOfSlides ?? 1) / Double(_selectedLayout.value))) + totalPositions = Int (ceil (Double(numberOfSlides) / Double(_selectedLayout.value))) } private func scrollThumbToPosition(_ position: Int?) { - setThumb(at: position) - onScrubberDidChange?(position ?? 1) + self.setThumb(at: position) + self.onScrubberDidChange?(position ?? 1) } private func setThumb(at position: Int?) { @@ -310,46 +304,37 @@ open class CarouselScrollbar: View { trayOriginalCenter = thumbView.center } else if sender.state == UIGestureRecognizer.State.changed { let draggedPositions = Int (ceil (Double(translation.x) / Double(computedWidth))) - setThumb(at: (position ?? 1) + draggedPositions) + setThumb(at: position + draggedPositions) } else if sender.state == UIGestureRecognizer.State.cancelled || sender.state == UIGestureRecognizer.State.ended { let draggedPositions = Int (ceil (Double(translation.x) / Double(computedWidth))) - position = (((position ?? 1) + draggedPositions) < 1) ? 1 : ((position ?? 1) + draggedPositions) + position = ((position + draggedPositions) < 1) ? 1 : (position + draggedPositions) } } // Move the scrollbar thumb to the left while tapping on the left side of the scrubber. - @objc func onThumbTouchStart(_ gesture: UILongPressGestureRecognizer) { - UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveLinear, animations: { [self] in - if gesture.state == .began { - leftActiveOverlayLayer.backgroundColor = activeOverlayColorConfiguration.getColor(self).cgColor - leftActiveOverlayLayer.opacity = activeOpacity - } else if gesture.state == .cancelled { - leftActiveOverlayLayer.backgroundColor = UIColor.clear.cgColor - leftActiveOverlayLayer.opacity = defaultOpacity - } else if gesture.state == .ended { - leftActiveOverlayLayer.backgroundColor = UIColor.clear.cgColor - leftActiveOverlayLayer.opacity = defaultOpacity - UIView.performWithoutAnimation { - self.onMoveBackward() - } - } - }) + @objc func onLeftViewLongPressRecognizer(_ gesture: UILongPressGestureRecognizer) { + animateOverlay(layer: leftActiveOverlayLayer, with: gesture, onGestureEnd: onMoveBackward) } // Move the scrollbar thumb to the right while tapping on the right side of the scrubber. - @objc func onThumbTouchEnd(_ gesture: UILongPressGestureRecognizer) { - UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveLinear, animations: { [self] in + @objc func onRightViewLongPressRecognizer(_ gesture: UILongPressGestureRecognizer) { + animateOverlay(layer: rightActiveOverlayLayer, with: gesture, onGestureEnd: onMoveForward) + } + + private func animateOverlay(layer: CALayer, with gesture: UILongPressGestureRecognizer, onGestureEnd: @escaping(() -> Void)) { + UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveLinear, animations: { [weak self] in + guard let self else { return } if gesture.state == .began { - rightActiveOverlayLayer.backgroundColor = activeOverlayColorConfiguration.getColor(self).cgColor - rightActiveOverlayLayer.opacity = activeOpacity + layer.backgroundColor = activeOverlayColorConfiguration.getColor(self).cgColor + layer.opacity = activeOpacity } else if gesture.state == .cancelled { - rightActiveOverlayLayer.backgroundColor = UIColor.clear.cgColor - rightActiveOverlayLayer.opacity = defaultOpacity + layer.backgroundColor = UIColor.clear.cgColor + layer.opacity = defaultOpacity } else if gesture.state == .ended { - rightActiveOverlayLayer.backgroundColor = UIColor.clear.cgColor - rightActiveOverlayLayer.opacity = defaultOpacity - self.onMoveForward() + layer.backgroundColor = UIColor.clear.cgColor + layer.opacity = defaultOpacity + onGestureEnd() } }) }