You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Musubi/App/Sources/ContentView.swift

123 lines
4.2 KiB

import DesignSystem
import MusubiCore
import SwiftUI
struct ContentView: View {
let sourceList: SourceListModel
let coordinator: Coordinator
@AppStorage("detailTab") private var tab = DetailTab.screens
enum DetailTab: String { case screens, sound }
var body: some View {
NavigationSplitView {
SourceListView(sourceList: sourceList, audio: coordinator.audio)
.navigationSplitViewColumnWidth(min: 220, ideal: 260)
} detail: {
switch tab {
case .screens: ScreensView(coordinator: coordinator)
case .sound: SoundView(audio: coordinator.audio, sourceList: sourceList)
}
}
.navigationTitle("Musubi")
.navigationSubtitle("NDI rein. Bild, Ton und Stimme raus.")
.toolbar {
ToolbarItem(placement: .navigation) {
if coordinator.settings.role == .control {
SceneMenu(coordinator: coordinator)
} else {
Text("Knoten").font(Theme.Font.caption).foregroundStyle(Theme.Color.nezumi)
}
}
ToolbarItem(placement: .principal) {
Picker("Ansicht", selection: $tab) {
Text("Bildschirme").tag(DetailTab.screens)
Text("Ton").tag(DetailTab.sound)
}
.pickerStyle(.segmented)
.fixedSize()
}
if coordinator.outputs.isSleepBlocked {
ToolbarItem(placement: .primaryAction) {
Text("Ruhezustand blockiert")
.font(Theme.Font.caption)
.foregroundStyle(Theme.Color.nezumi)
}
}
}
}
}
private struct SourceListView: View {
let sourceList: SourceListModel
let audio: AudioController
var body: some View {
List {
Section("NDI") {
switch sourceList.state {
case .unavailable:
HintRow(text: "NDI lässt sich nicht starten. Prüfe die Installation des NDI SDK.")
case .idle, .searching:
if sourceList.sources.isEmpty {
HintRow(text: "Keine NDI-Quellen gefunden. Prüfe, ob das Technik-Netz an en7 hängt.")
} else {
ForEach(sourceList.sources, id: \.ndiName) { source in
SourceRow(source: source)
.draggable(source.ndiName)
}
}
}
}
Section("Mikrofone") {
ForEach(audio.matrix.inputDevices) { device in
Label {
Text(verbatim: device.name)
.font(Theme.Font.body)
.foregroundStyle(Theme.Color.washi)
} icon: {
Image(systemName: "mic").foregroundStyle(Theme.Color.nezumi)
}
.draggable("input:\(device.uid)")
}
}
}
.scrollContentBackground(.hidden)
.background(Theme.Color.kasumi)
.safeAreaInset(edge: .top, spacing: 0) {
Text("Quellen")
.font(Theme.Font.title)
.foregroundStyle(Theme.Color.washi)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(Theme.Space.card)
}
}
}
private struct HintRow: View {
let text: LocalizedStringKey
var body: some View {
Text(text)
.font(Theme.Font.caption)
.foregroundStyle(Theme.Color.nezumi)
.fixedSize(horizontal: false, vertical: true)
}
}
private struct SourceRow: View {
let source: Source
var body: some View {
VStack(alignment: .leading, spacing: Theme.Space.unit / 2) {
Text(verbatim: source.label)
.font(Theme.Font.body)
.foregroundStyle(Theme.Color.washi)
Text(verbatim: source.ndiName)
.font(Theme.Font.caption.monospaced())
.foregroundStyle(Theme.Color.nezumi)
}
.padding(.vertical, Theme.Space.unit / 2)
}
}

Powered by TurnKey Linux.