ソースを参照

Merge branch 'dev' of https://github.com/nightscout/Trio into feat/dev-eversense

Deniz Cengiz 1 ヶ月 前
コミット
b5a2945450

+ 0 - 11
.gitmodules

@@ -1,49 +1,38 @@
 [submodule "LoopKit"]
 	path = LoopKit
 	url = https://github.com/loopandlearn/LoopKit.git
-	branch = trio
 [submodule "CGMBLEKit"]
 	path = CGMBLEKit
 	url = https://github.com/loopandlearn/CGMBLEKit.git
-	branch = trio
 [submodule "dexcom-share-client-swift"]
 	path = dexcom-share-client-swift
 	url = https://github.com/loopandlearn/dexcom-share-client-swift.git
-	branch = trio
 [submodule "RileyLinkKit"]
 	path = RileyLinkKit
 	url = https://github.com/loopandlearn/RileyLinkKit
-	branch = trio
 [submodule "OmniBLE"]
 	path = OmniBLE
 	url = https://github.com/loopandlearn/OmniBLE.git
-	branch = trio
 [submodule "G7SensorKit"]
 	path = G7SensorKit
 	url = https://github.com/loopandlearn/G7SensorKit.git
-	branch = trio
 [submodule "OmniKit"]
 	path = OmniKit
 	url = https://github.com/loopandlearn/OmniKit.git
-	branch = trio
 [submodule "MinimedKit"]
 	path = MinimedKit
 	url = https://github.com/loopandlearn/MinimedKit.git
-	branch = trio
 [submodule "LibreTransmitter"]
 	path = LibreTransmitter
 	url = https://github.com/loopandlearn/LibreTransmitter.git
-	branch = trio
 [submodule "TidepoolService"]
 	path = TidepoolService
 	url = https://github.com/loopandlearn/TidepoolService.git
-	branch = trio
 [submodule "DanaKit"]
 	path = DanaKit
 	url = https://github.com/loopandlearn/DanaKit
 [submodule "MedtrumKit"]
 	path = MedtrumKit
-	branch = dev
 	url = https://github.com/loopandlearn/MedtrumKit
 [submodule "EversenseKit"]
 	path = EversenseKit

+ 1 - 1
CGMBLEKit

@@ -1 +1 @@
-Subproject commit 134396b96170d410b18f9699b92409bc6d35aedb
+Subproject commit ba5d0b7daf83d282b587c8ff0e835162b8c75846

+ 135 - 0
CONTRIBUTING.md

