Repository navigation
feat(ios): choose which price the app shows - #141
Conversation
Erik, 1 November 2026: Now's strip made 450 against 550 öre look five times dearer. It put the window's cheapest quarter at the floor and the dearest at the top. Every price bar now reads one PriceScale: zero at the foot and a round top just over the dearest (1, 1.5, 2, 2.5, 3, 4, 5, 6 or 8 times a power of ten). Now's strip draws the bars from zero, marks half the top and the top with figures in a gutter on the right, and carries the price now on as a dashed line. A price below zero hangs under the zero line. The dial's ticks, the lock-screen glyphs, the plan widget and the watch's bars take the same scale in eight steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fredrik picked proposal 5 for Now on 1 November 2026. Each run of the battery and each car window on the strip is a pass (PlanPass, FTWShared, tested). A tap chooses one: it stands in full colour over a faint column of its colour, the bars under it take that colour, and three figures under the strip say when it runs, what it does to the level and the price it meets. The strip opens on the battery's run under way or next. A run on spare sun says it buys nothing. With no pass, the sentence stays; under a finger, the quarter's line still takes its place. The colours are Phosphor's, not the proposal's: gold gives power, cyan stores, violet for the car. Nothing glows, since a plan is not live. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Erik, 1 November 2026: on the 24-hour dial 18 is not straight down as on a clock, so you lose the feel for when things happen and have to read the figures at the edge. Fredrik said yes to round 3 of the design canvas the same day. - The dial is a clock: one turn is the next twelve hours, 12 at the top and 18 straight down, with the turn's whole hours round the rim. Its ticks are as long as the battery's planned power and coloured by what it does, gold giving power as on the strip, cyan storing. The price leaves the dial. The phone, its widget and the watch draw the same face. - Under the dial, and as the lanes, the plan shows Now's strip: the passes, the price from zero and the chosen pass's figures. A tap on a pass lights its ticks on the dial. The lanes run the whole plan with the battery's level in a row of its own. - The old lanes, the story under the dial and the rows under the lanes go; the figures say what they said. CLAUDE.md's dial rules follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fredrik, 1 November 2026: he wants the price without grid fees, and to know whether it is with or without VAT. Home gets "Price shown" with two switches: with the grid fee and tax, and with VAT. Now's strip, the plan and the price page draw the chosen price (PriceShown, FTWShared, tested) and name it: "SPOT INCL. VAT", "ELPRIS INKL. MOMS". The box sends spotMinor and totalMinor, and with srcfl/ftw#1949 the VAT rate it taxed at, as vatPermille (250 is 25 %), on price.get and on FTW Cloud's price tile. The phone reads both and keeps the rate with the prices. A box that does not send it gets the price the phone has: the total keeps its VAT, the spot price goes without, and the label says so. The widgets and the watch still show the total with VAT. The demo box sends 250. 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. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a29346897
ℹ️ 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".
| let prices = (entry?.prices ?? []).filter { $0.totalMinor.isFinite && $0.durationMs > 0 }.sorted { $0.startMs < $1.startMs } | ||
| // The prices this phone chose to show, where the price record has | ||
| // them, else the ones under the plan. | ||
| let prices = (shown ?? entry?.prices ?? []).filter { $0.totalMinor.isFinite && $0.durationMs > 0 }.sorted { $0.startMs < $1.startMs } |
There was a problem hiding this comment.
Preserve plan prices outside the price record's coverage
When the separately fetched price record is older or shorter than the plan, this replaces all of the plan's prices instead of falling back for uncovered quarters. Both Now and Plan now pass PriceModel.prices.slots here, and PriceModel.load() deliberately retains its previous window when fetching fails. Consequently, a newly received plan can contain tomorrow's prices while these strips show missing-price stubs for tomorrow—or no prices at all if the retained window has ended—even with the default display settings. Preserve coverage from the plan, applying the selected price representation consistently, rather than treating any non-nil price array as complete.
Useful? React with 👍 / 👎.
…ip ci] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why
Fredrik, 1 November 2026: the shown price should be a setting. He wants it without grid fees, and wants to know whether it is with or without VAT. This is step 4 of four. It stacks on #140 (and so on #139 and #138).
Paired with srcfl/ftw#1949 (Core sends
vatPermilleonprice.getand on FTW Cloud's price tile) and srcfl/ftw-webapp#116 (the protocol doc and the web client's type). The app works with an older box too; see below.Change
PriceShown(FTWShared, tested) turns the box'sspotMinorandtotalMinorinto the chosen price:totalMinor, as before and the default;totalMinor / (1 + v);spotMinor × (1 + v);spotMinor.It puts the result in
totalMinor, so every chart that drew the total draws the choice.Prices.vatPermilleis read fromprice.get(Messages.swift) and from FTW Cloud's tile (CloudWire.Prices), and kept in the cache (optional, so an older record still reads). The demo box sends 250.Evidence
swift testinappleApp/FTWKit: 638 tests in 96 suites and 348 Swift Testing tests pass locally. New:PriceShownTests(Erik's 462 öre: 369.6 total without VAT, 311.25 spot with VAT, 249 spot),PriceWireTests(the answer with 255, with 0, and without the key), and the cloud tile test now carries 250 to the widgets' record.The default is Fredrik's call
The PR keeps the total with VAT as the default, so nothing changes for anyone who does not touch the switches.
🤖 Generated with Claude Code