Skip to content

Commit

Permalink
Merge pull request #1250 from TortugaPower/more-controls
Browse files Browse the repository at this point in the history
Add new setting to toggle seek on progress bar on lock screen
  • Loading branch information
GianniCarlo authored Feb 6, 2025
2 parents bb12f0f + 021cc25 commit f2a804b
Show file tree
Hide file tree
Showing 38 changed files with 280 additions and 46 deletions.
7 changes: 6 additions & 1 deletion BookPlayer/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, BPLogger {
return .success
}

center.changePlaybackPositionCommand.isEnabled = true
setupChangePlaybackPositionCommand()
}

func setupChangePlaybackPositionCommand() {
let center = MPRemoteCommandCenter.shared()
center.changePlaybackPositionCommand.isEnabled = UserDefaults.standard.bool(forKey: Constants.UserDefaults.seekProgressBarEnabled)
center.changePlaybackPositionCommand.addTarget { [weak self] remoteEvent in
guard
let playerManager = self?.coreServices?.playerManager,
Expand Down
2 changes: 2 additions & 0 deletions BookPlayer/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,5 @@ We're working hard on providing a seamless experience, if possible, please conta
"runtime_unknown" = "Unknown duration";
"subscription_required_title" = "Subscription required";
"Swipe rows to see download options" = "Swipe rows to see download options";
"settings_seekprogressbar_title" = "Progress Bar Seeking";
"settings_seekprogressbar_description" = "Enable seeking on the lock screen";
11 changes: 11 additions & 0 deletions BookPlayer/Coordinators/PlayerControlsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,21 @@ class PlayerControlsCoordinator: Coordinator {
switch routes {
case .dismiss:
self.flow.finishPresentation(animated: true)
case .more:
self.showMoreControls()
}
}
let vc = PlayerControlsViewController.instantiate(from: .Player)
vc.viewModel = viewModel
flow.startPresentation(vc, animated: true)
}

func showMoreControls() {
let vc = PlayerSettingsViewController.instantiate(from: .Settings)
vc.navigationItem.largeTitleDisplayMode = .never
let nav = AppNavigationController.instantiate(from: .Main)
nav.viewControllers = [vc]

flow.navigationController.present(nav, animated: true)
}
}
51 changes: 30 additions & 21 deletions BookPlayer/Player/Base.lproj/Player.storyboard

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class PlayerControlsViewController: UIViewController, Storyboarded {
@IBOutlet weak var boostLabel: UILabel!
@IBOutlet weak var boostWarningLabel: UILabel!
@IBOutlet weak var boostSwitchControl: UISwitch!
@IBOutlet weak var moreButton: UIButton!

private var boostVolumeObserver: NSKeyValueObservation?

private var disposeBag = Set<AnyCancellable>()

Expand All @@ -49,6 +52,7 @@ class PlayerControlsViewController: UIViewController, Storyboarded {
self.playbackLabel.text = "player_speed_title".localized
self.boostLabel.text = "settings_boostvolume_title".localized
self.boostWarningLabel.text = "settings_boostvolume_description".localized
self.moreButton.setTitle("more_title".localized, for: .normal)

self.speedFirstQuickActionButton.layer.masksToBounds = true
self.speedFirstQuickActionButton.layer.cornerRadius = 5
Expand Down Expand Up @@ -91,14 +95,20 @@ class PlayerControlsViewController: UIViewController, Storyboarded {

func setupAccessibility() {
self.boostLabel.accessibilityHint = "settings_boostvolume_description".localized
self.decrementSpeedButton.accessibilityLabel = ""
self.currentSpeedSlider.accessibilityValue = "\(self.viewModel.getCurrentSpeed())"
self.incrementSpeedButton.accessibilityLabel = ""
self.boostWarningLabel.isAccessibilityElement = false
self.currentSpeedLabel.isAccessibilityElement = false

self.mainContainterStackView.accessibilityElements = [
self.playbackLabel!,
self.decrementSpeedButton!,
self.currentSpeedSlider!,
self.incrementSpeedButton!,
self.boostLabel!,
self.boostSwitchControl!
self.boostSwitchControl!,
self.moreButton!
]
}

Expand All @@ -110,6 +120,14 @@ class PlayerControlsViewController: UIViewController, Storyboarded {
self?.viewModel.handleBoostVolumeToggle(flag: switchControl.isOn)
}
.store(in: &disposeBag)

boostVolumeObserver = UserDefaults.standard.observe(
\.userSettingsBoostVolume,
options: [.new]
) { [weak self] _, change in
guard let newValue = change.newValue else { return }
self?.boostSwitchControl.setOn(newValue, animated: false)
}
}

func bindSpeedObservers() {
Expand Down Expand Up @@ -168,13 +186,18 @@ class PlayerControlsViewController: UIViewController, Storyboarded {
}

private func setSliderSpeed(_ value: Float) {
self.currentSpeedSlider.accessibilityValue = "\(value)"
self.currentSpeedSlider.value = value
self.viewModel.handleSpeedChange(newValue: value)
}

@IBAction func done(_ sender: UIBarButtonItem?) {
self.viewModel.dismiss()
}

@IBAction func handleMoreAction(_ sender: UIButton) {
viewModel.showMoreControls()
}
}

extension PlayerControlsViewController: Themeable {
Expand Down Expand Up @@ -203,6 +226,8 @@ extension PlayerControlsViewController: Themeable {
self.incrementSpeedButton.tintColor = theme.linkColor
}

self.moreButton.tintColor = theme.linkColor

self.overrideUserInterfaceStyle = theme.useDarkVariant
? UIUserInterfaceStyle.dark
: UIUserInterfaceStyle.light
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Foundation

class PlayerControlsViewModel {
enum Routes {
case more
case dismiss
}

Expand Down Expand Up @@ -65,4 +66,8 @@ class PlayerControlsViewModel {
func dismiss() {
onTransition?(.dismiss)
}

func showMoreControls() {
onTransition?(.more)
}
}
17 changes: 17 additions & 0 deletions BookPlayer/Player/Player Screen/PlayerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class PlayerViewController: UIViewController, MVVMControllerProtocol, Storyboard
private var disposeBag = Set<AnyCancellable>()
private var playingProgressSubscriber: AnyCancellable?
private var currentChapterSubscriber: AnyCancellable?
private var updateProgressObserver: NSKeyValueObservation?

/// Reference to displayed alert, to update the message label with the ongoing timer
weak var sleepTimerAlert: UIAlertController?
Expand Down Expand Up @@ -279,6 +280,22 @@ extension PlayerViewController {
self.updateView(with: progressObject)
}.store(in: &disposeBag)

updateProgressObserver = UserDefaults.standard.observe(
\.userSettingsUpdateProgress,
options: [.new]
) { [weak self] object, change in
guard
let self,
let newValue = change.newValue,
newValue == true
else { return }
self.viewModel.reloadSharedFlags()
let progressObject = self.viewModel.getCurrentProgressState()
self.updateView(with: progressObject)

object.set(false, forKey: Constants.UserDefaults.updateProgress)
}

self.progressButton.publisher(for: .touchUpInside)
.merge(with: self.chapterTitleButton.publisher(for: .touchUpInside))
.sink { [weak self] _ in
Expand Down
7 changes: 7 additions & 0 deletions BookPlayer/Player/Player Screen/PlayerViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,13 @@ class PlayerViewModel: ViewModelProtocol {
)
}

func reloadSharedFlags() {
/// Flags are not a getter to avoid reading too often from defaults, as progress objects can be
/// triggered multiple times in a second
self.prefersChapterContext = sharedDefaults.bool(forKey: Constants.UserDefaults.chapterContextEnabled)
self.prefersRemainingTime = sharedDefaults.bool(forKey: Constants.UserDefaults.remainingTimeEnabled)
}

func processToggleMaxTime() -> ProgressObject {
self.prefersRemainingTime = !self.prefersRemainingTime
sharedDefaults.set(self.prefersRemainingTime, forKey: Constants.UserDefaults.remainingTimeEnabled)
Expand Down
30 changes: 30 additions & 0 deletions BookPlayer/Player/Player Screen/Views/PlayerJumpIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ extension PlayerJumpIcon: Themeable {
}

class PlayerJumpIconForward: PlayerJumpIcon {
private var intervalObserver: NSKeyValueObservation?

override var backgroundImage: UIImage {
get {
return #imageLiteral(resourceName: "playerIconForward")
Expand All @@ -110,10 +112,25 @@ class PlayerJumpIconForward: PlayerJumpIcon {

self.title = "+\(Int(PlayerManager.forwardInterval.rounded())) "
self.actionButton.accessibilityLabel = VoiceOverService.fastForwardText()

self.bindObserver()
}

func bindObserver() {
intervalObserver = UserDefaults.standard.observe(
\.userSettingsForwardInterval,
options: [.new]
) { [weak self] _, change in
guard let newValue = change.newValue else { return }
self?.title = "+\(Int(newValue.rounded())) "
self?.actionButton.accessibilityLabel = VoiceOverService.fastForwardText()
}
}
}

class PlayerJumpIconRewind: PlayerJumpIcon {
private var intervalObserver: NSKeyValueObservation?

override var backgroundImage: UIImage {
get {
return #imageLiteral(resourceName: "playerIconRewind")
Expand All @@ -128,5 +145,18 @@ class PlayerJumpIconRewind: PlayerJumpIcon {

self.title = "\(Int(PlayerManager.rewindInterval.rounded())) "
self.actionButton.accessibilityLabel = VoiceOverService.rewindText()

self.bindObserver()
}

func bindObserver() {
intervalObserver = UserDefaults.standard.observe(
\.userSettingsRewindInterval,
options: [.new]
) { [weak self] _, change in
guard let newValue = change.newValue else { return }
self?.title = "-\(Int(newValue.rounded())) "
self?.actionButton.accessibilityLabel = VoiceOverService.rewindText()
}
}
}
Loading

0 comments on commit f2a804b

Please sign in to comment.