Disable survives a quit, the way switching one display off already did - #113
Merged
Conversation
Press Disable, quit Nifro, launch it again: the wallpapers are back. Switch a single display off from the panel and do the same, and it stays off. The two halves of "off" disagreed about whether they were worth keeping, and the half that lost is the one that covers the whole Mac. `disabledDisplays` is a `Defaults` key. `isManuallyDisabled` was a plain property on `AppState`, so it died with the process. `Constants.swift` sorts everything the app stores by one question — can this be asked again? — and names this as the one member out of place: the lock screen and the battery rule answer themselves the moment anybody wants to know, and a press does not. It gets a key. The property becomes that key rather than a value beside it, so there is one answer and not two. No `didSet` on the property. `Events` recomputes `isEnabled` from a change to the *key*, next to the line that does the same for `deactivateOnBattery` and for the same reason — the first delivery is what applies it on launch. That also gives the key its third writer for free: `Defaults.removeAll` deletes one key at a time, so Restore Defaults now switches the app back on. Before this change there was nothing to restore, and after it with a `didSet` there would have been a wiped key over a still-disabled app, with nothing on disk saying why. Which is the decision `RestoreDefaultsTests` demands of a new key, recorded there: this is one of the app's settings, so the wipe takes it. An app left switched off by a setting that has just been reset is the one state a user cannot read anywhere. The menu bar icon needed no change. It has read `isShowingWallpaper` since #107, which asks `isSwitchedOff`, which asks both switches — so the icon was already telling the truth about the state this makes reachable across a quit. That ordering was deliberate: this change makes a cold start with the app disabled a thing that happens, and the icon had to be honest first. 224 tests in 44 suites pass; build, `swiftlint --strict` and `periphery --strict` clean. Each of the three new assertions was checked by breaking the thing it names: dropping the key, making the property stored again, and pointing the subscription at another key. All three go red.
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.
What this is
Press Disable, quit Nifro, launch it again: the wallpapers are back. Switch a single display off from the panel and do the same, and it stays off. The two halves of "off" disagreed about whether they were worth keeping, and the half that lost is the one that covers the whole Mac.
The independent step the front/back alignment audit left last, and it was left last on purpose — see Scope.
Mechanism
disabledDisplaysis aDefaultskey.isManuallyDisabledwas a plain property onAppState, so it died with the process.Constants.swiftsorts everything the app stores by one question — can this be asked again? — and already named this as the one member out of place. The lock screen and the battery rule answer themselves the moment anybody wants to know. A press does not.It gets a key, and the property becomes that key rather than a value beside it, so there is one answer and not two.
No
didSeton the property.EventsrecomputesisEnabledfrom a change to the key, next to the line that does the same fordeactivateOnBatteryand for the same reason: the first delivery is what applies it on launch. That also gives the key its third writer for free —Defaults.removeAlldeletes one key at a time, so Restore Defaults now switches the app back on. Before this change there was nothing to restore; after it, with adidSet, there would have been a wiped key over a still-disabled app and nothing on disk saying why.Which is the decision
RestoreDefaultsTestsdemands of any new key, and it is recorded there: this is one of the app's settings, so the wipe takes it. An app left switched off by a setting that has just been reset is the one state a user cannot read anywhere.Scope
The menu bar icon needed no change, and that is why this step came last. It has read
isShowingWallpapersince #107, which asksisSwitchedOff, which asks both switches — so the icon was already honest about the state this makes reachable. Landed the other way round, this would have made a cold start with the app disabled a thing that happens while the icon still drew it as fully on.Nothing else about Disable changes: the menu item, the keyboard shortcut and the Shortcuts action all write the same property they wrote before.
Verification
224 tests in 44 suites pass;
xcodebuildDebug,swiftlint --strictandperiphery --strictall clean. macOS 26, Apple silicon.Three new assertions in
Tests/DisableSurvivesAQuitTests.swift, one per piece of the path, each checked by breaking the thing it names — dropping the key, making the property stored again, pointing the subscription at another key. All three go red.Worth running by hand, since
Appcompiles into no SwiftPM target:isSwitchedOffdoing its job and not this change.