diff --git a/Sources/HeardCore/MeetingNoteComposer.swift b/Sources/HeardCore/MeetingNoteComposer.swift index f36dfa8..720bba8 100644 --- a/Sources/HeardCore/MeetingNoteComposer.swift +++ b/Sources/HeardCore/MeetingNoteComposer.swift @@ -3,7 +3,7 @@ import SwiftUI /// Floating composer for in-meeting notes. Hotkey opens the panel; the panel /// becomes key immediately so the first keystroke goes into the field. Esc -/// cancels, Cmd+Return submits. +/// cancels, Return submits, Cmd+Return inserts a newline. @MainActor public final class MeetingNoteComposer { public static let shared = MeetingNoteComposer() @@ -159,16 +159,28 @@ private struct MeetingNoteComposerView: View { RoundedRectangle(cornerRadius: 6) .stroke(Color.secondary.opacity(0.3)) ) + .onKeyPress(.return) { press in + if press.modifiers.contains(.command) { + if let tv = NSApp.keyWindow?.firstResponder as? NSTextView { + tv.insertNewline(nil) + } + return .handled + } + guard !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + return .handled + } + onSubmit(text) + return .handled + } HStack(spacing: 8) { - Text("⌘↩ to save, Esc to cancel") + Text("↩ to save · ⌘↩ new line · Esc to cancel") .font(.caption) .foregroundStyle(.tertiary) Spacer() Button("Cancel") { onCancel() } .keyboardShortcut(.cancelAction) Button("Save Note") { onSubmit(text) } - .keyboardShortcut(.return, modifiers: [.command]) .buttonStyle(.borderedProminent) .disabled(text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) } diff --git a/handoff.md b/handoff.md index 0d0b3ef..c0a93e7 100644 --- a/handoff.md +++ b/handoff.md @@ -60,7 +60,7 @@ The app builds cleanly with `swift build` and runs as a menu bar app on macOS 15 ### In-Meeting Notes - During an active recording, the user can press a global hotkey (default Ctrl+Shift+N, configurable in Settings → General → Meeting Notes) to open a small floating composer panel. -- Composer is an `NSPanel` subclass overriding `canBecomeKey` so the text editor takes focus immediately; first keystroke goes into the field. Esc cancels, Cmd+Return saves. +- Composer is an `NSPanel` subclass overriding `canBecomeKey` so the text editor takes focus immediately; first keystroke goes into the field. Esc cancels, Return saves, Cmd+Return inserts a newline. - The note's recording-relative timestamp is captured at panel-open time (not submit time), so a slow typer's note still anchors to when they reacted. - Notes are stored on `RecordingSession.notes` while the meeting is in progress; carried into the `PipelineJob` when recording stops; persisted in `pipeline_queue.json` (with backwards-compat decoding for pre-feature queue files). - If the user submits *after* the meeting has ended, `PipelineProcessor.attachNoteToFinishedJob(at:text:)` finds the matching enqueued/processing job by wall-clock time and attaches there instead.