Make seek durations configurable in Playback menu and add secondary seek

Playback menu seek items now follow the durations from the active player
controls preset instead of hardcoded 10s/30s labels. AppEnvironment caches
the active preset's center settings (refreshed on preset change
notifications) so menu commands can read them synchronously.

Add secondary seek durations (default 30s) to CenterSectionSettings,
configurable on macOS in Seek Durations settings, used by Shift+arrows in
the player and Cmd+Shift+arrows in the Playback menu.

Also let Cmd-based key equivalents pass through the player keyboard
monitor so menu shortcuts (e.g. Cmd+Option+arrow previous/next video)
work while the player window has focus, and unify macOS built-in preset
primary seek at 10s to match iOS/tvOS (built-in presets version 8).
This commit is contained in:
Arkadiusz Fal
2026-06-19 08:50:39 +02:00
parent 5bc774dd83
commit ca67d480ca
7 changed files with 197 additions and 50 deletions

View File

@@ -11,7 +11,7 @@ extension LayoutPreset {
/// Bump this version whenever any built-in preset definition changes.
/// On launch, the app compares this against the last-applied version
/// and replaces stale built-in presets with fresh copies from code.
static let builtInPresetsVersion = 7
static let builtInPresetsVersion = 8
// MARK: - Built-in Preset IDs
@@ -164,13 +164,13 @@ extension LayoutPreset {
]
// On macOS center settings only drive seek amounts (keyboard arrows
// and default seek buttons); 5s preserves the historical arrow-key step.
// and default seek buttons).
let centerSettings = CenterSectionSettings(
showPlayPause: true,
showSeekBackward: true,
showSeekForward: true,
seekBackwardSeconds: 5,
seekForwardSeconds: 5,
seekBackwardSeconds: 10,
seekForwardSeconds: 10,
leftSlider: .disabled,
rightSlider: .disabled
)
@@ -308,8 +308,8 @@ extension LayoutPreset {
showPlayPause: true,
showSeekBackward: true,
showSeekForward: true,
seekBackwardSeconds: 5,
seekForwardSeconds: 5,
seekBackwardSeconds: 10,
seekForwardSeconds: 10,
leftSlider: .disabled,
rightSlider: .disabled
)

View File

@@ -25,6 +25,12 @@ struct CenterSectionSettings: Codable, Hashable, Sendable {
/// Number of seconds for the seek forward button.
var seekForwardSeconds: Int
/// Number of seconds for the secondary seek backward shortcut ( + seek).
var secondarySeekBackwardSeconds: Int
/// Number of seconds for the secondary seek forward shortcut ( + seek).
var secondarySeekForwardSeconds: Int
/// Type of slider to show on the left edge of the player (iOS only).
var leftSlider: SideSliderType
@@ -40,6 +46,8 @@ struct CenterSectionSettings: Codable, Hashable, Sendable {
/// - showSeekForward: Show seek forward button. Defaults to true.
/// - seekBackwardSeconds: Seconds to seek backward. Defaults to 10.
/// - seekForwardSeconds: Seconds to seek forward. Defaults to 10.
/// - secondarySeekBackwardSeconds: Seconds for the secondary () backward seek. Defaults to 30.
/// - secondarySeekForwardSeconds: Seconds for the secondary () forward seek. Defaults to 30.
/// - leftSlider: Type of slider on left edge. Defaults to disabled.
/// - rightSlider: Type of slider on right edge. Defaults to disabled.
init(
@@ -48,6 +56,8 @@ struct CenterSectionSettings: Codable, Hashable, Sendable {
showSeekForward: Bool = true,
seekBackwardSeconds: Int = 10,
seekForwardSeconds: Int = 10,
secondarySeekBackwardSeconds: Int = 30,
secondarySeekForwardSeconds: Int = 30,
leftSlider: SideSliderType = .disabled,
rightSlider: SideSliderType = .disabled
) {
@@ -56,6 +66,8 @@ struct CenterSectionSettings: Codable, Hashable, Sendable {
self.showSeekForward = showSeekForward
self.seekBackwardSeconds = max(1, seekBackwardSeconds)
self.seekForwardSeconds = max(1, seekForwardSeconds)
self.secondarySeekBackwardSeconds = max(1, secondarySeekBackwardSeconds)
self.secondarySeekForwardSeconds = max(1, secondarySeekForwardSeconds)
self.leftSlider = leftSlider
self.rightSlider = rightSlider
}
@@ -68,6 +80,8 @@ struct CenterSectionSettings: Codable, Hashable, Sendable {
case showSeekForward
case seekBackwardSeconds
case seekForwardSeconds
case secondarySeekBackwardSeconds
case secondarySeekForwardSeconds
case leftSlider
case rightSlider
}
@@ -80,6 +94,8 @@ struct CenterSectionSettings: Codable, Hashable, Sendable {
seekBackwardSeconds = try container.decode(Int.self, forKey: .seekBackwardSeconds)
seekForwardSeconds = try container.decode(Int.self, forKey: .seekForwardSeconds)
// New properties with defaults for backward compatibility
secondarySeekBackwardSeconds = try container.decodeIfPresent(Int.self, forKey: .secondarySeekBackwardSeconds) ?? 30
secondarySeekForwardSeconds = try container.decodeIfPresent(Int.self, forKey: .secondarySeekForwardSeconds) ?? 30
leftSlider = try container.decodeIfPresent(SideSliderType.self, forKey: .leftSlider) ?? .disabled
rightSlider = try container.decodeIfPresent(SideSliderType.self, forKey: .rightSlider) ?? .disabled
}