Add menu bar status item and popover#3
Closed
Newarr wants to merge 10 commits intofeature/headless-service-initfrom
Closed
Add menu bar status item and popover#3Newarr wants to merge 10 commits intofeature/headless-service-initfrom
Newarr wants to merge 10 commits intofeature/headless-service-initfrom
Conversation
c522a3a to
0a8df8c
Compare
c11552e to
07b634e
Compare
NSStatusItem with two icon states: waveform.circle (idle) and waveform.circle.fill (recording). Icon updates reactively via withObservationTracking (zero wakeups when idle). Popover shows live recording status with elapsed timer computed from actual session start time, Start/Stop button with consent gate, Show App, and Quit. Uses NSPopover with NSHostingController for reliable sizing and focus behavior.
07b634e to
7c582f4
Compare
Add acoustic echo cancellation via Apple Voice Processing. Enables setVoiceProcessingEnabled on AVAudioEngine mic input to cancel speaker echo that causes duplicate transcription. On by default with toggle in Settings > Recording. Closes yazinsai#88
Redesign NotesView: 2-tab model with batch cleanup Replaces the 3-state Raw/Refined/Notes detail view with a clean 2-tab segmented picker (Transcript / Notes). Adds batch transcript cleanup via TranscriptCleanupEngine for on-demand refinement of past sessions. Based on the design direction from @Newarr in PRs yazinsai#82 and yazinsai#83 — thank you for the original work! Reimplemented to keep drain() timeout at 5s and strip unrelated scope changes. Closes yazinsai#82, closes yazinsai#83.
Add structured Markdown meeting output (openoats/v1) Produces `.md` files in ~/Documents/OpenOats/ alongside existing `.txt` output. YAML frontmatter with date, duration, participants, ASR engine, and meeting app. Body sections: Summary, Action Items, Decisions, Transcript (high-signal first). Speaker-attributed transcript lines with relative timestamps. Three processing stages: raw transcript (always written at finalization), LLM-enriched sections inserted when notes are generated. Existing .txt output is preserved unchanged. Includes format specification, example transcript, and 42 unit tests. Closes no issues — new capability.
Derive isRecording from coordinator state machine Replace writable stored `_isRecording` property with a computed property that reads directly from the coordinator's authoritative `MeetingState`. Eliminates stale-value risk from the 100ms polling loop. Also adds `MeetingMetadata.manual()` static factory to deduplicate inline metadata construction across call sites.
Extract service initialization for headless operation Add ensureServicesInitialized() on AppRuntime with an idempotency guard. Coordinator-owned services (TranscriptionEngine, TranscriptLogger, RefinementEngine, AudioRecorder) are created on first call from wherever runs first. ContentView.task now only creates view-local services (KnowledgeBase, SuggestionEngine) that don't need to outlive the window.
Add clearModelCache() to TranscriptionBackend protocol so corrupt model files are removed on load failure. Each backend (Parakeet, Qwen3, WhisperKit) implements targeted cache deletion. TranscriptionEngine now clears cache and resets download state on failure, so "Download Now" triggers a fresh download.
Add horizontal wordmark logo (icon + text) for marketing and documentation use. Contributed by @Alex-Wengg.
…yazinsai#95) (yazinsai#103) Fix mic tap format failure and AEC conflict with system audio capture. Based on analysis from @brandonbloom in yazinsai#95.
Newarr
pushed a commit
that referenced
this pull request
Mar 22, 2026
- Make cancel() async and await task completion to prevent data races (#1) - Move session-switch guard before backfillRefinedText to prevent stale writes (#3) - Cancel cleanup engine in teardownMeetingDetection (#4) - Add .pre-llm.md backup before overwriting Markdown with LLM sections (yazinsai#10) - Add safety documentation for nonisolated(unsafe) vars (#2) - Add unit tests for chunkRecords and parseResponse (#5) https://claude.ai/code/session_01QTKjQDQpoVqFrPJM8bp218
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
OpenOats has no menu bar presence. When running as a background listener (upcoming LSUIElement mode), users need a way to see recording state, start/stop sessions, and access the main window without a dock icon.
Solution
Two new files implementing a menu bar status item via
NSStatusItem+NSPopover(not SwiftUIMenuBarExtra, which cannot reliably handle dynamic icons or survive activation policy changes).MenuBarController
Manages the
NSStatusItemwith two template image states:waveform.circlewaveform.circle.fillPolls
coordinator.isRecordingat 250ms to toggle the icon. Hosts the popover viaNSHostingController.MenuBarPopoverView
280pt-wide SwiftUI popover with 4 items:
.borderedProminent, red tint for stop. Drives coordinator directly (no ContentView dependency).Changed files
MenuBarController.swiftMenuBarPopoverView.swiftTest plan
PR 3 of 4 in the menu bar background mode series.
Depends on: #2 Extract service initialization
Next: #4 Enable background mode lifecycle