Repository navigation
iPhone: the planning style as a scale, the levers under the plan, and what a change moved (plan pass 5) - #61
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
So the plan's saving compares honestly and the plan view shows it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For pictures of the plan's unpriced stubs and its style line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plan on screen when a change leaves is kept beside the box's next plan, so the strip, the dial and a sentence can show only the quarters that moved. The style scale steps by fractions of one turn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(plan pass 5) The style is one control with five stops: a tick per stop, one command when the finger lets go, the receipt in the status line. It sits under the plan with the car's goal and the mode, and in the mode sheet that Now's button now opens. After a change, only the quarters that moved cross-fade on the strip and the dial, and one line says what moved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sheet held by the mode button in the bar did not open a second time after it closed itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opened again just after a mode was applied, it saw that change and closed itself. The tests now scroll the sheet in short, slow drags. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The demo answered after 0.9 s, and XCTest's wait for the app to settle after the tap took a second, so the look raced the answer. A debug flag, -FTWDemoResultDelayMs, lets this test hold the answer for 2.5 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
# Conflicts: # appleApp/FTW/UI/PlanView.swift # appleApp/FTWKit/Sources/FTWShared/PlanGlance.swift # appleApp/FTWKit/Sources/FTWShared/Resources/en.lproj/Plan.strings # appleApp/FTWKit/Sources/FTWShared/Resources/sv.lproj/Plan.strings
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 906206ea5b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| guard !sending else { return } | ||
| clearing?.cancel() | ||
| change = Change(ask: ask) | ||
| willSend?() |
There was a problem hiding this comment.
Clear pending plan attribution when a command fails
Calling willSend before the command is accepted records the current plan as awaiting a user-driven revision, but rejected, expired, or failed commands never clear that expectation. If the box publishes an unrelated plan revision within the next two minutes—for example, a scheduled replan while a command is refused—PlanModel.take attributes it to the failed action and shows a misleading “New plan” explanation and cross-fade. Clear the expectation for non-applied outcomes, while retaining support for plans that genuinely arrive before an applied receipt.
Useful? React with 👍 / 👎.
| for kind in [Kind.charge, .discharge, .car] { | ||
| let a = before.first { $0.kind == kind }, b = after.first { $0.kind == kind } | ||
| switch (a, b) { | ||
| case let (a?, b?) where abs(a.startMs - b.startMs) >= 60_000: |
There was a problem hiding this comment.
Compare later runs when describing what moved
Using only the first event of each kind misses changes whenever the earliest charge, discharge, or car window stays fixed but a later window moves, appears, or disappears. In that case the equal first start times fall through without adding a line, so moved can return nil even while the strip and dial detect and fade the changed quarters; this leaves both the plan view and mode sheet without the promised explanation. Compare the per-kind event sequences and report the first differing run instead.
Useful? React with 👍 / 👎.
|
UI tests on 8c0a0c6, iPhone SE (3rd generation), iOS 26.5: 18 of 18 green.
Since then main is merged in (70e43e7): #57 and #49. The four files that conflicted ( |
|
On 70e43e7 (main merged in): the watch app and the phone app build, |
Plan pass, change 5 of 5: the two levers under the plan, the planning style as a scale with five stops, and what a change moved. It targets main and carries changes 2–4 (#58, #59, #60) unchanged under its own commits, so the stack lands as one squash; main is merged in at 70e43e7.
What changes
The planning style is one control, not a list. Five stops, from very careful at the left to very bold at the right,
← FÖRSIKTIGandDJÄRV →at the ends. A finger moves the thumb from stop to stop with a.selectiontick at each; under the scale the style's name and its help in one line follow the thumb: "Balanserad · Planerar med lite marginal." One command goes when the finger lets go, and only if the stop changed: never one per stop. The status line walks the receipt,SKICKAT ▸ BEKRÄFTAT.It rests until the box has spoken in this session, while a manual mode runs, and while a change is on its way. Before the box has named its style it has no thumb: it never shows a guess. VoiceOver reads it as one adjustable element with the style's whole help, "Planeringsstil, Djärv. Planerar nära prognosen.", and each swipe up or down steps one style and sends it. With Reduce Motion the thumb jumps rather than springs.
Where it sits. At the foot of the plan view, under two plain rows:
BIL 80 % till 07:00 vardagar ›, which opens the car view, andLÄGE Plan ⌃⌄, which opens the mode sheet for the manual modes and selling to the grid. On Now, the glass mode button opens the same sheet in place of its menu, sized to its content, with the scale where the style picker was. The manual modes stay a short list of rows there. The root view presents it: a sheet held by the button in the bar did not open a second time after it closed itself.What a change moved. When the box's next plan comes after a change of the person's own, only the quarters that moved cross-fade, in 0.2 s, on Now's strip and on the dial; the rest hold still. One line says what moved, under the dial's story and under the scale in the sheet, until the box replans of its own accord:
Slider or arc
Fredrik asked for a slider or a short arc and for both to be shown. This ships the straight scale; the arc is behind a debug flag,
-FTWStyleControl arc, and in the pictures and the second clip below. Fredrik picks after trying both in TestFlight.The straight scale, because:
How
StyleScale(new): the shared logic and both looks.ModeModel.stop(at:)andfraction(of:)map a place to a stop;Style.briefis the help in one line.PlanModel.expectChange()keeps the plan on screen when a change is sent (ModeModel.willSend), andtake()setsPlanModel.movewhen the next revision comes within two minutes. The box may send the plan before its receipt, so this cannot wait forapplied.PlanShare.beforeandmoved;PlanGlance.moved(from:to:atMs:)says what changed;PlanStrip.moved(from:)andPlanDial.moved(from:)list the quarters.MovedFadedraws the old drawing over the new on the ground's colour, masked to the moved quarters (QuarterColumns,QuarterWedges), and fades it out. It plays once, as the plan arrives; a view opened later shows the new plan at once.CLAUDE.md: one row in the design references for a control with a few stops.Two fixes the new sheet needed:
HomeSheet.mode).Evidence
swift teston 70e43e7: FTWShared 226 and FTWKit 369 tests green. New:aChangeShowsWhatThePlanMoved(the plan before a change and the one after, also when the box sends the plan before its receipt),aNewPlanSaysWhatItMoved,onlyTheMovedQuartersChange,onlyTheMovedTicksChange.testTheStyleScaleSendsOnceWhenTheFingerLetsGodrags from Balanced to Very bold, waits forCONFIRMED, finds the moved line in the sheet, and drags back. It passed in every run.testTheModeMenuChangesTheModeAndTheLineFollowsTheBoxnow goes through the sheet.testTheModeSheetFitsWaitsInPlaceAndClosesOnceAppliedlooked at the tick 0.15 s after a tap, but XCTest's wait for the app to settle took a second, past the demo's 0.9 s answer. It raced on change 4 too and is the known flake on the Pro Max. The test now holds the demo's answer for 2.5 s with a debug flag,-FTWDemoResultDelayMs. On 8c0a0c6 and on 70e43e7 (main merged in),NowFitsTests12 of 12,PlanStripTests3 of 3 andPlanDialTests3 of 3. On 70e43e7 the watch app builds too.Recording
The plan view while the scale drives itself (
-FTWStyleScrub YES): to the levers, Balanserad → Mycket djärv with a tick at each stop, let go,SKICKAT ▸ MOTTAGET ▸ BEKRÄFTATin the status line, back to the dial as the new plan lands, its moved quarters fade, and "Ny plan 22:16: lagrar 23:00 i stället för 22:45." Then to Försiktig and back to Balanserad.The same as mp4
The arc, the same way: gif · mp4
Both clips are from before 906206e, which fades the old words out before the new fade in: in them the words overlap for a moment as the thumb moves. The same drive on 70e43e7, with the fix: gif · mp4
Pictures
The levers under the plan, dark and light, and at the largest text.
Line or arc: under the plan in dark, and in the sheet in light.
Now's mode button opens the sheet, dark and light.
🤖 Generated with Claude Code