mirror of
https://github.com/yattee/yattee.git
synced 2025-12-16 21:18:16 +00:00
Fix iOS playback settings menu text disappearing and resizing issues
When tapping menus in playback settings (playback mode, quality profile, stream, rate, captions, audio track), the selected value text would disappear and cause unwanted resizing animations. Implemented ZStack overlay technique for all iOS menu buttons: - Visible static label remains on screen - Invisible Menu overlay (.opacity(0)) handles tap interactions - Prevents text from disappearing when menu opens - Eliminates resizing animations on option selection
This commit is contained in:
@@ -209,16 +209,22 @@ struct PlaybackSettings: View {
|
|||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.frame(width: 100, alignment: .center)
|
.frame(width: 100, alignment: .center)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
Menu {
|
ZStack {
|
||||||
ratePicker
|
|
||||||
} label: {
|
|
||||||
Text(player.rateLabel(player.currentRate))
|
Text(player.rateLabel(player.currentRate))
|
||||||
.foregroundColor(.primary)
|
.foregroundColor(.primary)
|
||||||
.frame(width: 70)
|
.frame(width: 70)
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
ratePicker
|
||||||
|
} label: {
|
||||||
|
Text(player.rateLabel(player.currentRate))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
.frame(width: 70)
|
||||||
|
.opacity(0)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.transaction { t in t.animation = .none }
|
||||||
}
|
}
|
||||||
.transaction { t in t.animation = .none }
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.foregroundColor(.primary)
|
|
||||||
.frame(width: 70, height: 40)
|
.frame(width: 70, height: 40)
|
||||||
#else
|
#else
|
||||||
Text(player.rateLabel(player.currentRate))
|
Text(player.rateLabel(player.currentRate))
|
||||||
@@ -331,12 +337,20 @@ struct PlaybackSettings: View {
|
|||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.frame(width: 300, alignment: .trailing)
|
.frame(width: 300, alignment: .trailing)
|
||||||
#else
|
#else
|
||||||
Menu {
|
ZStack {
|
||||||
playbackModePicker
|
|
||||||
} label: {
|
|
||||||
Label(player.playbackMode.description.localized(), systemImage: player.playbackMode.systemImage)
|
Label(player.playbackMode.description.localized(), systemImage: player.playbackMode.systemImage)
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
playbackModePicker
|
||||||
|
} label: {
|
||||||
|
Label(player.playbackMode.description.localized(), systemImage: player.playbackMode.systemImage)
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
.opacity(0)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.transaction { t in t.animation = .none }
|
||||||
}
|
}
|
||||||
.transaction { t in t.animation = .none }
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,15 +370,22 @@ struct PlaybackSettings: View {
|
|||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.frame(width: 300, alignment: .trailing)
|
.frame(width: 300, alignment: .trailing)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
Menu {
|
ZStack {
|
||||||
qualityProfilePicker
|
|
||||||
} label: {
|
|
||||||
Text(player.qualityProfileSelection?.description ?? "Automatic".localized())
|
Text(player.qualityProfileSelection?.description ?? "Automatic".localized())
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
.frame(maxWidth: 240, alignment: .trailing)
|
.frame(maxWidth: 240, alignment: .trailing)
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
qualityProfilePicker
|
||||||
|
} label: {
|
||||||
|
Text(player.qualityProfileSelection?.description ?? "Automatic".localized())
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
.frame(maxWidth: 240, alignment: .trailing)
|
||||||
|
.opacity(0)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.transaction { t in t.animation = .none }
|
||||||
}
|
}
|
||||||
.transaction { t in t.animation = .none }
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
.frame(maxWidth: 240, alignment: .trailing)
|
.frame(maxWidth: 240, alignment: .trailing)
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
#else
|
#else
|
||||||
@@ -406,15 +427,22 @@ struct PlaybackSettings: View {
|
|||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.frame(width: 300, alignment: .trailing)
|
.frame(width: 300, alignment: .trailing)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
Menu {
|
ZStack {
|
||||||
StreamControl()
|
|
||||||
} label: {
|
|
||||||
Text(player.streamSelection?.resolutionAndFormat ?? "loading...")
|
Text(player.streamSelection?.resolutionAndFormat ?? "loading...")
|
||||||
.frame(width: 140, height: 40, alignment: .trailing)
|
|
||||||
.foregroundColor(player.streamSelection == nil ? .secondary : .accentColor)
|
.foregroundColor(player.streamSelection == nil ? .secondary : .accentColor)
|
||||||
|
.frame(width: 140, height: 40, alignment: .trailing)
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
StreamControl()
|
||||||
|
} label: {
|
||||||
|
Text(player.streamSelection?.resolutionAndFormat ?? "loading...")
|
||||||
|
.foregroundColor(player.streamSelection == nil ? .secondary : .accentColor)
|
||||||
|
.frame(width: 140, height: 40, alignment: .trailing)
|
||||||
|
.opacity(0)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.transaction { t in t.animation = .none }
|
||||||
}
|
}
|
||||||
.transaction { t in t.animation = .none }
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.frame(width: 140, height: 40, alignment: .trailing)
|
.frame(width: 140, height: 40, alignment: .trailing)
|
||||||
#else
|
#else
|
||||||
StreamControl(focusedField: $focusedField)
|
StreamControl(focusedField: $focusedField)
|
||||||
@@ -429,18 +457,13 @@ struct PlaybackSettings: View {
|
|||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.frame(width: 300, alignment: .trailing)
|
.frame(width: 300, alignment: .trailing)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
Menu {
|
ZStack {
|
||||||
if videoCaptions?.isEmpty == false {
|
|
||||||
captionsPicker
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Image(systemName: "text.bubble")
|
Image(systemName: "text.bubble")
|
||||||
if let captions = player.captions,
|
if let captions = player.captions,
|
||||||
let language = LanguageCodes(rawValue: captions.code)
|
let language = LanguageCodes(rawValue: captions.code)
|
||||||
{
|
{
|
||||||
Text("\(language.description.capitalized) (\(language.rawValue))")
|
Text("\(language.description.capitalized) (\(language.rawValue))")
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
} else {
|
} else {
|
||||||
if videoCaptions?.isEmpty == true {
|
if videoCaptions?.isEmpty == true {
|
||||||
Text("Not available")
|
Text("Not available")
|
||||||
@@ -449,13 +472,38 @@ struct PlaybackSettings: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
.frame(alignment: .trailing)
|
.frame(alignment: .trailing)
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
.disabled(videoCaptions?.isEmpty == true)
|
|
||||||
|
Menu {
|
||||||
|
if videoCaptions?.isEmpty == false {
|
||||||
|
captionsPicker
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Image(systemName: "text.bubble")
|
||||||
|
if let captions = player.captions,
|
||||||
|
let language = LanguageCodes(rawValue: captions.code)
|
||||||
|
{
|
||||||
|
Text("\(language.description.capitalized) (\(language.rawValue))")
|
||||||
|
} else {
|
||||||
|
if videoCaptions?.isEmpty == true {
|
||||||
|
Text("Not available")
|
||||||
|
} else {
|
||||||
|
Text("Disabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
.frame(alignment: .trailing)
|
||||||
|
.frame(height: 40)
|
||||||
|
.opacity(0)
|
||||||
|
.disabled(videoCaptions?.isEmpty == true)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.transaction { t in t.animation = .none }
|
||||||
}
|
}
|
||||||
.transaction { t in t.animation = .none }
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
#else
|
#else
|
||||||
ControlsOverlayButton(focusedField: $focusedField, field: .captions) {
|
ControlsOverlayButton(focusedField: $focusedField, field: .captions) {
|
||||||
HStack(spacing: 8) {
|
HStack(spacing: 8) {
|
||||||
@@ -500,15 +548,22 @@ struct PlaybackSettings: View {
|
|||||||
.controlSize(.large)
|
.controlSize(.large)
|
||||||
.frame(width: 300, alignment: .trailing)
|
.frame(width: 300, alignment: .trailing)
|
||||||
#elseif os(iOS)
|
#elseif os(iOS)
|
||||||
Menu {
|
ZStack {
|
||||||
audioTrackPicker
|
|
||||||
} label: {
|
|
||||||
Text(player.selectedAudioTrack?.displayLanguage ?? "Original")
|
Text(player.selectedAudioTrack?.displayLanguage ?? "Original")
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
.frame(maxWidth: 240, alignment: .trailing)
|
.frame(maxWidth: 240, alignment: .trailing)
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
audioTrackPicker
|
||||||
|
} label: {
|
||||||
|
Text(player.selectedAudioTrack?.displayLanguage ?? "Original")
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
.frame(maxWidth: 240, alignment: .trailing)
|
||||||
|
.opacity(0)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.transaction { t in t.animation = .none }
|
||||||
}
|
}
|
||||||
.transaction { t in t.animation = .none }
|
|
||||||
.buttonStyle(.plain)
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
.frame(maxWidth: 240, alignment: .trailing)
|
.frame(maxWidth: 240, alignment: .trailing)
|
||||||
.frame(height: 40)
|
.frame(height: 40)
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user