Fix video gallery controls not auto hiding

#535
This commit is contained in:
Shadowfacts 2024-08-26 10:25:28 -04:00
parent d7be2048af
commit d873b157ee
9 changed files with 45 additions and 35 deletions

View File

@ -17,7 +17,7 @@ public protocol GalleryContentViewController: UIViewController {
var bottomControlsAccessoryViewController: UIViewController? { get } var bottomControlsAccessoryViewController: UIViewController? { get }
var canAnimateFromSourceView: Bool { get } var canAnimateFromSourceView: Bool { get }
func setControlsVisible(_ visible: Bool, animated: Bool) func setControlsVisible(_ visible: Bool, animated: Bool, dueToUserInteraction: Bool)
func galleryContentDidAppear() func galleryContentDidAppear()
func galleryContentWillDisappear() func galleryContentWillDisappear()
} }
@ -35,7 +35,7 @@ public extension GalleryContentViewController {
true true
} }
func setControlsVisible(_ visible: Bool, animated: Bool) { func setControlsVisible(_ visible: Bool, animated: Bool, dueToUserInteraction: Bool) {
} }
func galleryContentDidAppear() { func galleryContentDidAppear() {

View File

@ -106,7 +106,7 @@ class GalleryDismissAnimationController: NSObject, UIViewControllerAnimatedTrans
content.view.frame = sourceFrameInContainer content.view.frame = sourceFrameInContainer
content.view.layer.opacity = 0 content.view.layer.opacity = 0
itemViewController.setControlsVisible(false, animated: false) itemViewController.setControlsVisible(false, animated: false, dueToUserInteraction: false)
} }
animator.addCompletion { _ in animator.addCompletion { _ in

View File

@ -42,7 +42,7 @@ class GalleryDismissInteraction: NSObject {
origControlsVisible = viewController.currentItemViewController.controlsVisible origControlsVisible = viewController.currentItemViewController.controlsVisible
if origControlsVisible! { if origControlsVisible! {
viewController.currentItemViewController.setControlsVisible(false, animated: true) viewController.currentItemViewController.setControlsVisible(false, animated: true, dueToUserInteraction: false)
} }
case .changed: case .changed:

View File

@ -213,7 +213,7 @@ class GalleryItemViewController: UIViewController {
updateZoomScale(resetZoom: false) updateZoomScale(resetZoom: false)
// Ensure the transform is correct if the controls are hidden // Ensure the transform is correct if the controls are hidden
setControlsVisible(controlsVisible, animated: false) setControlsVisible(controlsVisible, animated: false, dueToUserInteraction: false)
updateTopControlsInsets() updateTopControlsInsets()
} }
@ -229,7 +229,7 @@ class GalleryItemViewController: UIViewController {
} }
centerContent() centerContent()
// Ensure the transform is correct if the controls are hidden and their size changed. // Ensure the transform is correct if the controls are hidden and their size changed.
setControlsVisible(controlsVisible, animated: false) setControlsVisible(controlsVisible, animated: false, dueToUserInteraction: false)
} }
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
@ -250,7 +250,7 @@ class GalleryItemViewController: UIViewController {
func addContent() { func addContent() {
content.loadViewIfNeeded() content.loadViewIfNeeded()
content.setControlsVisible(controlsVisible, animated: false) content.setControlsVisible(controlsVisible, animated: false, dueToUserInteraction: false)
content.view.translatesAutoresizingMaskIntoConstraints = false content.view.translatesAutoresizingMaskIntoConstraints = false
if content.parent != self { if content.parent != self {
@ -290,7 +290,7 @@ class GalleryItemViewController: UIViewController {
content.view.layoutIfNeeded() content.view.layoutIfNeeded()
} }
func setControlsVisible(_ visible: Bool, animated: Bool) { func setControlsVisible(_ visible: Bool, animated: Bool, dueToUserInteraction: Bool) {
controlsVisible = visible controlsVisible = visible
guard let topControlsView, guard let topControlsView,
@ -301,7 +301,7 @@ class GalleryItemViewController: UIViewController {
func updateControlsViews() { func updateControlsViews() {
topControlsView.transform = CGAffineTransform(translationX: 0, y: visible ? 0 : -topControlsView.bounds.height) topControlsView.transform = CGAffineTransform(translationX: 0, y: visible ? 0 : -topControlsView.bounds.height)
bottomControlsView.transform = CGAffineTransform(translationX: 0, y: visible ? 0 : bottomControlsView.bounds.height) bottomControlsView.transform = CGAffineTransform(translationX: 0, y: visible ? 0 : bottomControlsView.bounds.height)
content.setControlsVisible(visible, animated: animated) content.setControlsVisible(visible, animated: animated, dueToUserInteraction: dueToUserInteraction)
} }
if animated { if animated {
let animator = UIViewPropertyAnimator(duration: 0.2, timingParameters: UISpringTimingParameters()) let animator = UIViewPropertyAnimator(duration: 0.2, timingParameters: UISpringTimingParameters())
@ -429,7 +429,7 @@ class GalleryItemViewController: UIViewController {
scrollView.zoomScale > scrollView.minimumZoomScale { scrollView.zoomScale > scrollView.minimumZoomScale {
animateZoomOut() animateZoomOut()
} else { } else {
setControlsVisible(!controlsVisible, animated: true) setControlsVisible(!controlsVisible, animated: true, dueToUserInteraction: true)
} }
} }
@ -531,7 +531,7 @@ extension GalleryItemViewController: GalleryContentViewControllerContainer {
} }
func setGalleryControlsVisible(_ visible: Bool, animated: Bool) { func setGalleryControlsVisible(_ visible: Bool, animated: Bool) {
setControlsVisible(visible, animated: animated) setControlsVisible(visible, animated: animated, dueToUserInteraction: false)
} }
} }
@ -546,9 +546,9 @@ extension GalleryItemViewController: UIScrollViewDelegate {
func scrollViewDidZoom(_ scrollView: UIScrollView) { func scrollViewDidZoom(_ scrollView: UIScrollView) {
if scrollView.zoomScale <= scrollView.minimumZoomScale { if scrollView.zoomScale <= scrollView.minimumZoomScale {
setControlsVisible(true, animated: true) setControlsVisible(true, animated: true, dueToUserInteraction: true)
} else { } else {
setControlsVisible(false, animated: true) setControlsVisible(false, animated: true, dueToUserInteraction: true)
} }
centerContent() centerContent()

View File

@ -75,7 +75,7 @@ class GalleryPresentationAnimationController: NSObject, UIViewControllerAnimated
container.layoutIfNeeded() container.layoutIfNeeded()
// This needs to take place after the layout, so that the transform is correct. // This needs to take place after the layout, so that the transform is correct.
itemViewController.setControlsVisible(false, animated: false) itemViewController.setControlsVisible(false, animated: false, dueToUserInteraction: false)
let duration = self.transitionDuration(using: transitionContext) let duration = self.transitionDuration(using: transitionContext)
// rougly equivalent to duration: 0.35, bounce: 0.3 // rougly equivalent to duration: 0.35, bounce: 0.3
@ -90,7 +90,7 @@ class GalleryPresentationAnimationController: NSObject, UIViewControllerAnimated
content.view.frame = destFrameInContainer content.view.frame = destFrameInContainer
content.view.layer.opacity = 1 content.view.layer.opacity = 1
itemViewController.setControlsVisible(true, animated: false) itemViewController.setControlsVisible(true, animated: false, dueToUserInteraction: false)
if let sourceToDestTransform { if let sourceToDestTransform {
self.sourceView.transform = sourceToDestTransform self.sourceView.transform = sourceToDestTransform

View File

@ -126,7 +126,7 @@ extension GalleryViewController: UIPageViewControllerDelegate {
public func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) { public func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
currentItemViewController.content.galleryContentWillDisappear() currentItemViewController.content.galleryContentWillDisappear()
let new = pendingViewControllers[0] as! GalleryItemViewController let new = pendingViewControllers[0] as! GalleryItemViewController
new.setControlsVisible(currentItemViewController.controlsVisible, animated: false) new.setControlsVisible(currentItemViewController.controlsVisible, animated: false, dueToUserInteraction: false)
} }
public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

View File

@ -128,7 +128,7 @@ class ImageGalleryContentViewController: UIViewController, GalleryContentViewCon
} }
} }
func setControlsVisible(_ visible: Bool, animated: Bool) { func setControlsVisible(_ visible: Bool, animated: Bool, dueToUserInteraction: Bool) {
if #available(iOS 16.0, macCatalyst 17.0, *), if #available(iOS 16.0, macCatalyst 17.0, *),
let analysisInteraction { let analysisInteraction {
analysisInteraction.setSupplementaryInterfaceHidden(!visible, animated: animated) analysisInteraction.setSupplementaryInterfaceHidden(!visible, animated: animated)

View File

@ -52,7 +52,7 @@ class LoadingGalleryContentViewController: UIViewController, GalleryContentViewC
if let wrapped = await provider() { if let wrapped = await provider() {
self.wrapped = wrapped self.wrapped = wrapped
wrapped.container = container wrapped.container = container
wrapped.setControlsVisible(container?.galleryControlsVisible ?? false, animated: false) wrapped.setControlsVisible(container?.galleryControlsVisible ?? false, animated: false, dueToUserInteraction: false)
addChild(wrapped) addChild(wrapped)
wrapped.view.translatesAutoresizingMaskIntoConstraints = false wrapped.view.translatesAutoresizingMaskIntoConstraints = false
@ -102,8 +102,8 @@ class LoadingGalleryContentViewController: UIViewController, GalleryContentViewC
]) ])
} }
func setControlsVisible(_ visible: Bool, animated: Bool) { func setControlsVisible(_ visible: Bool, animated: Bool, dueToUserInteraction: Bool) {
wrapped?.setControlsVisible(visible, animated: animated) wrapped?.setControlsVisible(visible, animated: animated, dueToUserInteraction: dueToUserInteraction)
} }
func galleryContentDidAppear() { func galleryContentDidAppear() {

View File

@ -86,19 +86,10 @@ class VideoGalleryContentViewController: UIViewController, GalleryContentViewCon
updateItemObservations() updateItemObservations()
rateObservation = player.observe(\.rate, options: .old, changeHandler: { [unowned self] player, info in rateObservation = player.observe(\.rate, options: .old, changeHandler: { [unowned self] player, info in
hideControlsWorkItem?.cancel() if player.rate == 0 {
if player.rate > 0 && info.oldValue == 0 { hideControlsWorkItem?.cancel()
hideControlsWorkItem = DispatchWorkItem { [weak self] in } else if player.rate > 0 && info.oldValue == 0 {
MainActor.runUnsafely { scheduleControlsHide()
guard let self,
let container = self.container,
container.galleryControlsVisible else {
return
}
container.setGalleryControlsVisible(false, animated: true)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5), execute: hideControlsWorkItem!)
} }
}) })
@ -179,6 +170,20 @@ class VideoGalleryContentViewController: UIViewController, GalleryContentViewCon
} }
} }
private func scheduleControlsHide() {
hideControlsWorkItem = DispatchWorkItem { [weak self] in
MainActor.runUnsafely {
guard let self,
let container = self.container,
container.galleryControlsVisible else {
return
}
container.setGalleryControlsVisible(false, animated: true)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5), execute: hideControlsWorkItem!)
}
// MARK: GalleryContentViewController // MARK: GalleryContentViewController
weak var container: (any GalleryVC.GalleryContentViewControllerContainer)? weak var container: (any GalleryVC.GalleryContentViewControllerContainer)?
@ -206,9 +211,14 @@ class VideoGalleryContentViewController: UIViewController, GalleryContentViewCon
private(set) lazy var bottomControlsAccessoryViewController: UIViewController? = VideoControlsViewController(player: player, playbackSpeed: _playbackSpeed) private(set) lazy var bottomControlsAccessoryViewController: UIViewController? = VideoControlsViewController(player: player, playbackSpeed: _playbackSpeed)
#endif #endif
func setControlsVisible(_ visible: Bool, animated: Bool) { func setControlsVisible(_ visible: Bool, animated: Bool, dueToUserInteraction: Bool) {
overlayVC.setVisible(visible) overlayVC.setVisible(visible)
hideControlsWorkItem?.cancel()
if !visible {
hideControlsWorkItem?.cancel()
} else if dueToUserInteraction {
scheduleControlsHide()
}
} }
func galleryContentDidAppear() { func galleryContentDidAppear() {