Improve tvOS controls overlay with single-press menus

Changed context menus from press-and-hold to single-press for better UX:
- Quality profile selection
- Stream quality selection
- Captions selection
- Audio track selection

Updated ControlsOverlayButton to support tap actions via new onSelect parameter.
Replaced .contextMenu modifiers with .alert for instant menu access on tvOS.
Removed hint text and unnecessary 80px padding as single-press is self-evident.
This commit is contained in:
Arkadiusz Fal
2025-11-22 23:39:55 +01:00
parent 1397a2fee6
commit 997de6468d
3 changed files with 72 additions and 44 deletions

View File

@@ -4,25 +4,52 @@ struct ControlsOverlayButton<LabelView: View>: View {
var focusedField: FocusState<ControlsOverlay.Field?>.Binding
var field: ControlsOverlay.Field
let label: LabelView
var onSelect: (() -> Void)?
init(
focusedField: FocusState<ControlsOverlay.Field?>.Binding,
field: ControlsOverlay.Field,
onSelect: (() -> Void)? = nil,
@ViewBuilder label: @escaping () -> LabelView
) {
self.focusedField = focusedField
self.field = field
self.onSelect = onSelect
self.label = label()
}
var body: some View {
label
.padding()
.frame(width: 400)
.focusable()
let isFocused = focusedField.wrappedValue == field
if let onSelect {
Button(action: onSelect) {
label
.padding()
.frame(width: 400)
}
.buttonStyle(TVButtonStyle(isFocused: isFocused))
.focused(focusedField, equals: field)
.background(focusedField.wrappedValue == field ? Color.white : Color.secondary)
.foregroundColor(focusedField.wrappedValue == field ? Color.black : Color.white)
.clipShape(RoundedRectangle(cornerRadius: 4))
} else {
label
.padding()
.frame(width: 400)
.focusable()
.focused(focusedField, equals: field)
.background(isFocused ? Color.white : Color.secondary)
.foregroundColor(isFocused ? Color.black : Color.white)
.clipShape(RoundedRectangle(cornerRadius: 4))
}
}
}
struct TVButtonStyle: ButtonStyle {
let isFocused: Bool
func makeBody(configuration: Configuration) -> some View {
configuration.label
.background(isFocused ? Color.white : Color.secondary)
.foregroundColor(isFocused ? Color.black : Color.white)
.clipShape(RoundedRectangle(cornerRadius: 4))
.scaleEffect(configuration.isPressed ? 0.95 : 1.0)
}
}