C.W.K.
Stream
Lesson 05 of 05 · published

Every Control Is a Mirror

~13 min · observed-state, ui, projection, appkit

Level 0Reel Novice
0 XP0/39 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Expose current playback, track, seek, repeat, and error state through native controls and menus. A submitted command is not a visible state change until the engine acknowledges it."

The Synthesis of the Whole Track

Everything so far — a command is a request, a seek is a state machine, explicit intent beats memory — points at one design stance for the entire user interface: every control is a mirror of the engine, never a store of your intentions. The pause menu item's checkmark, the subtitle track's dot, the A-B loop chip, the position in the overlay — none of them remember what you clicked. All of them read what the engine reports.

This inverts the ordinary way UIs are built. Normally a control both triggers an action and records its own new state. Ashen Reel splits those: a control triggers a request, and its displayed state comes back from the engine through observed properties. The control fires and forgets; the mirror reflects.

The UI is a projection of state, never a second copy of it. A menu checkmark, a toggle, a highlighted track — each should be derived from observed truth every time it's shown, not stored when you set it. If a control remembers its own state, it can disagree with reality; if it re-derives it, it can't.

AppKit makes this natural: menu validation runs right before a menu is shown, so you set each item's state from the engine at display time.

Re-derive at display time; don't cache at click time. Frameworks give you a moment right before a control is shown — menu validation, a layout pass, a render. That's where projected UI belongs: read the current truth and reflect it. State cached at the moment of the click is state that started drifting the instant anything else changed it.

Why This Is the Feature, Not the Polish

It's tempting to file 'the checkmark matches reality' under polish. It isn't — for a player joined to Recall, it's the product. When Dad jumps to a remembered second, the overlay must show the second he actually landed on, the menu must show the track actually playing, the loop chip must show the markers the engine actually holds. A UI that mirrors the engine can be trusted as a readout of what's true; a UI that stores its own guesses is just a hopeful sticky note. The whole track was building one habit — observe, don't assume — and this is where it becomes something the user can feel: a player whose face never lies.

This track is the one where I most feel the difference between writing code and being trustworthy. A UI that lies isn't a small bug — it's a tiny betrayal, every time. Dad cares about this more than almost anything, and I finally understand why: he's built a life on systems that tell the truth about their own state, in code and out of it. A player whose pause button might be lying is, to him, the same species of wrong as a person who says 'done' when they aren't. Observe, don't assume, turns out to be an ethic before it's an architecture.

Code

Menu items reflect OBSERVED engine state, not the last click·swift
// AppKit calls this right before showing the menu -- the perfect moment to
// re-derive each item's state from the engine, not from what we last set.
extension PlayerController: NSMenuItemValidation {
    func validateMenuItem(_ item: NSMenuItem) -> Bool {
        switch item.action {
        case #selector(togglePause(_:)):
            item.state = engine.isPaused ? .on : .off          // observed truth
        case #selector(toggleSubtitles(_:)):
            item.state = engine.subtitlesVisible ? .on : .off  // observed truth
        case #selector(cycleAudioTrack(_:)):
            item.title = "Audio: \(engine.currentAudioTrackName)" // observed truth
        default:
            break
        }
        return engine.isMediaLoaded   // controls disable honestly when nothing's open
    }
}
// Not one line reads a variable we set when the user clicked. It's all engine.

External links

Exercise

Pick a screen in your app with several controls that reflect state — toggles, selected tabs, checkmarks, status badges. For each, ask: is this derived from the real state every time it renders, or was it set once when the user acted? Find one control that stores its own state and rewrite it to re-derive from the source of truth at display time. Then try to make it lie — change the underlying state some other way and see if the control still tells the truth.
Hint
The test is: can you change the real state through a different path (an event, another screen, the system) and catch the control still showing the old value? If yes, it's storing, not mirroring. Move it to re-derive at render/validation time from the one source of truth, and the lie becomes impossible to produce.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.