MiniPlayer/Sources/ContentView.swift

115 lines
3.4 KiB
Swift

import SwiftUI
struct ContentView: View {
@EnvironmentObject var engine: PlayerEngine
@State private var columnVisibility: NavigationSplitViewVisibility = .all
@State private var showURLInput = false
@State private var urlInput = ""
var body: some View {
Group {
if engine.isFullscreen {
PlayerView()
.onTapGesture(count: 2) {
engine.toggleFullscreen()
}
} else {
NavigationSplitView(columnVisibility: $columnVisibility) {
playlistSidebar
} detail: {
PlayerView()
}
.navigationSplitViewStyle(.balanced)
.navigationSplitViewColumnWidth(min: 240, ideal: 300, max: 400)
}
}
.alert("添加流媒体 URL", isPresented: $showURLInput) {
TextField("M3U8 或其他流媒体 URL", text: $urlInput)
Button("添加") {
addStreamURL()
}
Button("取消", role: .cancel) {}
} message: {
Text("输入 M3U8、MP4 或其他流媒体地址")
}
.keyboardShortcut(.escape, action: {
if engine.isFullscreen { engine.toggleFullscreen() }
})
}
// MARK: -
private var playlistSidebar: some View {
VStack(spacing: 0) {
PlaylistView()
Divider()
// : URL +
HStack(spacing: 12) {
Button {
urlInput = ""
showURLInput = true
} label: {
Label("添加流 URL", systemImage: "link")
.font(.caption)
}
.buttonStyle(.bordered)
.controlSize(.small)
Spacer()
//
Button {
engine.repeatMode = engine.repeatMode.next
} label: {
HStack(spacing: 4) {
Image(systemName: engine.repeatMode.icon)
Text(repeatModeText)
}
.font(.caption)
.foregroundStyle(engine.repeatMode == .none ? .secondary : .blue)
}
.buttonStyle(.plain)
}
.padding(.horizontal, 16)
.padding(.vertical, 10)
}
}
private var repeatModeText: String {
switch engine.repeatMode {
case .none: return "不循环"
case .single: return "单曲"
case .all: return "列表"
}
}
private func addStreamURL() {
guard !urlInput.isEmpty, let url = URL(string: urlInput) else { return }
engine.addToQueue(urls: [url])
}
}
// ESC
extension View {
func keyboardShortcut(_ key: KeyEquivalent, action: @escaping () -> Void) -> some View {
self.background(
KeyboardShortcutView(key: key, action: action)
)
}
}
struct KeyboardShortcutView: View {
let key: KeyEquivalent
let action: () -> Void
var body: some View {
Button(action: action) {
EmptyView()
}
.keyboardShortcut(key, modifiers: [])
.hidden()
}
}