Tidepool sync 2026-05-11#2438
Open
loopkitdev wants to merge 494 commits into
Open
Conversation
…date UI (LoopKit#749) * if delivery states are not changed, still update UI * set refresh context before reloading
…ntifiers-for-new-test [QAE-446] Add identifiers for new tests
* Preset editing * Preset editing updates * Add duration editing * Add duration for legacy workout override
…ntifiers-for-UI-tests [QAE-451] Add identifier for Presets button
…was manually edited (LoopKit#757)
… updates. (LoopKit#925) * [LOOP-1114] Add blocking modal and open loop enforcement for required updates When a support plugin returns .required from checkVersion, Loop now: - Forces the app into open loop mode - Sends a critical user notification - Presents a non-dismissable modal with an App Store link The modal and notification use the dynamic app name for white labeling. * Clean up unneeded checks for pre iOS 15 support
…nce & Fix Status Icon Mismatch/Freshness Sync (LoopKit#924) * [LOOP-5878] Remove Duplicate Reference * [LOOP-5797] Fix Loop Status Icon Mismatch * [LOOP-5771] Freshness Sync * [LOOP-5771] Freshness Color Sync
…pKit#927) * Updates to wording and layout tweak for Required Software Update * Tweaks
14 commits from tidepool-org/Loop dev. Only the project.pbxproj had conflicts (3 regions); all source files auto-merged. pbxproj resolution: - Region 260-264 / 1033-1037: kept both ContentMargin.swift (DIY) and PresetPerformanceHistoryView.swift (Tidepool) — additive - Region 1251-1261: dropped Tidepool's *.strings PBXFileReferences (ru/de InfoPlist/Localizable/ckcomplication); kept Tidepool's new Swift files (RequiredVersionUpdateView, AutomationHistoryEntry, AutomationHistoryEntryTests, LoopCircleView) - Removed 3 orphaned variant-group children at lines ~4088, 4147, 4166 that referenced the dropped .strings FileReferences
# Conflicts: # Loop/Managers/Live Activity/LiveActivityManager.swift
Without this, automatic temp basal changes, no-op Loop cycles, and manual temp basal cancellations never produce the "updateRemoteRecommendation" dosing decision that NightscoutService pairs with the cached "loop" decision to upload Loop pill + forecast. Add a force parameter to updateRemoteRecommendation() that bypasses the "manual bolus rec changed" gate, forwarded through updateDisplayState as forceStoreRemoteRecommendation. Call updateDisplayState(force: true) at the end of loop() (success and error branches) and cancelActiveTempBasal(). DIY divergence from tidepool/Loop. See memory/divergence_ns_post_dose_decision.md. Original NS pairing logic introduced in NightscoutService commit 08abe274 (2022-07-18) assumed a separate post-dose decision; later refactoring consolidated it into the "loop" decision, breaking the pairing for non-bolus paths.
ResizeablePicker was the only cross-module use of LoopKitUI's ResizeablePicker (which Tidepool keeps internal-only). Replacing it with a standard Picker(.wheel) here means LoopKit no longer needs DIY-only public modifiers on ResizeablePicker — eliminating a small but ongoing DIY divergence in LoopKitUI.
Bug: lock-screen Live Activity preview was showing raw Swift debug
output like 'Optional(LoopKit.PresetSymbol(symbolType: ..., value:
"figure.outdoor.cycle"))' above the preset name, because
TemporaryScheduleOverride.getTitle() was interpolating preset.symbol
directly:
return "\(preset.symbol) \(preset.name)"
preset.symbol is Optional<PresetSymbol> (a struct introduced by the
2026-03-10 tidepool sync — wraps an SF Symbol name with a tint), not a
String, so Swift's default Optional interpolation produced the debug
dump.
Fix:
- Add iconSystemSymbolName: String? to the Preset Codable struct in
GlucoseActivityAttributes (with backward-compatible decoder).
- Replace getTitle() -> String with liveActivityTitleAndSymbol() ->
(title, systemSymbolName?). Emoji symbols are folded inline into the
title (they render fine as text); .systemImage symbols are returned as
a separate SF Symbol name; .image (asset) symbols can't be loaded from
the widget bundle so we render the name without an icon. Pre-meal
preset also gets a fork.knife icon.
- In ChartView, render the preset label as
Text(Image(systemName: iconSystemSymbolName)) + Text(" ") + Text(title)
when a symbol is present, else just Text(title).
… y-axis labels The chart's y-axis labels (175/150/125/100) render on the right side of the plot, but the preset-name label (e.g. '🚴 Biking') was also at top-trailing, so they crowded the same top-right corner. Switched the ZStack alignment to .leading and updated the label padding from trailing→leading so the preset sits in the empty top-left area.
Use .chartPlotStyle's overlay (alignment: .topTrailing) to render the preset label inside the plot rectangle rather than via an outer ZStack. The plot area excludes axis labels, so right-aligning inside it puts the label flush with the right edge of the chart without overlapping the y-axis numbers (175/150/125/100) that render along the trailing axis. Removed the surrounding ZStack and the trailing/.top vs leading/.top alignment juggling — not needed anymore.
Moved the 'Live activity' NavigationLink out of AlertManagementView and into SettingsView's alertManagementSection, directly below the Alert Management row. Both now share a Section using the LargeButton style. The new Live Activity row uses 'rectangle.on.rectangle' as the icon and the descriptive text 'Lock Screen, Dynamic Island, and CarPlay display'. Rationale: Live Activity is an output/display concern, not an alert permission concern, so users were unlikely to look for it inside Alert Management. Surfacing it at the top level makes it discoverable.
…stic report Both fields are implicitly-unwrapped optionals that are guaranteed to be set by the time the diagnostic report runs; reflecting the Optional wrappers produced opaque "Optional(...)" lines that obscured the underlying state. Matches how the other manager fields above and below these lines are rendered.
The carb-effect chart on the Carb Absorption screen and the Favorite Foods insights screen lost their predicted carb-effect line in the Tidepool stateless-algorithm refactor. `dynamicGlucoseEffects(from: end, ...)` generated effects only from now+1h forward, but the chart's visible window ends at roughly now+1h — so the two ranges only touched at a single point and nothing rendered. Widen the output sampling window to `from: start` at both call sites (carb-absorption review and historical-charts data). The carb-absorption model itself is unchanged; only the sample window grows to span the chart. No dosing-path impact: the main Loop algorithm runs through LoopAlgorithm (SPM), not these UI-only helpers. Reported by @marionbarker in LoopKit/LoopWorkspace#213.
Marion's LoopKit#2399 (b6e8841) added submodule branch+SHA to the build-details section of the diagnostic report. The script and BuildDetails.submodules accessor survived the Tidepool merges, but the report-builder block itself was relocated from DeviceDataManager.swift to LoopAppManager in Tidepool's refactor, and the merge kept Tidepool's older shape — so the consumer of .submodules was effectively dropped. Port the original change into generateDiagnosticReport(): - drop the now-redundant Loop-submodule gitRevision/gitBranch lines - rename workspaceGit{Revision,Branch} to "Workspace SHA/branch" - append the submodule list (alphabetized, "name: branch, sha")
Adds an `external` case to the bolus event type so manually-entered doses appear as "External Insulin" in the delivery log instead of being lumped in with corrections. The event details screen gains a destructive Delete button (with confirmation) that removes the dose via DoseStore.deleteDose when the underlying DoseEntry is manually entered.
Closed
# Conflicts: # Loop.xcodeproj/project.pbxproj # WatchApp/Info.plist
added 7 commits
May 20, 2026 16:49
The dev merge resurrected the legacy WKWatchKitApp key alongside DIY's modern WKApplication single-target watch app, causing 'WatchKit App doesn't contain any WatchKit Extensions' on archive/device builds. Keep WKApplication + dev's WKSupportsLiveActivityLaunchAttributeTypes; remove WKWatchKitApp.
New "Apple Health" settings row pushes a detail page showing the write/share authorization status (Allowed/Denied/Not Set) for glucose and insulin, with a warning indicator when sharing is denied. Read authorization is intentionally not reported by iOS, so the page explains that, notes Loop reads insulin data from other apps, and points the user at the Health app to review or change access (the app cannot re-prompt once a choice is made). Exposes DeviceDataManager.healthKitSharingStatus(for:) so the Settings layer can read per-type sharing authorization.
Adds FeatureFlags.doseDeletionEnabled (off by default). When enabled, the dose details screen offers a Delete action for any bolus/basal dose, not just external (manually-entered) ones. Deleting a Loop-recorded dose that still has active insulin (within the ~6h window) shows an extra confirmation warning that Loop may make up for the reduced active insulin by dosing more. External-dose deletion is unchanged and still always available.
updateDisplayState only ever advanced lastManualBolus to a newer bolus, so a deleted (or otherwise removed) bolus lingered in the status "Last Bolus" footer. Now reflect the most recent user-entered bolus actually present in the store, clearing/downgrading when it is gone, while still preserving a just-enacted bolus the store may not have persisted yet.
The Intents.intentdefinition variant group listed all 26 locales as children, but the sync's .strings cleanup dropped the PBXFileReference definitions for 22 of them (es, ru, en, it, fr, de, zh-Hans, nl, nb, pl, ja, pt-BR, vi, da, sv, fi, ro, tr, he, ar, sk, cs), leaving dangling children. Those locales' Intents.strings were never compiled, so Apple flagged missing localized descriptions for the NewCarbEntry and EnableOverridePreset custom intents across all of them. Re-add the file references (reusing the IDs the variant group already points at); the strings now bundle for every declared locale.
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.
Refreshed Tidepool → DIY sync from the
tidepool-sync/2026-05-11branch.This supersedes and replaces the previous Tidepool Merge PR (#2237), which is being closed in favor of this one.