Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support actions for the standard settings menu #1160

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Sources/Player/Types/SettingsUpdate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

import AVFoundation

/// A settings update.
public enum SettingsUpdate {
/// Playback speed.
case playbackSpeed(Float)

/// Media selection.
case mediaSelection(characteristic: AVMediaCharacteristic, option: MediaSelectionOption)
}
29 changes: 23 additions & 6 deletions Sources/Player/UserInterface/SettingsMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ private struct MediaSelectionMenuContent: View {
@available(iOS 16.0, tvOS 17.0, *)
private struct SettingsMenuContent: View {
let player: Player
let speeds: Set<Float>
let action: (SettingsUpdate) -> Void

var body: some View {
playbackSpeedMenu()
Expand All @@ -93,7 +95,9 @@ private struct SettingsMenuContent: View {

private func playbackSpeedMenu() -> some View {
Menu {
player.playbackSpeedMenu()
player.playbackSpeedMenu(speeds: speeds) { speed in
action(.playbackSpeed(speed))
}
} label: {
Label {
Text("Playback Speed", bundle: .module, comment: "Playback setting menu title")
Expand All @@ -105,7 +109,7 @@ private struct SettingsMenuContent: View {

private func audibleMediaSelectionMenu() -> some View {
Menu {
player.mediaSelectionMenu(characteristic: .audible)
mediaSelectionMenuContent(characteristic: .audible)
} label: {
Label {
Text("Languages", bundle: .module, comment: "Playback setting menu title")
Expand All @@ -117,7 +121,7 @@ private struct SettingsMenuContent: View {

private func legibleMediaSelectionMenu() -> some View {
Menu {
player.mediaSelectionMenu(characteristic: .legible)
mediaSelectionMenuContent(characteristic: .legible)
} label: {
Label {
Text("Subtitles", bundle: .module, comment: "Playback setting menu title")
Expand All @@ -126,23 +130,36 @@ private struct SettingsMenuContent: View {
}
}
}

private func mediaSelectionMenuContent(characteristic: AVMediaCharacteristic) -> some View {
player.mediaSelectionMenu(characteristic: characteristic) { option in
action(.mediaSelection(characteristic: characteristic, option: option))
}
}
}

@available(iOS 16.0, tvOS 17.0, *)
public extension Player {
/// Returns content for a standard player settings menu.
///
/// - Parameters:
/// - speeds: The offered playback speeds.
/// - action: The action to perform when the user interacts with an item from the menu.
///
/// The returned view is meant to be used as content of a `Menu`. Using it for any other purpose has undefined
/// behavior.
///
func standardSettingsMenu() -> some View {
SettingsMenuContent(player: self)
func standardSettingsMenu(
speeds: Set<Float> = [0.5, 1, 1.25, 1.5, 2],
action: @escaping (_ update: SettingsUpdate) -> Void = { _ in }
) -> some View {
SettingsMenuContent(player: self, speeds: speeds, action: action)
}

/// Returns content for a playback speed menu.
///
/// - Parameters:
/// - speeds: The offered speeds.
/// - speeds: The offered playback speeds.
/// - action: The action to perform when the user interacts with an item from the menu.
///
/// The returned view is meant to be used as content of a `Menu`. Using it for any other purpose has undefined
Expand Down