From c64caa7a9f8ffd629ccba3bb3516ac34e470268c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 27 Mar 2024 15:24:40 -0500 Subject: [PATCH] added publishers/cancellables Signed-off-by: Matt Bruce --- .../CarouselScrollbar/CarouselScrollbar.swift | 101 +++++++++++++++--- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift b/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift index 260f14e5..5f99c6b7 100644 --- a/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift +++ b/VDS/Components/CarouselScrollbar/CarouselScrollbar.swift @@ -100,25 +100,99 @@ open class CarouselScrollbar: View { setNeedsUpdate() } } - + /// Allows a unique id to be passed into the thumb and track of the thumb(scrubber). open var scrubberId: Int? { didSet { setNeedsUpdate() } } /// A callback when the scrubber position changes. Passes parameters (position). - open var onScrubberDrag: ((Int) -> Void)? + open var onScrubberDrag: ((Int) -> Void)? { + get { nil } + set { + onScrubberDragCancellable?.cancel() + if let newValue { + onScrubberDragCancellable = onScrubberDragPublisher + .sink { c in + newValue(c) + } + } + } + } + + /// A publisher for when the scrubber position changes. Passes parameters (position). + open var onScrubberDragPublisher = PassthroughSubject() + private var onScrubberDragCancellable: AnyCancellable? /// A callback when the thumb move forward. Passes parameters (position). - open var onMoveForward: ((Int) -> Void)? + open var onMoveForward: ((Int) -> Void)? { + get { nil } + set { + onMoveForwardCancellable?.cancel() + if let newValue { + onMoveForwardCancellable = onMoveForwardPublisher + .sink { c in + newValue(c) + } + } + } + } + + /// A publisher for when the thumb move forward. Passes parameters (position). + open var onMoveForwardPublisher = PassthroughSubject() + private var onMoveForwardCancellable: AnyCancellable? /// A callback when the thumb move backward. Passes parameters (position). - open var onMoveBackward: ((Int) -> Void)? + open var onMoveBackward: ((Int) -> Void)? { + get { nil } + set { + onMoveBackwardCancellable?.cancel() + if let newValue { + onMoveBackwardCancellable = onMoveBackwardPublisher + .sink { c in + newValue(c) + } + } + } + } + + /// A publisher for when the thumb move backward. Passes parameters (position). + open var onMoveBackwardPublisher = PassthroughSubject() + private var onMoveBackwardCancellable: AnyCancellable? /// A callback when the thumb touch start. Passes parameters (position). - open var onThumbTouchStart: ((Int) -> Void)? + open var onThumbTouchStart: ((Int) -> Void)? { + get { nil } + set { + onThumbTouchStartCancellable?.cancel() + if let newValue { + onThumbTouchStartCancellable = onThumbTouchStartPublisher + .sink { c in + newValue(c) + } + } + } + } + + /// A publisher for when the thumb touch start. Passes parameters (position). + open var onThumbTouchStartPublisher = PassthroughSubject() + private var onThumbTouchStartCancellable: AnyCancellable? /// A callback when the thumb touch end. Passes parameters (position). - open var onThumbTouchEnd: ((Int) -> Void)? + open var onThumbTouchEnd: ((Int) -> Void)? { + get { nil } + set { + onThumbTouchEndCancellable?.cancel() + if let newValue { + onThumbTouchEndCancellable = onThumbTouchEndPublisher + .sink { c in + newValue(c) + } + } + } + } + /// A publisher for when the thumb touch end. Passes parameters (position). + open var onThumbTouchEndPublisher = PassthroughSubject() + private var onThumbTouchEndCancellable: AnyCancellable? //-------------------------------------------------- // MARK: - Private Properties @@ -250,13 +324,13 @@ open class CarouselScrollbar: View { func movePositionBackward() { position = position - 1 scrollThumbToPosition(position) - self.onMoveBackward?(position) + onMoveBackwardPublisher.send(position) } func movePositionForward() { position = position + 1 scrollThumbToPosition(position) - self.onMoveForward?(position) + onMoveForwardPublisher.send(position) } // Compute track width and should maintain minimum thumb width if needed @@ -298,12 +372,13 @@ open class CarouselScrollbar: View { } private func scrollThumbToPosition(_ position: Int) { - self.setThumb(at: position) - self.onScrubberDrag?(position) + setThumb(at: position) + onScrubberDragPublisher.send(position) } private func setThumb(at position: Int) { - UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveLinear, animations: { + UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveLinear, animations: { [weak self] in + guard let self else { return } self.thumbView.frame.origin.x = CGFloat(Float((position) - 1) * self.computedWidth) + self.trackView.frame.origin.x self.updateActiveOverlays() }) @@ -318,7 +393,7 @@ open class CarouselScrollbar: View { let translation = sender.translation(in: thumbView) if sender.state == UIGestureRecognizer.State.began { trayOriginalCenter = thumbView.center - self.onThumbTouchStart?(position) + onThumbTouchStartPublisher.send(position) } else if sender.state == UIGestureRecognizer.State.changed { let draggedPositions = Int (ceil (Double(translation.x) / Double(computedWidth))) setThumb(at: position + draggedPositions) @@ -327,7 +402,7 @@ open class CarouselScrollbar: View { let draggedPositions = Int (ceil (Double(translation.x) / Double(computedWidth))) position = ((position + draggedPositions) < 1) ? 1 : (position + draggedPositions) if sender.state == UIGestureRecognizer.State.ended { - self.onThumbTouchEnd?(position) + onThumbTouchEndPublisher.send(position) } } }