Files
gart/code/Hex-main/Hex/Features/Settings/MicrophoneSelectionSectionView.swift
T

88 lines
2.3 KiB
Swift
Executable File

import ComposableArchitecture
import Inject
import SwiftUI
struct MicrophoneSelectionSectionView: View {
private static let systemDefaultTag = "__system_default__"
@ObserveInjection var inject
@Bindable var store: StoreOf<SettingsFeature>
private var selectedDeviceTag: Binding<String> {
Binding(
get: { store.hexSettings.selectedMicrophoneID ?? Self.systemDefaultTag },
set: { newValue in
store.send(.setSelectedMicrophoneID(newValue == Self.systemDefaultTag ? nil : newValue))
}
)
}
private var missingSelectedDeviceID: String? {
guard let selectedID = store.hexSettings.selectedMicrophoneID,
!store.availableInputDevices.contains(where: { $0.id == selectedID })
else {
return nil
}
return selectedID
}
private var pickerIdentity: String {
[
store.defaultInputDeviceName ?? "",
store.hexSettings.selectedMicrophoneID ?? Self.systemDefaultTag,
store.availableInputDevices.map { "\($0.id):\($0.name)" }.joined(separator: "|")
].joined(separator: "||")
}
var body: some View {
Section {
// Input device picker
HStack {
Label {
let systemLabel: String = {
if let name = store.defaultInputDeviceName, !name.isEmpty {
return "System Default (\(name))"
}
return "System Default"
}()
Picker("Input Device", selection: selectedDeviceTag) {
Text(systemLabel).tag(Self.systemDefaultTag)
ForEach(store.availableInputDevices) { device in
Text(device.name).tag(device.id)
}
if let missingSelectedDeviceID {
Text("Unavailable Device").tag(missingSelectedDeviceID)
}
}
.pickerStyle(.menu)
.id(pickerIdentity)
} icon: {
Image(systemName: "mic.circle")
}
Button(action: {
store.send(.loadAvailableInputDevices)
}) {
Image(systemName: "arrow.clockwise")
}
.buttonStyle(.borderless)
.help("Refresh available input devices")
}
// Show fallback note for selected device not connected
if missingSelectedDeviceID != nil {
Text("Selected device not connected. System default will be used.")
.settingsCaption()
}
} header: {
Text("Microphone Selection")
} footer: {
Text("Override the system default microphone with a specific input device. This setting will persist across sessions.")
.font(.footnote)
.foregroundColor(.secondary)
}
.enableInjection()
}
}