Files

95 lines
3.4 KiB
Swift

import AppKit
import SstData
import SstUI
import SwiftUI
struct NoteView: View {
@EnvironmentObject private var model: AppModel
@ObservedObject var note: NoteStore
@State private var confirmingClear = false
private var editedEntry: HistoryEntry? {
model.editingEntryID.flatMap { model.historyList.entry(id: $0) }
}
/// The note, or the transcript being edited.
private var text: Binding<String> {
if let entry = editedEntry {
return Binding(
get: { model.historyList.entry(id: entry.id)?.finalText ?? "" },
set: { model.historyList.updateText(id: entry.id, to: $0) })
}
return $note.text
}
var body: some View {
VStack(spacing: Layout.panelGap) {
header
ZStack {
PaperBackground()
if SnapshotMode.isActive {
// ImageRenderer cannot draw an NSView; the snapshot shows the text instead.
Text(text.wrappedValue)
.textStyle(Typography.reading)
.foregroundStyle(Palette.inkPrimary)
.padding(Space.s5)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
} else {
NoteEditor(text: text, isEditable: editedEntry != nil || !note.isReadOnly)
.id(editedEntry?.id)
}
}
footer
}
.confirmationDialog(Strings.clearNoteConfirm, isPresented: $confirmingClear) {
Button(Strings.clear, role: .destructive) { note.text = "" }
}
.onChange(of: model.section) { _, new in
if new != .note { model.editingEntryID = nil }
}
}
private var header: some View {
HStack(spacing: Space.s4) {
if let entry = editedEntry {
SilkLabel("\(Strings.transcript) · \(entry.date.formatted(Date.FormatStyle().hour().minute().second().locale(Locale(identifier: "nl_NL"))))")
} else {
SilkLabel(Strings.note)
}
Spacer()
Text(Strings.characters(text.wrappedValue.count))
.textStyle(Typography.counterSmall)
.foregroundStyle(Palette.inkSecondary)
Button(Strings.copy) {
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(text.wrappedValue, forType: .string)
}
.buttonStyle(KeyButtonStyle())
.disabled(text.wrappedValue.isEmpty)
if editedEntry != nil {
Button(Strings.done) {
model.editingEntryID = nil
model.section = .transcripts
}
.buttonStyle(KeyButtonStyle(kind: .record))
} else {
Button(Strings.clear) { confirmingClear = true }
.buttonStyle(KeyButtonStyle())
.disabled(note.text.isEmpty)
}
}
}
private var footer: some View {
Text(footerText)
.textStyle(Typography.label)
.foregroundStyle(Palette.inkTertiary)
.frame(maxWidth: .infinity, alignment: .leading)
}
private var footerText: String {
if editedEntry != nil { return Strings.editingTranscriptHint }
return note.isReadOnly ? Strings.noteUnreadable : Strings.noteHint(model.hotkeyBinding.displayName)
}
}