fix: settings form alignment — grouped form, aligned labels #13
@@ -5,39 +5,79 @@ import ShotdeckCore
|
||||
struct SettingsView: View {
|
||||
@Environment(AppModel.self) private var model
|
||||
|
||||
private let labelWidth: CGFloat = 104
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Section("Hotkey") {
|
||||
LabeledContent("Capture", value: "⌥⇧2 — fixed in this version")
|
||||
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 10) {
|
||||
GridRow {
|
||||
Text("Hotkey")
|
||||
.font(.headline)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.gridCellColumns(2)
|
||||
}
|
||||
Section("Folders") {
|
||||
LabeledContent("Watch folder") {
|
||||
HStack(spacing: 8) {
|
||||
Text(model.watchFolderURL.path)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(.secondary)
|
||||
Button("Choose…") { model.chooseWatchFolder() }
|
||||
}
|
||||
}
|
||||
LabeledContent("Output folder") {
|
||||
HStack(spacing: 8) {
|
||||
Text(model.outboxURL.path)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(.secondary)
|
||||
Button("Choose…") { model.chooseOutboxFolder() }
|
||||
}
|
||||
|
||||
GridRow(alignment: .firstTextBaseline) {
|
||||
fieldLabel("Capture")
|
||||
Text("⌥⇧2 — fixed in this version")
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.frame(minHeight: 22, alignment: .leading)
|
||||
}
|
||||
|
||||
GridRow {
|
||||
Text("Folders")
|
||||
.font(.headline)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.gridCellColumns(2)
|
||||
.padding(.top, 6)
|
||||
}
|
||||
|
||||
GridRow(alignment: .center) {
|
||||
fieldLabel("Watch folder")
|
||||
folderValue(path: model.watchFolderURL.path) {
|
||||
model.chooseWatchFolder()
|
||||
}
|
||||
}
|
||||
Section {
|
||||
|
||||
GridRow(alignment: .center) {
|
||||
fieldLabel("Output folder")
|
||||
folderValue(path: model.outboxURL.path) {
|
||||
model.chooseOutboxFolder()
|
||||
}
|
||||
}
|
||||
|
||||
GridRow {
|
||||
Button("Reveal spool folder") { model.openSpoolFolder() }
|
||||
.gridCellColumns(2)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.frame(width: 360)
|
||||
.padding(16)
|
||||
.frame(minWidth: 320, idealWidth: 360, maxWidth: 360, alignment: .leading)
|
||||
.controlSize(.small)
|
||||
}
|
||||
|
||||
private func fieldLabel(_ title: String) -> some View {
|
||||
Text(title)
|
||||
.lineLimit(1)
|
||||
.frame(width: labelWidth, alignment: .trailing)
|
||||
.gridColumnAlignment(.trailing)
|
||||
.frame(minHeight: 22, alignment: .trailing)
|
||||
}
|
||||
|
||||
private func folderValue(path: String, choose: @escaping () -> Void) -> some View {
|
||||
HStack(spacing: 8) {
|
||||
Text(path)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.foregroundStyle(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Button("Choose…") { choose() }
|
||||
}
|
||||
.frame(minHeight: 22)
|
||||
}
|
||||
}
|
||||
|
||||
extension AppModel: SettingsWindowPresenting {
|
||||
|
||||
Reference in New Issue
Block a user