~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

The iOS app is drawn in knotless's themes, the account's own included

Merged
Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:ios/themes

What changes

Themes on iOS. The app is drawn in the themes knotless's pages are. Settings, Appearance is now a screen of its own, each choice with a swatch of its colours: Same as knotless.dev (the default), which follows the account's appearancePref, day and night pairs included; Automatic, Light and Dark, iOS's own colours as before; the six themes the pages offer by name; and Your themes, those the account published (listThemes with actor) and those it added (themesPref), each added one saying who made it (listThemes with uris). A choice changes the whole app at once, with no screen rebuilt. The account's theme and its own are kept, so the app starts in them offline.

Colour tokens. Every iOS colour the screens took directly (systemBackground, secondarySystemGroupedBackground, separator, Color.primary, …) is now a token in Support/Palette.swift that stands for that same iOS colour where there's no theme, and for the theme's where there is. Lists and screens draw on the theme's page. The states' colours, the accent and code's highlighting follow the theme too. A palette that leaves colours out is filled in as tokens.css does.

Buttons as on the pages. In a theme the main button (Merge pull, Review, a review's send) is the theme's primary under its onPrimary; a state's pill and an icon square its colour under onSolid; and a button beside the main one (Add to merge queue, Leave the queue, Unblock) sits on the theme's surface. In iOS's own colours they're as they were, but for Merge pull in dark mode, now the darker green under white that light mode has, as white on dark mode's green read poorly.

ios-look. --theme dracula (or latte/mocha for a pair) draws a screen in a theme, appearance is a new screen, and each run starts as a new install, so what the simulator was left in doesn't show. look-answers.json records two themes of alice's for it.

Why

The pages have themes, and anyone can make and share one; the app was the one place they didn't reach. A theme's colours are named for what they colour, so they map onto the app's surfaces, texts and states as they do the pages', and the pairs the pages' contrast check holds a theme to (on-primary on primary, on-solid on the states') are the ones the app draws, so a theme that passes there reads here. Choosing on the phone stays on the phone, an override of the default rather than a change to the account's pages.

How it was checked

Every ios-look screen, scrolled to its end, in iOS's light and dark, Dracula and Latte, each looked at: the default as before, the themes whole. Picking a theme in Settings and one of the account's own (Ember, recorded) changes the app at once. ios/check-models.sh compiles the models with only Foundation and reads all the recorded answers; its write check, and the rest, are left to CI.

Shortcomings

Sheets (new issue, review, report) weren't looked at in a theme, as ios-look doesn't open them, and neither were pckt, plyr and Blacksky. A pair whose halves are both dark has iOS's light chrome by day. Themes are made and edited on the pages only.

Review

A look at the pictures, then Support/Palette.swift (the tokens and how a change of theme reaches them) and Views/AppearanceView.swift. Most of the rest is a colour swapped for its token, or a list's rows given the theme's background.

🤖 Generated with Claude Code

pull-in-dracula.png

pull-in-latte.png

appearance-in-ember.png

secondary-buttons-before-after.png

Approved

This pull draws the iOS app in knotless's themes. It adds colour tokens in Palette.swift, a themed Appearance screen, and a cached copy of the account's theme and own themes. I read the models, client, app entry, Palette.swift, AppearanceView.swift and Theme.swift closely. The remaining view files are mostly token swaps, and I did not read them.

The design holds up. The old automatic, light and dark raw values still mean the same thing, so existing choices carry over. A theme the account no longer has falls back to iOS's colours.

  • Merge conflict: the head conflicts with main in Support/Markdown.swift and Views/RepoView.swift, so every check failed without running. Merge main into the branch and run them again. The checks enforce this, so I'm not holding the approval for it.
  • Fragile theme load: one note on AccountTheme.load, in the line comment below. It is a robustness issue rather than a blocker.
ios/Knotless/Views/AppearanceView.swiftline 122
for i in added.indices { added[i].maker = found.themes.first { $0.uri == added[i].uri }?.creator?.handle }
}
let all = (mine + added).sorted { ($0.at ?? "") > ($1.at ?? "") }
hold(answer.appearance, themes: all)
review.knotless.dev

If the listThemes call with actor fails (made is nil) while getPreferences succeeds, mine is empty and hold overwrites the cached list with only the added themes. The account's published themes then disappear from the picker. If one of them was selected, the app falls back to iOS's colours, and that is saved too, so it stays that way offline. When either themes query fails, keep the previous themes rather than replacing them.

Approved

The only change since my approval is the merge of main, which resolved the two conflicts in Support/Markdown.swift and Views/RepoView.swift. I read the pull's diff for both files. Each side's change is kept: main's PagedList and ItemsView bodies are now wrapped in a Group with .listRowBackground(Color.page), and the remaining colours use the tokens. I found nothing wrong. The pull now merges cleanly.

My earlier note on AccountTheme.load still applies. If the listThemes call with actor fails while getPreferences succeeds, hold overwrites the cached themes with only the added ones. It is not a blocker.

Merged as b22c4d0