115 lines
3.4 KiB
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()
|
|
}
|
|
}
|