Files
yattee/Shared/Views/OpenVideosView.swift
Arkadiusz Fal 9177abb0ec Fix iOS menu text disappearing in navigation headers
Extended the ZStack overlay fix to all iOS navigation header menus
where text labels would disappear when tapping the menu:

- HomeView: "Home" title menu
- PopularView: "Popular" title with icon menu
- TrendingView: Country/flag title menu
- PlaylistsView: Playlist title with thumbnail menu
- ChannelPlaylistView: Playlist title with thumbnail menu
- OpenVideosView: Playback mode picker menu

All menus now use the same pattern as PlaybackSettings:
- Visible static label layer in ZStack
- Invisible Menu overlay with .opacity(0)
- Prevents text disappearing and resizing animations
2025-11-23 14:16:21 +01:00

225 lines
6.6 KiB
Swift

import SwiftUI
struct OpenVideosView: View {
@State private var presentingFileImporter = false
@State private var urlsToOpenText = ""
@State private var playbackMode = OpenVideosModel.PlaybackMode.playNow
@State private var removeQueueItems = false
@ObservedObject private var navigation = NavigationModel.shared
@Environment(\.openURL) private var openURL
@Environment(\.presentationMode) private var presentationMode
var body: some View {
#if os(macOS)
openVideos
.frame(minWidth: 600, maxWidth: 800, minHeight: 350, maxHeight: 500)
#else
NavigationView {
ScrollView(.vertical, showsIndicators: false) {
openVideos
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
closeButton
}
}
.navigationTitle("Open Videos")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
#endif
}
var closeButton: some View {
Button(action: { presentationMode.wrappedValue.dismiss() }) {
Label("Done", systemImage: "xmark")
}
#if os(macOS)
.labelStyle(.titleOnly)
#endif
#if !os(tvOS)
.keyboardShortcut(.cancelAction)
#endif
}
var openVideos: some View {
VStack(alignment: .leading) {
#if os(macOS)
closeButton
#endif
ZStack(alignment: .topLeading) {
#if os(tvOS)
TextField("URL to Open", text: $urlsToOpenText)
#else
TextEditor(text: $urlsToOpenText)
.padding(2)
.border(Color(white: 0.8), width: 1)
.frame(minHeight: 100, maxHeight: 250)
#if !os(macOS)
.keyboardType(.URL)
#endif
#endif
}
Group {
#if os(tvOS)
Text("Enter link to open")
#else
Text("Enter links to open, one per line")
#endif
}
.font(.caption2)
.foregroundColor(.secondary)
playbackModeControl
Toggle(isOn: $removeQueueItems) {
Text("Clear Queue before opening")
}
.disabled(!playbackMode.allowsRemovingQueueItems)
.padding(.bottom)
HStack {
Group {
#if os(tvOS)
Spacer()
#endif
openURLsButton
Spacer()
#if !os(tvOS)
openFromClipboardButton
#endif
}
}
.padding(.bottom, 10)
#if !os(tvOS)
openFilesButton
#endif
Spacer()
}
.padding()
.alert(isPresented: $navigation.presentingAlertInOpenVideos) { navigation.alert }
#if !os(tvOS)
.fileImporter(
isPresented: $presentingFileImporter,
allowedContentTypes: [.audiovisualContent],
allowsMultipleSelection: true
) { result in
do {
let selectedFiles = try result.get()
let urlsToOpen = selectedFiles.map { url in
if let bookmarkURL = URLBookmarkModel.shared.loadBookmark(url) {
return bookmarkURL
}
if url.startAccessingSecurityScopedResource() {
URLBookmarkModel.shared.saveBookmark(url)
}
return url
}
openURLs(urlsToOpen)
} catch {
navigation.alert = Alert(title: Text("Could not open Files"))
navigation.presentingAlertInOpenVideos = true
}
presentationMode.wrappedValue.dismiss()
}
#endif
}
var playbackModeControl: some View {
HStack {
#if !os(tvOS)
Text("Playback Mode")
Spacer()
#endif
#if os(iOS)
ZStack {
Text(playbackMode.description)
Menu {
playbackModePicker
} label: {
Text(playbackMode.description)
.opacity(0)
}
}
#else
playbackModePicker
#if !os(tvOS)
.frame(maxWidth: 200)
#endif
#endif
}
.transaction { t in t.animation = .none }
.padding(.bottom, 5)
.frame(maxWidth: .infinity, alignment: .center)
}
var playbackModePicker: some View {
Picker("Playback Mode", selection: $playbackMode) {
ForEach(OpenVideosModel.PlaybackMode.allCases, id: \.rawValue) { mode in
Text(mode.description).tag(mode)
}
}
.labelsHidden()
}
var openURLsButton: some View {
AccentButton(text: "Open", imageSystemName: "network") {
openURLs(urlsToOpenFromText)
}
.disabled(urlsToOpenFromText.isEmpty)
#if os(tvOS)
.frame(maxWidth: 600)
#else
.keyboardShortcut(.defaultAction)
#endif
}
var openFromClipboardButton: some View {
AccentButton(text: "Paste", imageSystemName: "doc.on.clipboard.fill") {
OpenVideosModel.shared.openURLsFromClipboard(
removeQueueItems: removeQueueItems,
playbackMode: playbackMode
)
}
}
var openFilesButton: some View {
AccentButton(text: "Open Files", imageSystemName: "folder") {
presentingFileImporter = true
}
}
var urlsToOpenFromText: [URL] {
OpenVideosModel.shared.urlsFrom(urlsToOpenText)
}
func openURLs(_ urls: [URL]) {
OpenVideosModel.shared.openURLs(urls, removeQueueItems: removeQueueItems, playbackMode: playbackMode)
presentationMode.wrappedValue.dismiss()
}
}
struct OpenVideosView_Previews: PreviewProvider {
static var previews: some View {
OpenVideosView()
.injectFixtureEnvironmentObjects()
#if os(iOS)
.navigationViewStyle(.stack)
#endif
}
}