Skip to content

Lay the Settings window out as a source list - #17

Merged
TerrifiedBug merged 1 commit into
mainfrom
feat/settings-window-sidebar
Aug 31, 2026
Merged

Lay the Settings window out as a source list#17
TerrifiedBug merged 1 commit into
mainfrom
feat/settings-window-sidebar

Conversation

@TerrifiedBug

Copy link
Copy Markdown
Owner

Why

The Settings window shipped as one column you scroll. That is not a settings window, it is a config file with switches: everything at one visual weight, no way to jump, and the section people open it for — Meetings → Ignored apps — below the fold.

What

Split it the way macOS splits settings: a source list on the left, one short pane on the right.

  • Rail — Dictation / Recording / Meetings, each with a tinted SF Symbol chip, on the real .sidebar material. Red goes to Recording deliberately: it is the record light, the same thing it means everywhere else in yap. The rail doubles as the map — you can see everything yap can be told to do without touching anything.
  • Panes — each one fits on screen. No pane scrolls on open.
  • Header — every pane says what it is for in one line, so nobody has to infer it from the controls.
  • Ignored apps — the control macOS already has for an editable set: a bordered list with + / beneath it, the same one Login Items uses. Rows carry the app's real icon and its bundle id, because the id is what the config file actually stores. An app that has since been deleted keeps its place under its identifier with a drawn placeholder; the generic application icon read as a failed image load.
  • Bottom bar — names the file every control writes to. The whole point is that clicking here and editing the JSON are the same act, so the path is worth saying out loud rather than hiding behind a button.

No behaviour change: the same keys, the same immediate write-through, the same live reload. Open Config File moves from a section of its own into the bottom bar.

Split into three files along a real seam — window chrome, pane content, config-backed model — rather than one 600-line view. Each is now under the 400-line lint bar.

The one rule

No new dependencies; SwiftUI and NSVisualEffectView are system frameworks. Still nothing built until the menu item is first clicked, still nothing running while idle. No new processes, no new timers.

Verified

Local CI gate green (swift test, swift build -c release --arch arm64, the three smoke subcommands, embedded __info_plist), then driven live as a signed binary on an M4 across three inspection rounds. Each round fixed what it showed:

  • Round 1 — the rail, panes and bottom bar render; footer path reads ~/.config/yap/config.json.
  • Round 2 — fixed a not-installed row printing its bundle id twice (once as a stand-in name, once as the subtitle), which read as a debug dump; swapped the blank generic icon for a drawn placeholder; gave rows and the +/ bar room.
  • Round 3 — fixed a hairline drawn after the last row that read as content clipped off the bottom, and cut ~60 pt of dead space by sizing the window to the tallest pane rather than to a guess.

Confirmed at the end: Meetings shows header, both toggles, a three-row list and its +/ bar with nothing clipped and no scroll; Dictation and Recording likewise. Ignored-app add and remove still round-trip to meeting_excluded_apps, and the daemon still logs config reloaded on every change.

One column you scroll is not a settings window, it is a config file with
switches. Split it the way macOS splits settings: a source list on the
left, one short pane on the right. Three panes that each fit on screen
beat one that does not, and the rail doubles as the map — you can see
everything yap can be told to do without touching anything.

Ignored apps gets the control macOS already has for an editable set: a
bordered list with + and - under it, the same one login items use. Rows
carry the app's real icon and its bundle id, because the id is what the
config file actually stores. An app that has since been deleted keeps its
place under its identifier with a drawn placeholder rather than the
generic app icon, which read as a failed image load.

The window names the file it writes in a bottom bar. The whole point is
that clicking here and editing the JSON are the same act, so the path is
worth saying out loud rather than hiding behind the button.

Split into three files along a real seam — window chrome, pane content,
and the config-backed model — rather than one 600-line view.
@TerrifiedBug
TerrifiedBug merged commit 62c4831 into main Aug 31, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant