Repository navigation
Release v8.0.0 - #811
Merged
Merged
Release v8.0.0#811
Conversation
Sync v7.1.0 version bump to dev
RemoteCommandTracker keeps one pending/done state per key (Trio meal id or Loop sync identifier) with a 60 s timeout, and resolves it from the AID app's return push through two thin adapters: TRC by command_id, Loop by sync_identifier. Loop carb delete/edit require LoopFollow's return credentials, like Trio, since the push is the only confirmation. The detail view reads busy / failure message from the tracker and dismisses on a success transition it observes itself, so a terminal state left from an earlier visit never dismisses a freshly opened view.
An FPU child row offers Edit only when its root meal is loaded; the edit sheet is then prefilled with the root's macros and time and addresses the root's id. Delete stays available for every child and targets the whole meal. The view model builds the fpuID → root lookup once per regroup.
A Nightscout carb document from Trio is an FPU child exactly when its fpuID equals its id; a document without fpuID is a root meal.
Carbs, bolus, carb delete and carb edit share commandHeader for the otp, remote-address, notes, entered-by, sent-at, expiration and alert fields. The builders are static and take the send time, so tests pin the exact key set and values of each payload. A carb edit always carries carbs-edit-entry, carbs-edit-absorption-time and carbs-edit-start-time; carbs-edit-food-type is sent only when set.
LabeledValueRow renders the label/value rows in the treatment detail sections and both edit sheets. A Trio meal without carbs is listed as "Meal" with its fat and protein grams as subtitle. When Trio Remote Control is active but the Trio build's profile does not advertise the meal commands, the Meal section footer says a newer Trio version is needed.
A patched Loop lists carbs-delete and carbs-edit under loop.testingDetails.remoteCommands in every devicestatus upload. DeviceStatusLoop stores that list in loopRemoteCommands, clearing it when the key is absent, and the treatment detail offers the Loop carb remote actions only when both commands are advertised. With Loop APNS active but the commands missing, the carb entry section explains that the remote carb edit customization is needed.
* Add ability to double-click carbs to enter Treatments screen * Keep the carb detail sheet across remounts and share carb treatment construction (#758) * Share carb Treatment construction and root-meal lookup Treatment.carb builds a carb entry for both the treatments list and the chart's detail sheet, with one id fallback for entries without a Nightscout _id. Treatment.rootMealsByFPUID and rootMeal(in:) back the FPU-child root lookup in both places. * Refresh treatments when a remote meal command completes The chart's carb marks follow a remote meal edit or delete from any screen by running the treatments task as soon as the command resolves. * Keep the carb detail sheet in the chart shell BGChartView owns the selected carb and its sheet, outside the subtree that is remounted on foregrounding, so an open sheet survives a trip to Notification Center or the background. Double-tap hit-tests carb marks only, so a nearby bolus cannot shadow the carb it sits next to. --------- Co-authored-by: Jonas Björkert <jonas@bjorkert.se>
…6.04 (#767) * Update fastlane to 2.240.1 and move workflows off ubuntu-latest and macos-26 The Gemfile pins fastlane 2.240.1, which brings rubyzip and json onto version ranges without open security advisories. Jobs that ran on ubuntu-latest now run on ubuntu-26.04, since the ubuntu-latest label is about to move to Ubuntu 26 and GitHub posts a notice about it on every run. The build job runs on the xcode-27 runner image and selects Xcode 27.0. That image only ships Xcode 27, so the xcode-select path points at Xcode_27.0.app. * Run all macOS jobs on macos-26 The build job stays on Xcode 26.2. The certificate, identifier and secret validation jobs move from macos-15 to macos-26, so every workflow runs on either macos-26 or ubuntu-26.04. * Run all macOS jobs on the xcode-27 runner image The build job selects Xcode 27.0, which is the default on that image. The certificate, identifier and secret validation jobs run on the same image, so every workflow runs on either xcode-27 or ubuntu-26.04.
Treatment parsers force-cast `timestamp`/`created_at` to String after a `!= nil` check. A treatment carrying a JSON null or numeric timestamp passes the nil check and traps in swift_dynamicCast on the main queue, so the app aborts on every launch while that record is within the download window. Add NightscoutUtils.treatmentDate(from:) which accepts ISO 8601 strings, epoch milliseconds/seconds, and falls back to created_at on null; use it in the bolus, SMB, carb, note and stats parsers. Replace the remaining forced casts in device status, SAge, CAge and IAge handling with conditional binding so malformed data is skipped instead of crashing. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* Add device status history graphs and scrubbed-time values Cache the loop values from Nightscout devicestatus on the phone. The Show Days Back window is downloaded once in pages of 100 records, after that only missing ranges are fetched, and changing the Nightscout address drops the cache. Add optional IOB, COB, sensitivity ratio and smoothed BG graphs, shown as separate graphs under the main graph or in the bottom of the main graph. While scrubbing, the BG display and info table show the values at that time together with the forecast from that loop cycle, and the pill only lists treatments. A tap shows BG and treatments. Add a Smoothed BG info row and remove the divider between the BG display and the info table. * Remove the scrub pill and the main-graph legend While scrubbing, the BG display and info table show the values at that time, so the graph only shows the indicator and the forecast. The jump to now button is hidden while scrubbing. * Fade the jump to now button back in after scrubbing The button hides while scrubbing and fades in a moment after the finger lifts, so it is not in the way while reading the values. * Hide the jump to now button while panning and zooming The button hides while the chart is panned, zoomed or scrubbed and fades back in a moment after.
* Larger Snoozer text * Keep the Snoozer emoji and clock above the tab bar on small phones In portrait the left column's heights scale down together to leave room for the emoji and clock, and its text can shrink to 30% to fit.
The environment is read from the isAPNSProduction value that Loop uploads to the Nightscout profile, so the manual Production toggle is removed from the Loop APNS settings. The current environment is shown under Debug / Info, the same as for Trio.
* Define glucose range cut-offs in one place and pick the range mode from a full-width list The 54/70/140/180/250 mg/dL cut-offs were repeated across the stats, GRI, the settings footer and the Live Activity. They now live in GlucoseThresholds in Shared, so the app, Live Activity and watch targets all see the same values. Each TimeInRangeDisplayMode carries its title and fixed thresholds, and the range settings, stats title and stats card toggle are built from allCases, so a new mode is its cut-offs plus one case. The segmented TIR/TITR/Custom picker and its footer are replaced by a row showing the selected mode's full name and cut-offs, which opens a list with one line per mode. Choosing Custom Range stays on the list and shows the Low and High pickers there. The onboarding statistics page gets a navigation stack so the list can open from it. * Add Extended Tight Range (TING, 63–140 mg/dL) as a range mode TING is the tight range with its lower cut-off moved down from 70 to 63 mg/dL, also known as Time in Normoglycemia. It is shown as Extended Tight Range, sits between Time in Tight Range and Custom Range in the range list and the stats card toggle, and its cut-offs live in GlucoseThresholds next to TIR and TITR. The settings search finds Range Mode for "ting" and "extended".
* Switch Loop profiles from the Loop remote screen Adds a Profiles button that lists the profiles Loop uploads to Nightscout, previews one the way Loop does and sends an OTP-protected profile switch with a fingerprint of the previewed values. Loop's return push is matched by profile name. The button is greyed out with an explanation when Loop does not list profile-switch in remoteCommands. * Point the unavailable Profiles button at the profiles customization * Say the Profiles button needs the profiles customization * Require device authentication before sending a profile switch
* Ignore the previous pod's reservoir volume after a pod change Loop keeps uploading its last reservoir reading for 15 minutes after a pod change, under the new pod's ID. LoopFollow now ignores volumes for a new Omnipod until it has uploaded a record without one or 15 minutes have passed, and dates readings by the record's pump clock. * Treat a volume in an Omnipod record with no pod paired as the previous pod's * Show no reservoir volume for an Omnipod with no pod paired * Show no reservoir volume while Loop shows a pump status in its place * Show the status Loop uploads in place of the reservoir
… meal and bolus buttons (#792) * Open the watch bolus on the amount, start at the recommendation, and fit the meal and bolus buttons The bolus screen opens on the amount instead of a list that, without Quick-Pick boluses or a recent recommendation, held only Other Amount. Loop / Trio's recommendation and the Quick-Pick boluses move behind a Presets button under Continue, shown only when there are any, with the Old Calculation Warning as before. While the recommendation is under 5 minutes old the amount starts there, with an icon line showing the amount and its age. It is filled in once, so coming back from the confirmation keeps what was set. The Max line is gone, since the crown and + stop at the maximum, and − and + click like a crown detent. The meal and bolus buttons use a compact capsule whose height scales with the watch, so the amount and two buttons fit without scrolling; the system buttons pushed Log off the bottom of the meal screen. On the meal screen, Time and Log are both centered, so they line up. * Warn when the watch's starting recommendation goes stale, and drop it from Presets while fresh * Follow and check the latest bolus recommendation on the watch, and mark recommended amounts on the confirmation * Offer a newer watch bolus recommendation with a tap instead of applying it * Revert "Offer a newer watch bolus recommendation with a tap instead of applying it" This reverts commit dda326a. * Follow a lower watch bolus recommendation, offer a higher one with a tap, and catch up after the confirmation * Offer a recommendation that arrives after the watch bolus opened, follow only untouched amounts while on top, clear an expired starting recommendation, and let compact buttons wrap A loop cycle without a recommendation no longer counts as 0 U. The Presets button appears once the recommendation is old enough to be listed there, and meal Quick-Picks are centered like the other buttons. * Don't offer a bolus recommendation calculated before the last bolus After a bolus, the recommendation stays the same until Loop or Trio runs a new cycle and LoopFollow fetches it, which can take a few minutes. During that time the watch filled the old amount in again, so Continue and the crown would have given the bolus twice. The phone's bolus screens offered it too, with a tap. The phone now leaves out a recommendation when a manual bolus came after its loop cycle: from Nightscout, or sent from LoopFollow or the watch, alone or with a meal. The watch also ignores one from before insulin it sent itself, including when it sent directly. For Loop, the recommendation's time is now the cycle's own timestamp. The pump clock it used before also moves on failed cycles, which keep the old recommendation, so after a bolus that recommendation looked newer than the bolus. * Order the watch's last-insulin key modifiers the way SwiftFormat expects --------- Co-authored-by: Jonas Björkert <jonas@bjorkert.se>
…ity (#805) * Don't send the watch a state that hasn't changed Every Nightscout fetch rebuilds the chart, and every rebuild sent the full 24-hour state to the watch, even when nothing in it had changed. Each send can wake the watch app. The phone now skips a state equal to the last one sent, apart from its build time. It still sends at least every 5 minutes, well inside the 10 minutes after which the watch treats the phone's data as stale and fetches on its own. It always sends after the session activates or the watch changes (new install or pairing), and retries after a failed send. * Fetch from the watch after a command it sends without the phone When the phone is out of reach, the watch sends commands directly to Loop or Trio. Nothing then fetched the result: the watch only fetches on its own once the phone's last state is more than 10 minutes old, so a command sent soon after losing the phone could take up to 10 minutes to show. After a successful direct command, the watch now fetches 10, 20, 40 and 60 seconds after the send, even while the phone's last state is still fresh, and stops at the first fetch that shows the change: the preset's override or temp target, its cancellation, or a new bolus or carb entry with the sent amount. A check that never matches only means all four fetches run. The follow-up stops as soon as a newer state arrives from the phone, so a fetch that was already under way does not replace it. While the phone's last state is still fresh, its alarm stays shown, since the watch's own fetch has no alarms. The watch's own fetch now reads the override name from "notes" before "reason", as the phone does, so Trio overrides show the same name on both. * Fetch Nightscout early on the phone after a remote command Loop and Trio apply a command within seconds, but the phone only saw the result on its next regular fetch: up to 2 minutes for treatments (overrides, temp targets, boluses, carbs) and about 5 minutes for device status (IOB, recommended bolus). The phone, the watch and the Live Activity showed the old state until then. After a command is sent from the phone or the watch, the phone now fetches treatments and device status 10, 20, 30, 60, 90 and 120 seconds later. It stops as soon as the command's change is visible: the active override or temp target differs from before the send, or a new bolus or carb entry with the sent amount appears. A Trio meal sent with a bolus waits for both. A newer command restarts the schedule. Each fetch schedules the next, so when the app was suspended past several of them, as in the Bluetooth heartbeat modes, it fetches once on resuming instead of all the overdue ones at once. * Don't offer the watch a recommendation from before a manual bolus When the watch fetches on its own, it took the recommended bolus from the latest device status as is. If a manual bolus came after that loop cycle, the recommendation leaves that bolus out, and the watch could start the bolus screen at it. The phone already drops such a recommendation, and the watch only dropped one from before insulin it sent itself. The watch's own fetch now drops it the same way as the phone: when a manual bolus (not automatic, not an SMB) is at or after the loop cycle. This matters more now that the watch also fetches right after a command it sends without the phone, while the phone's last state is still fresh.
When no temp basal is running, the Basal info value is the scheduled rate at the current time, and the basal graph from the end of the last temp basal follows the schedule in the profile time zone, stepping at each schedule entry.
Trio in open loop uploads dosingMode "open" with only a suggested block and no temp basals, and Loop reports its Closed Loop setting as loopSettings.dosingEnabled in the profile. The loop status shows ⏀ in both cases, Trio IOB falls back to suggested.IOB, and the Basal row shows the scheduled profile basal when there are no temp basals.
…e Download Prediction setting (#809)
Contributor
|
|
bjorkert
approved these changes
Nov 2, 2026
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.
Release v8.0.0.
Merging this PR triggers the tagging workflow, which creates tag
v8.0.0fromLOOP_FOLLOW_MARKETING_VERSIONinConfig.xcconfig.mainkeeps the original feature-PR commits.