Skip to content

Commit

Permalink
[LOOP-5055] Presets Training QA Feedback (#740)
Browse files Browse the repository at this point in the history
  • Loading branch information
Camji55 authored Jan 8, 2025
1 parent 39e7d86 commit c963f83
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 43 deletions.
8 changes: 4 additions & 4 deletions Loop.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@
7D7076631FE06EE4004AC8EA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7D7076651FE06EE4004AC8EA /* Localizable.strings */; };
7E69CFFC2A16A77E00203CBD /* ResetLoopManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E69CFFB2A16A77E00203CBD /* ResetLoopManager.swift */; };
8496F7312B5711C4003E672C /* ContentMargin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8496F7302B5711C4003E672C /* ContentMargin.swift */; };
84A7B5502D2D972C00B6D202 /* Image+Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A7B54F2D2D972C00B6D202 /* Image+Optional.swift */; };
84AA81D32A4A27A3000B658B /* LoopWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA81D22A4A27A3000B658B /* LoopWidgets.swift */; };
84AA81D62A4A28AF000B658B /* WidgetBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA81D52A4A28AF000B658B /* WidgetBackground.swift */; };
84AA81D82A4A2910000B658B /* StatusWidgetTimelimeEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AA81D72A4A2910000B658B /* StatusWidgetTimelimeEntry.swift */; };
Expand All @@ -269,7 +270,6 @@
84E8BBCA2CCA16290078E6CF /* PresetsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E8BBC92CCA16290078E6CF /* PresetsView.swift */; };
84E8BBCC2CCA16B30078E6CF /* PresetsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E8BBCB2CCA16B30078E6CF /* PresetsViewModel.swift */; };
84E8BBCE2CCA1E070078E6CF /* PresetsTrainingCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E8BBCD2CCA1E070078E6CF /* PresetsTrainingCard.swift */; };
84E8BBD02CCA279B0078E6CF /* Image+Exists.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E8BBCF2CCA27960078E6CF /* Image+Exists.swift */; };
84EC162E2C9115CA00D220C5 /* DIYLoopUnitTestPlan.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 84EC162D2C9115CA00D220C5 /* DIYLoopUnitTestPlan.xctestplan */; };
84F20DFB2D0A56CB0089DF02 /* PresetStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F20DFA2D0A56CB0089DF02 /* PresetStatsView.swift */; };
84F20DFD2D0B9C3A0089DF02 /* EditOverrideDurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F20DFC2D0B9C3A0089DF02 /* EditOverrideDurationView.swift */; };
Expand Down Expand Up @@ -1125,6 +1125,7 @@
80F864E52433BF5D0026EC26 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/InfoPlist.strings; sourceTree = "<group>"; };
840A2F0D2C0F978E003D5E90 /* LoopKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = LoopKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8496F7302B5711C4003E672C /* ContentMargin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentMargin.swift; sourceTree = "<group>"; };
84A7B54F2D2D972C00B6D202 /* Image+Optional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image+Optional.swift"; sourceTree = "<group>"; };
84AA81D22A4A27A3000B658B /* LoopWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoopWidgets.swift; sourceTree = "<group>"; };
84AA81D52A4A28AF000B658B /* WidgetBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WidgetBackground.swift; sourceTree = "<group>"; };
84AA81D72A4A2910000B658B /* StatusWidgetTimelimeEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusWidgetTimelimeEntry.swift; sourceTree = "<group>"; };
Expand All @@ -1150,7 +1151,6 @@
84E8BBC92CCA16290078E6CF /* PresetsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetsView.swift; sourceTree = "<group>"; };
84E8BBCB2CCA16B30078E6CF /* PresetsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetsViewModel.swift; sourceTree = "<group>"; };
84E8BBCD2CCA1E070078E6CF /* PresetsTrainingCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetsTrainingCard.swift; sourceTree = "<group>"; };
84E8BBCF2CCA27960078E6CF /* Image+Exists.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image+Exists.swift"; sourceTree = "<group>"; };
84EC162D2C9115CA00D220C5 /* DIYLoopUnitTestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = DIYLoopUnitTestPlan.xctestplan; sourceTree = "<group>"; };
84F20DFA2D0A56CB0089DF02 /* PresetStatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetStatsView.swift; sourceTree = "<group>"; };
84F20DFC2D0B9C3A0089DF02 /* EditOverrideDurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditOverrideDurationView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2124,7 +2124,6 @@
43E344A01B9E144300C85C07 /* Extensions */ = {
isa = PBXGroup;
children = (
84E8BBCF2CCA27960078E6CF /* Image+Exists.swift */,
A98556842493F901000FD662 /* AlertStore+SimulatedCoreData.swift */,
C1D289B422F90A52003FFBD9 /* BasalDeliveryState.swift */,
C1F2CAAB2B7A980600D7F581 /* BasalRelativeDose.swift */,
Expand Down Expand Up @@ -2165,6 +2164,7 @@
C13DA2AF24F6C7690098BB29 /* UIViewController.swift */,
430B29922041F5B200BA9F93 /* UserDefaults+Loop.swift */,
A9B607AF247F000F00792BE4 /* UserNotifications+Loop.swift */,
84A7B54F2D2D972C00B6D202 /* Image+Optional.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -3593,7 +3593,6 @@
E98A55EF24EDD6E60008715D /* DosingDecisionStoreProtocol.swift in Sources */,
B4001CEE28CBBC82002FB414 /* AlertManagementView.swift in Sources */,
E9C00EF524C623EF00628F35 /* LoopSettings+Loop.swift in Sources */,
84E8BBD02CCA279B0078E6CF /* Image+Exists.swift in Sources */,
4389916B1E91B689000EEF90 /* ChartSettings+Loop.swift in Sources */,
C178249A1E1999FA00D9D25C /* CaseCountable.swift in Sources */,
C1F2CAAC2B7A980600D7F581 /* BasalRelativeDose.swift in Sources */,
Expand Down Expand Up @@ -3702,6 +3701,7 @@
439706E622D2E84900C81566 /* PredictionSettingTableViewCell.swift in Sources */,
430D85891F44037000AF2D4F /* HUDViewTableViewCell.swift in Sources */,
43A51E211EB6DBDD000736CC /* LoopChartsTableViewController.swift in Sources */,
84A7B5502D2D972C00B6D202 /* Image+Optional.swift in Sources */,
8968B1122408B3520074BB48 /* UIFont.swift in Sources */,
84E8BBC42CC9B9890078E6CF /* AdjustedGlucoseRangeView.swift in Sources */,
84C170EF2CCA37680098E52F /* PresetCard.swift in Sources */,
Expand Down
21 changes: 0 additions & 21 deletions Loop/Extensions/Image+Exists.swift

This file was deleted.

20 changes: 20 additions & 0 deletions Loop/Extensions/Image+Optional.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Image+Optional.swift
// Loop
//
// Created by Cameron Ingham on 1/7/25.
// Copyright © 2025 LoopKit Authors. All rights reserved.
//

import SwiftUI

// Since this `Image` initializer provides a view even if the asset is not found in the bundle, it can double the spacing between adjacent elements in a `VStack`, `HStack`, etc.
extension Image {
init?(_ name: String, bundle: Bundle? = nil) {
if let _ = UIImage(named: name, in: bundle, with: nil) {
self = Image(name, bundle: bundle)
} else {
return nil
}
}
}
50 changes: 46 additions & 4 deletions Loop/View Models/PresetsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,53 @@ enum SelectablePreset: Hashable, Identifiable {
public class PresetsViewModel {

// MARK: Training
@ObservationIgnored @AppStorage("hasCompletedPresetsTraining") var hasCompletedTraining: Bool = false
@ObservationIgnored @AppStorage("presetsSortOrder") var selectedSortOption: PresetSortOption = .name
@ObservationIgnored @AppStorage("presetsSortDirectionReversed") var presetsSortAscending: Bool = true

// This double property is needed to allow AppStorage to be observed
@ObservationIgnored @AppStorage("hasCompletedPresetsTraining") private var _hasCompletedTraining: Bool = false
@ObservationIgnored
var hasCompletedTraining: Bool {
get {
access(keyPath: \.hasCompletedTraining)
return _hasCompletedTraining
}
set {
withMutation(keyPath: \.hasCompletedTraining) {
_hasCompletedTraining = newValue
}
}
}

// This double property is needed to allow AppStorage to be observed
@ObservationIgnored @AppStorage("presetsSortOrder") private var _selectedSortOption: PresetSortOption = .name
@ObservationIgnored
var selectedSortOption: PresetSortOption {
get {
access(keyPath: \.selectedSortOption)
return _selectedSortOption
}
set {
withMutation(keyPath: \.selectedSortOption) {
_selectedSortOption = newValue
}
}
}

// This double property is needed to allow AppStorage to be observed
@ObservationIgnored @AppStorage("presetsSortDirectionReversed") private var _presetsSortAscending: Bool = true
@ObservationIgnored
var presetsSortAscending: Bool {
get {
access(keyPath: \.selectedSortOption)
return _presetsSortAscending
}
set {
withMutation(keyPath: \.selectedSortOption) {
_presetsSortAscending = newValue
}
}
}

@ObservationIgnored var correctionRangeOverrides: CorrectionRangeOverrides?
var correctionRangeOverrides: CorrectionRangeOverrides?

let temporaryPresetsManager: TemporaryPresetsManager

Expand Down
4 changes: 1 addition & 3 deletions Loop/Views/Presets/Components/PresetDetentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct PresetDetentView: View {
case .end:
Button("End Preset") {
viewModel.endPreset()
dismiss()
}
.buttonStyle(ActionButtonStyle(.destructive))

Expand Down Expand Up @@ -143,8 +144,5 @@ struct PresetDetentView: View {
.padding(16)
.presentationHuggingDetent()
}
.onChange(of: viewModel.activePreset) { _, _ in
dismiss()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ struct PresetsTrainingContentContainerView: View {
} message: {
Text("Ending now will require you to restart training before creating new presets.\n\nDo you want to end training?", comment: "End presets training alert message")
}

}

private func content(withSpacer: Bool = false) -> some View {
Expand Down Expand Up @@ -101,5 +100,6 @@ struct PresetsTrainingContentContainerView: View {
}
}
.padding(.horizontal, 16)
.padding(.bottom)
}
}
5 changes: 3 additions & 2 deletions Loop/Views/Presets/PresetsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ struct PresetsView: View {
NavigationView {
ScrollView {
VStack(spacing: 20) {

if !viewModel.hasCompletedTraining {
PresetsTrainingCard(showTraining: $showTraining)
}
Expand Down Expand Up @@ -95,7 +94,9 @@ struct PresetsView: View {

Button(action: {}) {
Image(systemName: "plus")
}.disabled(!viewModel.hasCompletedTraining)
}
// .disabled(!viewModel.hasCompletedTraining)
.disabled(true) // [LOOP-5055] Revert this after phase 1 of presets 2.0. https://tidepool.atlassian.net/browse/LOOP-5055?focusedCommentId=61276
}

LazyVStack(spacing: 12) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ struct CreatingYourOwnPresetsContentView: View {

Text("You can manage all presets by tapping the Presets button on the toolbar.", comment: "Creating your own presets training content, managing presets, paragraph 1")

if Image.imageExists("PresetsTraining1") {
Image("PresetsTraining1")
if let image = Image("PresetsTraining1") {
image
.resizable()
.aspectRatio(contentMode: .fill)
.accessibilityHidden(true)
Expand All @@ -53,8 +53,8 @@ struct CreatingYourOwnPresetsContentView: View {
Text("(if applicable) the glucose chart will show your adjusted correction range", comment: "Creating your own presets training content, managing presets, paragraph 2, bullet 3")
}

if Image.imageExists("PresetsTraining2") {
Image("PresetsTraining2")
if let image = Image("PresetsTraining2") {
image
.resizable()
.aspectRatio(contentMode: .fill)
.accessibilityHidden(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ struct HowTheyWorkContentView: View {
Text("Adjusting Overall Insulin", comment: "How presets work training content, adjusting overall insulin, subtitle 1")
.font(.title2.bold())

if Image.imageExists("PresetsTraining3") {
Image("PresetsTraining3")
if let image = Image("PresetsTraining3") {
image
.resizable()
.aspectRatio(contentMode: .fill)
.accessibilityHidden(true)
Expand Down Expand Up @@ -93,8 +93,8 @@ struct HowTheyWorkContentView: View {
Text("Adjusting the Correction Range", comment: "How presets work training content, adjusting correction range, subtitle 1")
.font(.title2.bold())

if Image.imageExists("PresetsTraining4") {
Image("PresetsTraining4")
if let image = Image("PresetsTraining4") {
image
.resizable()
.aspectRatio(contentMode: .fill)
.accessibilityHidden(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ struct PresetsAndIllnessContentView: View {
@ViewBuilder
var stepOneView: some View {
Text("Physical stressors can cause your glucose to rise and sickness is a common example. Your healthcare provider can help you make a personal plan for sickness. The following is one example of using presets to manage an illness.", comment: "Presets and illness training content, paragraph 1")
.fixedSize(horizontal: false, vertical: true)
.bold()

Text("Let’s imagine Paloma Porpoise notices her glucose is higher than usual and wants to create a preset to help keep her glucose in range while she is sick.", comment: "Presets and illness training content, paragraph 2")
.fixedSize(horizontal: false, vertical: true)

TherapySettingsExampleView(
title: NSLocalizedString("Paloma’s Therapy Settings", comment: "Presets and illness training content, therapy settings example, title"),
Expand Down Expand Up @@ -115,6 +117,7 @@ struct PresetsAndIllnessContentView: View {
.font(.title2.bold())

Text("Let’s imagine Paloma decides to eat a meal of 31g carbs. How will her preset impact her bolus recommendation?", comment: "Presets and illness training content, impact on bolusing, paragraph 1")
.fixedSize(horizontal: false, vertical: true)
}

Text("While a preset is ON, the modified basal rates, carb ratio and insulin sensitivity factor (ISF) are applied for every bolus.", comment: "Presets and illness training content, impact on bolusing, paragraph 2")
Expand Down

0 comments on commit c963f83

Please sign in to comment.