@@ -0,0 +1,135 @@
+# Contributing to Trio
+
+Thank you for your interest in contributing to Trio.
+
+Trio is a community effort, and contributions of all kinds are welcome. This document outlines some guidelines, good practices, and expectations for contributing to the project, with the goal of making collaboration and review as smooth as possible.
+
+Whether you are helping other users, improving documentation, translating the app, testing builds, reviewing code, or contributing new features and fixes, your work matters.
+
+## Ways to contribute
+
+There are many ways to support the Trio community:
+
+- **Help others** by answering questions and guiding users in support communities.
+- Improve the **documentation** by updating or expanding TrioDocs.
+- Improve the **app** by contributing code, fixes, features, or tests.
+- Help with **translation and localization** through Crowdin.
+- Support **testing and feedback** by validating changes and reporting issues clearly.
+
+### Pay it forward
+
+If Trio has helped you manage your diabetes successfully, consider paying it forward by helping others. Answering questions in [Discord](https://discord.triodocs.org) or [Facebook](https://facebook.triodocs.org) groups can make a real difference for someone getting started.
+
+### Translate
+
+Trio is translated into multiple languages to make it easier to understand and use around the world. Translation is managed through [Crowdin](https://crowdin.triodocs.org/) and does not require programming experience.
+
+If your preferred language is missing, or you would like to improve an existing translation, please sign up as a translator on [Crowdin](https://crowdin.com/project/trio).
+
+### Develop
+
+Do you work with Swift? UI/UX? Testing? API optimization? Data storage?
+
+Trio is a collaborative project, and contributions of all kinds are welcome. Whether you are writing code, improving the user experience, testing builds, helping with documentation, or contributing in other ways, your help matters.
+
+## General principles
+
+- Start small. Smaller, focused contributions are easier to review, test, and merge.
+- For larger changes or new features, open or reference an issue first so there is a clear place for discussion and progress tracking.
+- Reach out early if you are planning to work on something substantial, especially if it may overlap with work already in progress.
+- Keep discussions constructive, respectful, and focused on improving Trio for the community.
+- Remember that Trio is part of a wider open source AID ecosystem. Collaboration and maintainability matter just as much as shipping features.
+
+## Development guidelines
+
+### Coding conventions
+
+- Use Xcode and follow the existing formatting and style used throughout the codebase.
+- Keep indentation and formatting consistent in every file you change.
+- Format your code before committing.
+- Avoid unrelated formatting-only changes in files you are not otherwise modifying.
+- Prefer clear, readable code over clever or overly compact solutions.
+- Follow existing naming, file organization, and architectural patterns unless there is a good reason not to.
+
+### Strings and localization
+
+- Add new user-facing strings in the appropriate localization mechanism used by the app.
+- Provide English source strings only unless the contribution is specifically about translations.
+- Translation and localization for other languages should go through [Crowdin](https://crowdin.triodocs.org/).
+- Translations from shared pump managers, CGM managers and services are handled by the [Loop lokalise project](https://loopkit.github.io/loopdocs/faqs/app-translation/#code-translation).
+
+### Documentation
+
+- Update docstrings when your change affects setup, configuration, behavior, workflows, or troubleshooting.
+- Keep documentation changes clear and practical.
+- +1: Documentation contributions are just as valuable as code contributions.
+
+## Branches, commits, and pull requests
+
+### Getting started
+
+1. Fork the [Trio repository](https://github.com/nightscout/Trio) on GitHub.
+1. Create a separate branch for each feature or fix with an [appropriate name](#branch-names).
+1. Branch from the most recent appropriate development branch (typically `dev`).
+1. Commit your changes to your fork.
+1. When ready, open a pull request against the upstream repository (`nightscout/Trio`).
+
+### Before opening a pull request
+
+- Rebase or otherwise sync your branch with the latest target branch.
+- Make sure your change is focused and does not include unrelated edits.
+- Test your changes as thoroughly as you reasonably can.
+- Update relevant documentation when needed.
+- Double-check for debug code, commented-out code, accidental version changes, or temporary workarounds left behind.
+
+### Pull request guidance
+
+- Keep pull requests as small and focused as practical.
+- Use a clear title and description.
+- Explain **what** changed and **why**.
+- Link the relevant issue when applicable.
+- Mention any areas that need particular review attention.
+- Be open to feedback and follow-up changes during review.
+- Use AI tools, if at all, as a support for small, well-understood tasks rather than to generate large parts of a contribution
+- Do not submit AI-heavy or "vibe-coded" pull requests; we welcome thoughtful use of tooling, but contributions need to be intentionally designed.
+
+## Naming conventions
+
+### Branch names
+
+Use short, descriptive branch names that make the purpose of the change obvious. For example:
+
+- `fix/watchstate-sync`
+- `feature/onboarding-target-behavior`
+- `refactor/therapy-editor`
+
+### Pull request titles
+
+Use concise, descriptive pull request titles. Good titles usually start with the type of change, for example:
+
+- `Fix watch state sync timing issue`
+- `Add onboarding step for target behavior`
+- `Update build documentation`
+- `Refactor therapy editor validation`
+
+## Communication and coordination
+
+For new ideas, larger features, or work that may affect multiple parts of the app, **discuss it with the community first** — reach out to the contributor core on [Trio Discord](https://discord.triodocs.org/). This helps reduce duplicate work, avoid merge conflicts, and improve the final design.
+
+## Review expectations
+
+Please remember that Trio is maintained by contributors with limited time. Reviews may take time, and some pull requests may require iteration before they are ready to merge.
+
+To help keep reviews efficient:
+
+- Keep the scope narrow.
+- Explain your reasoning clearly.
+- Respond to review comments directly.
+- Avoid force-pushing large unexplained rewrites during active review unless necessary.
+- AI-assisted work is welcome for limited, well-understood tasks, but contributions should remain author-driven and must be code you fully understand, and can explain.
+
+We do not accept pull requests that are largely AI-generated or submitted without careful engineering judgment, testing, and alignment with Trio’s existing patterns.
+
+## Final note
+
+Trio exists because people choose to contribute their time, knowledge, and care to a shared effort. Thank you for helping improve the project and support the broader open source AID community.

+ 1 - 1
Config.xcconfig

@@ -19,7 +19,7 @@ TRIO_APP_GROUP_ID = group.org.nightscout.$(DEVELOPMENT_TEAM).trio.trio-app-group
 
 // The developers set the version numbers, please leave them alone
 APP_VERSION = 0.6.0
-APP_DEV_VERSION = 0.6.0.78
+APP_DEV_VERSION = 0.6.0.84
 APP_BUILD_NUMBER = 1
 COPYRIGHT_NOTICE =
 

+ 1 - 1
G7SensorKit

@@ -1 +1 @@
-Subproject commit 0c093050084b63d7af0dc99307dba09239eb3180
+Subproject commit 4d0780db06c7c95b3a3bf3cdb2f2838d521e411a

+ 1 - 1
LibreTransmitter

@@ -1 +1 @@
-Subproject commit 12dec3ce191afe761fd68a70172ef75638319e20
+Subproject commit 20f6d0e171450b294b202cefa8edaf2c5e4a5150

+ 1 - 1
MinimedKit

@@ -1 +1 @@
-Subproject commit 942996e3f53c4875553c9827aeee1799a8dbf434
+Subproject commit ba80a8f46aa6582818289e7457574017281351e6

+ 1 - 1
OmniBLE

@@ -1 +1 @@
-Subproject commit 3782c584fe800116b6e60754e3be3cd818e033ee
+Subproject commit b0b78e66a6962677970a00e5d37ae4157e548b8a

+ 1 - 1
OmniKit

@@ -1 +1 @@
-Subproject commit 1446be89bfab23ac021d3e22f03b34bda8ce30cf
+Subproject commit 38af22b3d36e05a4cdffb242a1a47b347a4031fc

ファイルの差分が大きいため隠しています
+ 35 - 35
README.md


+ 1 - 1
TidepoolService

@@ -1 +1 @@
-Subproject commit a10f9d3ba097daae85de61d4a5bca063f34d64dc
+Subproject commit 5f4927dcac2b17276776b83016896997001b1a67

+ 8 - 2
Trio/Sources/APS/OpenAPS/OpenAPS.swift

@@ -132,8 +132,14 @@ final class OpenAPS {
 
             return glucoseResults.map { glucose -> AlgorithmGlucose in
                 let glucoseValue: Int16
-                if shouldSmoothGlucose, !glucose.isManual, let smoothedGlucose = glucose.smoothedGlucose, smoothedGlucose != 0 {
-                    glucoseValue = smoothedGlucose.rounding(accordingToBehavior: roundingBehavior).int16Value
+                if shouldSmoothGlucose {
+                    if !glucose.isManual, let smoothedGlucose = glucose.smoothedGlucose, smoothedGlucose != 0 {
+                        glucoseValue = smoothedGlucose.rounding(accordingToBehavior: roundingBehavior).int16Value
+                    } else {
+                        // use the raw value = finger prick, so manual readings are always included for algorithm decision making
+                        // cf. https://github.com/nightscout/Trio/issues/1054
+                        glucoseValue = glucose.glucose
+                    }
                 } else {
                     glucoseValue = glucose.glucose
                 }

+ 25 - 16
Trio/Sources/Modules/Onboarding/View/Animations/LogoBurstSplash.swift

@@ -16,6 +16,8 @@ struct LogoBurstSplash<Content: View>: View {
     @State private var viewOpacity: Double = 1.0
     @State private var splashScale: CGFloat = 1.0
 
+    @Environment(\.accessibilityReduceMotion) var reduceMotion
+
     init(isActive: Binding<Bool>, @ViewBuilder content: () -> Content) {
         _isActive = isActive
         self.content = content()
@@ -58,32 +60,39 @@ struct LogoBurstSplash<Content: View>: View {
                             .scaleEffect(isPulsing ? 1.1 : logoScale)
                             .opacity(logoOpacity)
                             .rotationEffect(.degrees(logoRotation))
-                            .animation(.easeInOut(duration: 1.0), value: logoScale)
+                            .animation(reduceMotion ? nil : .easeInOut(duration: 1.0), value: logoScale)
                             .animation(.easeInOut(duration: 1.0), value: logoOpacity)
-                            .animation(.linear(duration: 2.0), value: logoRotation)
+                            .animation(reduceMotion ? nil : .linear(duration: 2.0), value: logoRotation)
                             .animation(
-                                .easeInOut(duration: 0.8).repeatForever(autoreverses: true),
+                                reduceMotion ? nil : .easeInOut(duration: 0.8).repeatForever(autoreverses: true),
                                 value: isPulsing
                             )
                     }
                     .scaleEffect(splashScale)
                     .opacity(viewOpacity)
                     .onAppear {
-                        shapes = BurstShape.createBurst(count: 250, in: geo.frame(in: .local))
-
-                        withAnimation {
-                            isPulsing = true
-                            logoOpacity = 1
+                        if reduceMotion {
+                            withAnimation(.easeInOut(duration: 1.0)) {
+                                logoOpacity = 1
+                            }
                             logoScale = 1
-                            logoRotation = 360
-                        }
+                        } else {
+                            shapes = BurstShape.createBurst(count: 250, in: geo.frame(in: .local))
+
+                            withAnimation(.easeInOut(duration: 1.0)) {
+                                isPulsing = true
+                                logoOpacity = 1
+                                logoScale = 1
+                                logoRotation = 360
+                            }
 
-                        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
-                            isPulsing = false
-                        }
+                            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+                                isPulsing = false
+                            }
 
-                        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
-                            exploded = true
+                            DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
+                                exploded = true
+                            }
                         }
 
                         DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
@@ -96,7 +105,7 @@ struct LogoBurstSplash<Content: View>: View {
                         DispatchQueue.main.asyncAfter(deadline: .now() + 2.8) {
                             withAnimation(.easeIn(duration: 0.6)) {
                                 viewOpacity = 0
-                                splashScale = 0.1
+                                if !reduceMotion { splashScale = 0.1 }
                             }
                         }
 

+ 9 - 0
Trio/Sources/Modules/Onboarding/View/Animations/PulsingLogoAnimation.swift

@@ -11,6 +11,7 @@ struct PulsingLogoAnimation: View {
     @State private var opacity = 0.0
     @State private var rotation = 0.0
     @State private var isPulsing = false
+    @Environment(\.accessibilityReduceMotion) var reduceMotion
 
     var body: some View {
         Image("trioCircledNoBackground")
@@ -22,6 +23,14 @@ struct PulsingLogoAnimation: View {
             .rotationEffect(.degrees(rotation))
             .scaleEffect(isPulsing ? 1.1 : 1.0)
             .onAppear {
+                if reduceMotion {
+                    scale = 1.0
+                    withAnimation(.easeInOut(duration: 1.0)) {
+                        opacity = 1.0
+                    }
+                    return
+                }
+
                 withAnimation(.easeInOut(duration: 1.0)) {
                     scale = 1.0
                     opacity = 1.0

+ 17 - 7
Trio/Sources/Modules/Onboarding/View/OnboardingRootView.swift

@@ -296,6 +296,19 @@ struct OnboardingStepContent: View {
     @Binding var currentTargetBehaviorSubstep: TargetBehaviorSubstep
     @Bindable var state: Onboarding.StateModel
     var navigationDirection: OnboardingNavigationDirection
+    @Environment(\.accessibilityReduceMotion) var reduceMotion
+
+    private var transition: AnyTransition {
+        if reduceMotion {
+            return .opacity
+        }
+        switch navigationDirection {
+        case .forward:
+            return .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))
+        case .backward:
+            return .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing))
+        }
+    }
 
     var body: some View {
         ScrollViewReader { scrollProxy in
@@ -377,11 +390,7 @@ struct OnboardingStepContent: View {
                                 CompletedStepView(isOnboardingCompleted: true, currentChapter: nil)
                             }
                         }
-                        .transition(
-                            navigationDirection == .forward
-                                ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading))
-                                : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing))
-                        )
+                        .transition(transition)
                         .padding(.horizontal)
                         .id(currentStep.id)
                     }
@@ -464,13 +473,14 @@ struct OnboardingNavigationButtons: View {
     @Bindable var state: Onboarding.StateModel
     var shouldDisableNextButton: Bool
     var navigationDirectionChanged: (OnboardingNavigationDirection) -> Void
+    @Environment(\.accessibilityReduceMotion) var reduceMotion
 
     var body: some View {
         HStack {
             if currentStep != .welcome {
                 Button(action: {
                     navigationDirectionChanged(.backward)
-                    withAnimation {
+                    withAnimation(reduceMotion ? .easeInOut(duration: 0.25) : .default) {
                         handleBackNavigation()
                     }
                 }) {
@@ -487,7 +497,7 @@ struct OnboardingNavigationButtons: View {
 
             Button(action: {
                 navigationDirectionChanged(.forward)
-                withAnimation {
+                withAnimation(reduceMotion ? .easeInOut(duration: 0.25) : .default) {
                     handleNextNavigation()
                 }
             }) {

+ 5 - 7
Trio/Sources/Services/AppVersionChecker/AppVersionChecker.swift

@@ -3,7 +3,7 @@ import UIKit
 // AppVersionChecker is a singleton responsible for checking the app's version status.
 // It fetches version data from remote sources (GitHub), caches the results, and notifies the user
 // if an update is available or if the current version is blacklisted.
-final class AppVersionChecker {
+@MainActor final class AppVersionChecker {
     // Shared singleton instance.
     static let shared = AppVersionChecker()
 
@@ -81,7 +81,7 @@ final class AppVersionChecker {
     //
     // - Parameter viewController: The UIViewController on which to present any alerts.
     func checkAndNotifyVersionStatus(in viewController: UIViewController) {
-        Task { @MainActor in
+        Task {
             let (latestVersion, isNewer, isBlacklisted) = await checkForNewVersion()
             let now = Date()
 
@@ -488,10 +488,8 @@ final class AppVersionChecker {
     // - title: The title text for the alert.
     // - message: The body message of the alert.
     private func showAlert(on viewController: UIViewController, title: String, message: String) {
-        DispatchQueue.main.async {
-            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
-            alert.addAction(UIAlertAction(title: "OK", style: .default))
-            viewController.present(alert, animated: true)
-        }
+        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
+        alert.addAction(UIAlertAction(title: "OK", style: .default))
+        viewController.present(alert, animated: true)
     }
 }

+ 2 - 1
Trio/Sources/Services/Network/TidepoolManager.swift

@@ -320,11 +320,12 @@ extension BaseTidepoolManager {
                                     .processTempBasalEvent(event, existingTempBasalEntries: existingTempBasalEntries)
                             )
                     case .bolus:
+                        guard let amount = event.amount else { return result }
                         let bolusDoseEntry = DoseEntry(
                             type: .bolus,
                             startDate: event.timestamp,
                             endDate: event.timestamp,
-                            value: Double(event.amount!),
+                            value: Double(amount),
                             unit: .units,
                             deliveredUnits: nil,
                             syncIdentifier: event.id,

+ 1 - 1
dexcom-share-client-swift

@@ -1 +1 @@
-Subproject commit 8c4f0edfe9356463c66a2e5dff9d00794291ebfd
+Subproject commit 875faf232bb3f13d619512f9e8b47a2d5acac433

+ 2 - 2
scripts/define_common_trio.sh

@@ -17,8 +17,8 @@
 #
 # The scrips in LoopWorkspace are used to update translations and make
 #   sure the loopandlearn branches are up to date
-# Even though MedtrumKit and EversenseKit are not yet part of dev
-#   it does no harm to update those repositories using this script
+# Even though EversenseKit is only found in a feature branch
+#   it does no harm to update extra repositories using this script
 TRIO_PROJECTS=( \
     loopandlearn:LoopKit:trio \
     loopandlearn:CGMBLEKit:dev \