From 163358b3fa0cdba46a1e6dba08fe3af88a571a14 Mon Sep 17 00:00:00 2001 From: Ibrahim Sulejmenov Date: Sat, 19 Apr 2025 22:33:17 +0200 Subject: [PATCH] dim mode --- .../CustomPlayer/CustomPlayer.swift | 118 +++++++++++++++++- 1 file changed, 112 insertions(+), 6 deletions(-) diff --git a/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift b/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift index aea8c01..4bcd995 100644 --- a/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift +++ b/Sora/Utils/MediaPlayer/CustomPlayer/CustomPlayer.swift @@ -126,6 +126,29 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele private var loadedTimeRangesObservation: NSKeyValueObservation? private var playerTimeControlStatusObserver: NSKeyValueObservation? + private var isDimmed = false + private var dimButton: UIButton! + private var dimButtonToSlider: NSLayoutConstraint! + private var dimButtonToRight: NSLayoutConstraint! + private var dimButtonTimer: Timer? + + private lazy var controlsToHide: [UIView] = [ + dismissButton, + playPauseButton, + backwardButton, + forwardButton, + sliderHostingController!.view, + skip85Button, + marqueeLabel, + menuButton, + qualityButton, + speedButton, + watchNextButton, + volumeSliderHostingView! + ] + + private var originalHiddenStates: [UIView: Bool] = [:] + private var volumeObserver: NSKeyValueObservation? private var audioSession = AVAudioSession.sharedInstance() private var hiddenVolumeView = MPVolumeView(frame: .zero) @@ -195,6 +218,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele setupSubtitleLabel() setupDismissButton() volumeSlider() + setupDimButton() setupSpeedButton() setupQualityButton() setupMenuButton() @@ -204,6 +228,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele startUpdateTimer() setupAudioSession() + controlsToHide.forEach { originalHiddenStates[$0] = $0.isHidden } DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in self?.checkForHLSStream() @@ -784,6 +809,38 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele ]) } + private func setupDimButton() { + let cfg = UIImage.SymbolConfiguration(pointSize: 24, weight: .regular) + dimButton = UIButton(type: .system) + dimButton.setImage(UIImage(systemName: "moon.fill", withConfiguration: cfg), for: .normal) + dimButton.tintColor = .white + dimButton.addTarget(self, action: #selector(dimTapped), for: .touchUpInside) + controlsContainerView.addSubview(dimButton) + dimButton.translatesAutoresizingMaskIntoConstraints = false + + dimButton.layer.shadowColor = UIColor.black.cgColor + dimButton.layer.shadowOffset = CGSize(width: 0, height: 2) + dimButton.layer.shadowOpacity = 0.6 + dimButton.layer.shadowRadius = 4 + dimButton.layer.masksToBounds = false + + NSLayoutConstraint.activate([ + dimButton.centerYAnchor.constraint(equalTo: dismissButton.centerYAnchor), + dimButton.widthAnchor.constraint(equalToConstant: 24), + dimButton.heightAnchor.constraint(equalToConstant: 24), + ]) + + dimButtonToSlider = dimButton.trailingAnchor.constraint( + equalTo: volumeSliderHostingView!.leadingAnchor, + constant: -8 + ) + dimButtonToRight = dimButton.trailingAnchor.constraint( + equalTo: controlsContainerView.trailingAnchor, + constant: -16 + ) + + dimButtonToSlider.isActive = true + } func updateMarqueeConstraints() { UIView.performWithoutAnimation { @@ -1126,12 +1183,24 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele } @objc func toggleControls() { - isControlsVisible.toggle() - UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseInOut, animations: { - let alphaVal: CGFloat = self.isControlsVisible ? 1 : 0 - self.controlsContainerView.alpha = alphaVal - self.skip85Button.alpha = alphaVal - }) + if isDimmed { + dimButton.isHidden = false + dimButton.alpha = 1.0 + dimButtonTimer?.invalidate() + dimButtonTimer = Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false) { [weak self] _ in + guard let self = self else { return } + UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseInOut]) { + self.dimButton.alpha = 0 + } + } + } else { + isControlsVisible.toggle() + UIView.animate(withDuration: 0.2) { + let a: CGFloat = self.isControlsVisible ? 1 : 0 + self.controlsContainerView.alpha = a + self.skip85Button.alpha = a + } + } } @objc func seekBackwardLongPress(_ gesture: UILongPressGestureRecognizer) { @@ -1241,6 +1310,43 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele } } + @objc private func dimTapped() { + isDimmed.toggle() + + if isDimmed { + originalHiddenStates = [:] + for view in controlsToHide { + originalHiddenStates[view] = view.isHidden + view.isHidden = true + } + + blackCoverView.alpha = 1.0 + + dimButtonToSlider.isActive = false + dimButtonToRight.isActive = true + + dimButton.isHidden = true + + dimButtonTimer?.invalidate() + } else { + for view in controlsToHide { + if let wasHidden = originalHiddenStates[view] { + view.isHidden = wasHidden + } + } + + blackCoverView.alpha = 0.4 + + dimButtonToRight.isActive = false + dimButtonToSlider.isActive = true + + dimButton.isHidden = false + dimButton.alpha = 1.0 + + dimButtonTimer?.invalidate() + } + } + func speedChangerMenu() -> UIMenu { let speeds: [Double] = [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0] let playbackSpeedActions = speeds.map { speed in