Repository navigation
Sync upstream Trio dev (e797b4adf) into Tai dev - #38
Merged
Merged
Conversation
When "Use CGM App Alerts" is on and the active CGM provides its own glucose alerts, evaluateGlucoseAlarms() bails on every new reading and called retractAllFiringIfNeeded(), which retracted every firing alarm — including forecastedLow and carbsRequired. Those are determination-driven and deliberately not covered by the CGM-ownership guard (a CGM app cannot compute Trio's forecast or carbsReq), so the next determination a few seconds later fired them again. The result was "Low Glucose Soon" and "Carbs Required" re-delivered with sound on every loop cycle for as long as the condition held; retractAlert also resets the 5-minute throttle, so it never engaged. Retract only the reading-driven alarms on that path. Forecast and carbs-required alarms keep their firing state across reading updates and retract through their own evaluators on recovery or snooze, as before. Low Glucose Soon only started firing on these CGMs with #1428, which is when the repeat became visible; Carbs Required had the same cycle before.
Points G7SensorKit at loopandlearn feat/trio-g7-direct, which carries the direct-connection work from LoopKit/G7SensorKit#67 plus the changes needed to build against the LoopKit Trio ships. The direct G7 stack originates in DexKit by Erik Tolboom (MIT), built and proven with Trio tester feedback over several weeks; Pete Schwamb ported it into G7SensorKit in #67. Per-file attribution headers are retained in that repository. No picker change needed: the existing Dexcom G7 / ONE+ entry already routes through G7UICoordinator, so onboarding picks up direct pairing with no re-pairing. Info.plist gains dexcomoneplus and stelo for the app-detection warning (LoopKit/Loop#2512; dexcomg7 was already present) and a camera usage description, without which TCC kills the app when the onboarding package scanner asks for access. Co-authored-by: ETolboom <e.s.tolboom@student.tue.nl> Co-authored-by: Pete Schwamb <pete@schwamb.net>
G7SensorKit already drives Stelo (DX01 advertisements, its own sensor model and title); only the picker still read G7 / ONE+. Co-authored-by: ETolboom <e.s.tolboom@student.tue.nl>
The Lock Screen Widget Style picker only offered a Widget Configuration screen for the Detailed style. The Simple style had no configuration at all, and its glucose reading was hard-coded to `.title` and colored only when the Dynamic glucose color scheme happened to be selected. Add a Widget Configuration screen for the Simple style with: - Font Face: Default, Rounded, Serif or Monospaced typeface for the glucose reading and its trend arrow. - Font Size: Small, Medium, Large or Extra Large, backed by Dynamic Type text styles so the reading keeps scaling with the user's text size. - Color Glucose Reading: when on, the reading, trend arrow and delta use the app's existing glucose coloring rules (Glucose Color Scheme plus the Low/High thresholds); when off, they use the default text color. The screen shows a live preview of the Simple layout, with a Low / In Range / High sample selector so the coloring can be judged per band. The preview resolves its color the same way `LiveActivityView` does. The settings live in `TrioSettings` and travel to the widget through a new `LiveActivityAttributes.SimpleViewStyle` on the content state, so changes push to a running Live Activity right away. The enums and the style struct are shared by the app and the LiveActivityExtension target. Along the way, `bgAndTrend` and `LiveActivityGlucoseDeltaLabelView` no longer re-derive the static-color-scheme decision internally; callers now pass the resolved color. The Dynamic Island call sites pass exactly what those views resolved before, so their appearance is unchanged. Behavior change: with Color Glucose Reading defaulting to on, users on the Static glucose color scheme now see the Simple lock screen reading in its band color, matching what the Detailed style already does. It can be turned off on the new screen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
Two follow-ups to the Simple style's Widget Configuration screen: Color Glucose Reading now defaults to off, so the Simple lock screen reading stays in the default text color until the user opts in. The Detailed style gains a "Glucose, Trend, Delta (Double Width)" item that puts the reading, its trend arrow and the delta on a single line and takes two of the four configuration slots. Its button in the slot row spans both slots, and the row keeps its overall width. Slot occupancy is tracked with a `wideContinuation` placeholder written into the slot the wide item swallows. The "Add Widget" sheet only offers an item that still fits at the tapped slot, removing a wide item frees both of its slots, and a saved order is repaired on load so a wide item always owns its second slot and no placeholder is left stranded. The widget drops the placeholders before laying out the row, so they earn no divider or gap. Also fixed while in this code: `loadOrder` could trap on a saved order longer than four slots (negative `Array(repeating:count:)`), and the slot `ForEach` keyed on `\.element`, which is not unique once more than one slot is empty — it now keys on the slot's position. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
The Simple style's Widget Configuration briefly carried its own "Color Glucose Reading" toggle. A second, Live-Activity-only color switch sat awkwardly next to the app-wide Glucose Color Scheme: it read like a global setting but governed only the iPhone lock screen Simple layout, leaving the Watch/CarPlay widget and the Detailed layout on the app-wide setting. Remove it and leave the Glucose Color Scheme in sole charge. Reading color in every Live Activity layout is now exactly what it was before this branch. `bgAndTrend`, `LiveActivityGlucoseDeltaLabelView` and the Dynamic Island call sites are restored verbatim, so the call-site color refactor those changes required is gone too — it was only there to serve the toggle. The Widget Configuration screen keeps Font Face and Font Size, and its preview resolves color the way the widget does, so it shows an uncolored reading while the Static scheme is selected. A line in the preview footer says where that setting lives. Also restores the "Simple:" hint sentence verbatim and puts the new information in a sentence of its own. Editing the original would have changed its String Catalog key and dropped every existing translation of it back to English. Net effect on users: nobody's Live Activity changes color on update. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
The screen offered four "+" buttons and an action sheet, and told users that re-ordering meant removing every widget and adding it back in the order they wanted. Replace that with direct manipulation: - Drag a widget in the layout row to move it. Dropping it on another widget puts it in that position and shifts the rest along. - An "Available Widgets" palette below the layout lists every widget. Drag one up into the row to add it at a chosen position, or tap it to append. Widgets already placed, or too wide for the room that is left, are dimmed. - Drag a widget back down onto the palette to take it out of the layout. The trash button on each widget still removes it. The layout is now held as an ordered list of widgets whose slot widths spend a four-slot budget, rather than as a fixed array with holes. That makes a move an ordinary list reorder and keeps the double-width widget honest without per-position arithmetic. It is expanded back into the four-slot array on save, and a saved array is read back leniently: gaps, stranded continuation placeholders, repeats and widgets that would overrun the four slots are all dropped. Because the list has no interior gaps, a layout saved with an empty slot in the middle compacts the first time it is edited. The widget renders the same, minus that gap. The drag payload is the widget enum itself, carried as JSON via Transferable. An app-specific exported UTType would have to be declared in Info.plist, and anything dropped from outside simply fails to decode. Also drops an unused `color` gradient the file had been carrying. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
…t help, larger sizes Addresses review feedback on the Simple Lock Screen widget configuration and the double-width detailed item: - Simple config preview now shows the real current CGM reading (value, delta, trend) fetched from Core Data and refreshed live, instead of a canned Low/In Range/High sample. Removed the sample picker and its footer text. - Font Face "Rounded" now renders distinctly: glucoseFont uses SwiftUI .system(size:weight:design:); the previous UIFontDescriptor route silently dropped the rounded design. - Filled in the "Glucose Reading Font" help sheet, which rendered blank because it read shared mutable @State that presented empty. Its content is now static. - Enlarged every font-size step (Small 30pt through Extra Large 64pt, Dynamic Type scaled); Extra Large drops vertical padding to fill the widget; the double-width Glucose/Trend/Delta item is drawn much larger in both the configuration preview and the Live Activity. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r palette - Rename "Glucose and Trend, no Delta" to "Glucose and Trend (Colored)" and add an uncolored "Glucose and Trend". - Rename "Glucose, Trend, Delta (Double Width)" to "... (Double Width, Colored)" and add an uncolored "Glucose, Trend, Delta (Double Width)". - Add a colored single "Glucose, Trend, Delta (Colored)" so each glucose widget shape has a colored and an uncolored variant. Colored draws the reading (and, for the single/large items, the trend) in the glucose color; uncolored uses the default text color. New enum cases added to both the settings and the Live Activity attributes enums with matching raw values; saved layouts keep working since existing raw values are unchanged. - Available Widgets palette: lay out on a three-column grid so each double-width widget spans two columns and shares its line with the matching single-width widget, and show the full widget title instead of truncating at two lines. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
storeCarbs mints the fpuID when the caller omits it, so the parent row and the FPU children always link. saveCarbsToCoreData keeps a UUID entry id and replaces only non-UUID ids.
Nightscout, Apple Health and Tidepool deletes are awaited before the Core Data rows are removed, and Nightscout failures are reported to the caller. The History screen delegates delete and edit to the service.
fetchMealRoot accepts a root id or the family fpuID. Nightscout carb and FPU treatments include fpuID, and the profile store lists the remote command types this build accepts.
meal_id is the Nightscout id of the meal root or of one of its carb equivalents. Edit replaces the meal through CarbEntryMutationService, so the id changes and the ack carries the new one. Acks include command_id, meal_id and result; unknown command types are rejected with an ack.
storeCarbs stores the fpuID a caller supplies and derives carb equivalents only when both fat and protein are set. A UUID-parsable entry id is kept as the Core Data row id.
A root with fat or protein but no fpuID is rejected with a clear message, and a failing deleteMeal/replaceMeal call yields a rejected ack. CarbEntryMutationService returns plain failure message lists, syncMealsWithServices is private, and CommandType derives its supported list from CaseIterable.
v1.0.1's submodule update moved G7SensorKit to c2abb4f, a lokalise translations commit on main. Our pin tracks feat/trio-g7-direct, so the gitlink conflicted; resolved by merging c2abb4f into that branch (6f015b9) rather than dropping the translations.
Picks up LoopKit/G7SensorKit#70 (manual pairing robust when other sensors are nearby) and #71 (Dexcom Share upload with follower management), merged into feat/trio-g7-direct. No Trio-side changes needed.
Follows dnzxy's review on nightscout/Trio#1566. - Remove the Simple layout's font face option end to end: the enum, the setting and its decoding, the state model binding, the picker, the settings-export row, and the SimpleViewStyle field. Font size stays. Help and hint text that mentioned the typeface now describe size only. - Drop the `#if canImport(UIKit)` guards and their `#else` fallbacks in LiveActivityGlucoseStyle. Both targets are iOS-only, so UIKit is always available and the fallback never compiled in. - Draw the double-width item's delta in the same font as its reading, in the Live Activity and in the configuration preview, so the two do not sit at mismatched sizes. The widget shares one `wideFont` so they cannot drift apart. - Palette cells no longer box the label together with the widget. Each cell shows the widget as the same tile it becomes in the layout row, with its name beneath it. The row, the palette and the drag preview now share one `widgetTile` helper. - Remove the explanatory comments flagged in review, and two more of the same kind in LiveActivityView. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
The file is not part of any target and never compiles: the Xcode project has no reference to it, and Trio/Sources is not a synchronized folder. It holds an obsolete copy of `LiveActivityAttributes` whose ContentState no longer matches the real one in LiveActitiyAttributes.swift, and it occupies the path that file should have. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
Fixes the long-standing typo in the filename. Contents are unchanged. The project keeps the file's existing references and IDs, so it stays in both the Trio and LiveActivityExtension targets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
Drops the doc and inline comments this branch added that restate what the code already says. Comment-only change: no code lines are touched. Kept: the section MARKs, which Trio uses as navigation elsewhere; a one-line note on the `wideContinuation` sentinel case; and a one-line note on why the drag payload is JSON rather than a custom exported UTType, which would need an Info.plist declaration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
…ents Follows the rest of dnzxy's review on nightscout/Trio#1566. - The Simple Widget Configuration preview no longer reads live CGM data. It shows a fixed 123 / → / +6 reading, the same mock the Detailed configuration's previews use. That removes the Core Data fetch, the glucose storage subscription, the injected GlucoseStorage and the three published reading properties from the settings state model, which now only adds the font size setting over upstream. - Remove the two one-line comments kept in the previous cleanup: the `wideContinuation` case note and the note on the JSON drag payload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UVfX1mSyg6kjsVtCoW8mau
The delta in the double-width Glucose, Trend, Delta widget used the same bold largeTitle as the glucose value, so "+6" was as prominent as the reading itself. Give it the arrow's size (title2, title3 on watchOS), and make the Widget Configuration preview mirror the widget: glucose at largeTitle with the arrow and delta at title2. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RwMti9CLZgjS37Tzpz41Ut
Add Glycemia Risk Index feature with calculations and UI components
fix race condition: Persist the restored pump manager's state on processQueue
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcptGJfxyCKscK3RaZuqby
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcptGJfxyCKscK3RaZuqby
Add a Statistics Range setting for the home stats panel
Add Dexcom G7, ONE+ and Stelo Direct Sensor Connection
The sync took the upstream catalog; re-insert the 726 keys that only exist in Tai, keeping upstream values and key order for shared keys.
Tai keeps its duration-based FPU split and excludes upstream's capped 3-entry split (PRs #951/#1019/#1022), so the hardcoded count == 3 expectations in testDeleteMealRemovesFamily and testDeleteChildThrows failed. Assert one root plus carb-equivalent children belonging to the meal, and an unchanged row set after the rejected child delete.
Rework Trio Alarm Sounds: Add Urgency Levels and Voice Alarms
fixes crash when uploading carb entry without id to Tidepool issue #1425
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.
Sync upstream Trio dev (e797b4a) into Tai dev
Tai
dev(7daf1348f, 1.0.2) is merged with upstreamnightscout/Triodevate797b4adf— 95 upstream commits since the last sync atefb5bea30. Branchsync/trio-2026-10-19: merge commit17841352a, plus93c3c79e9re-adding the Tai-only localization keys on top of the upstream catalog and four small follow-ups,66a3c49b5(build fix inGlucoseSetup.swift),9854cd2b1(SwiftLint cleanups),6f8bc95c7(Home Statistics Panel hint wording) and0cb7835aa(test-only adaptation of the mergedCarbEntryMutationServiceTeststo Tai's FPU split). Net againstdev: 78 files, +3282 −707.What comes in from upstream
GRICalculator,GRIView) show the GRI alongside the existing statistics, backed byGRICalculatorTests.G7SensorKitonfeat/trio-g7-directlets the app talk to G7, ONE+ and Stelo directly, including owning glucose alerts when the sensor is paired to the app rather than the receiver. Stelo is named in the picker.delete_mealandedit_mealremote commands (TrioRemoteControl+MealMutation), with unlinked meals and service errors rejected and meal roots resolved by handle; the payload publishes the fpuID and the supported command list (RemoteMealMutationPayloadTests).CarbEntryMutationService. The meal deletion and replacement logic is extracted into one service shared by the remote commands and the app (CarbEntryMutationServiceTests), and a meal and its carb equivalents now share one fpuID.LiveActivitySimpleWidgetConfiguration), andLiveActitiyAttributes.swiftrenamed toLiveActivityAttributes.swiftwith its references inproject.pbxprojupdated.Gemfile.lockbumps, and submodule pin moves forG7SensorKit5c0fc075a,LibreLoop82c92f2cfandOmnipodKit928bb7950.Tai specifics that stay
autoISF settings, the Garmin watchface and datafield selection, the profile scheduler, Bobble/CGM status, glucose peaks, the today-average display, Trio Chart, and Tai's versioning in
Config.xcconfig(APP_DEV_VERSION = 1.0.2.12) are unchanged by the merge. Tai's 726 fork-only localization strings were re-added on top of the upstream catalog, so the file holds the exact union: 3475 keys, no Tai key lost, no key added beyond the two sides.Tai also keeps its duration-based FPU carb-equivalent split with the 10-minute minimum instead of upstream's capped 3-entry split (upstream PRs #951/#1019/#1022), as recorded under "Deliberate Tai differences" in
UPSTREAM_SYNC_BASELINE.md; the merged upstreamCarbEntryMutationServiceTestswas adapted to that behaviour in0cb7835aa, and Tai's ownCarbsStorageTests.swiftdoes not carry the capped-split expectations either.Conflicts
The 13 conflicted files were resolved by integrating both sides — upstream's Home Statistics Panel and range setting together with Tai's fork UI — and
Localizable.xcstringswas taken from upstream and re-augmented with the Tai-only keys.Known residual, cosmetic: the Home Statistics Panel hint text in Tai's UI still says "today's" although a range setting now exists. The banner itself follows the range; the wording is a follow-up.
Testing
xcodebuild -list -project Trio.xcodeprojparses and lists the six targets (Trio, TrioTests, LiveActivityExtension, Trio Watch App, Trio Watch AppTests, Trio Watch Complication Extension).git merge-base --is-ancestor e797b4adf HEADpasses; the merge carries 95 upstream commits.project.pbxproj(build file, sources phase, file reference and group), and the three new tests sit in the TrioTests target.Localizable.xcstringsis valid JSON and the key union is exact (3475 keys, 0 missing, 0 extra).xcodebuild -workspace Trio.xcworkspace -scheme Trio -destination 'generic/platform=iOS Simulator' buildon the branch exits 0; the one build artifact of the merge (aGlucoseSetupscope error) is fixed in66a3c49b5.9854cd2b1:Algorithm Package (swift test)passed (56s) andRun Unit Testsfailed (14m35s) with exactly two assertion failures, both in upstream's newCarbEntryMutationServiceTests.swift— thecount == 3expectations in "Delete removes the root and its carb equivalents" and "Delete on a carb equivalent row is rejected", which encode upstream's capped 3-entry fat/protein split. That split is a documented Tai exclusion (UPSTREAM_SYNC_BASELINE.md), so the tests, not the code, were wrong for this fork.0cb7835aachanges that one test file only (+15 −2): the family is asserted by provenance (one root with the meal'sid, its carb equivalents byfpuID, non-zero carbs) instead of a hardcoded row count, and the rejected child delete asserts an unchanged before/after row set. No production code and no FPU algorithm change.xcodebuild test -workspace Trio.xcworkspace -scheme 'Trio Tests' -destination 'platform=iOS Simulator,id=66ACB141-5FFF-47ED-9701-2957699F7522' -only-testing:TrioTests/CarbEntryMutationServiceTests— 10 tests in 1 suite passed,TEST SUCCEEDED, exit 0.0cb7835aa:Algorithm Package (swift test)passes (54s) andRun Unit Testspasses (17m23s) — green on the fix head.CI on the PR (
Algorithm Package/Run Unit Tests) is the gate. The on-device check is done by the operator once CI is green.Merge target:
Tai/dev— do not merge before CI is green.