Skip to content

Commit 8240def

Browse files
committed
[LOOP-4685] secret favorites foods feature unlock
1 parent efa7700 commit 8240def

File tree

7 files changed

+171
-103
lines changed

7 files changed

+171
-103
lines changed

Loop/Managers/SettingsManager.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ class SettingsManager {
109109
maximumBolus: latestSettings.maximumBolus,
110110
suspendThreshold: latestSettings.suspendThreshold,
111111
automaticDosingStrategy: latestSettings.automaticDosingStrategy,
112-
defaultRapidActingModel: latestSettings.defaultRapidActingModel?.presetForRapidActingInsulin)
112+
defaultRapidActingModel: latestSettings.defaultRapidActingModel?.presetForRapidActingInsulin,
113+
favoriteFoodsEnabled: latestSettings.favoriteFoodsEnabled)
113114
}
114115
}
115116

@@ -132,6 +133,7 @@ class SettingsManager {
132133
deviceToken: deviceToken,
133134
insulinType: deviceStatusProvider?.pumpManagerStatus?.insulinType,
134135
defaultRapidActingModel: newLoopSettings.defaultRapidActingModel.map(StoredInsulinModel.init),
136+
favoriteFoodsEnabled: newLoopSettings.favoriteFoodsEnabled,
135137
basalRateSchedule: newLoopSettings.basalRateSchedule,
136138
insulinSensitivitySchedule: newLoopSettings.insulinSensitivitySchedule,
137139
carbRatioSchedule: newLoopSettings.carbRatioSchedule,

Loop/View Controllers/CarbEntryViewController.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
173173
}()
174174

175175
private var lastContentHeight: CGFloat = 0
176+
177+
public weak var favoriteFoodsDelegate: FavoriteFoodsFeatureUnlockDelegate?
176178

177179
override func createChartsManager() -> ChartsManager {
178180
// Consider including a chart on this screen to demonstrate how absorption time affects prediction
@@ -552,6 +554,10 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
552554
guard let updatedEntry = updatedCarbEntry else {
553555
return
554556
}
557+
558+
if foodType == "🍞🥜🍫🥛" && quantity?.doubleValue(for: .gram()) == 63 {
559+
favoriteFoodsDelegate?.featureAvailabilityChanged()
560+
}
555561

556562
let viewModel = BolusEntryViewModel(
557563
delegate: deviceManager,
@@ -784,3 +790,7 @@ extension CarbEntryViewController: EmojiInputControllerDelegate {
784790
extension DateAndDurationTableViewCell: NibLoadable {}
785791

786792
extension DateAndDurationSteppableTableViewCell: NibLoadable {}
793+
794+
protocol FavoriteFoodsFeatureUnlockDelegate: AnyObject {
795+
func featureAvailabilityChanged()
796+
}

Loop/View Controllers/StatusTableViewController.swift

Lines changed: 141 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -271,22 +271,40 @@ final class StatusTableViewController: LoopChartsTableViewController {
271271
private func setupToolbarItems() {
272272
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
273273
let carbs = UIBarButtonItem(image: UIImage(named: "carbs"), style: .plain, target: self, action: #selector(userTappedAddCarbs))
274-
let meals = UIBarButtonItem(image: UIImage(named: "meals"), style: .plain, target: self, action: #selector(presentMealsScreen))
275274
let bolus = UIBarButtonItem(image: UIImage(named: "bolus"), style: .plain, target: self, action: #selector(presentBolusScreen))
276-
let presets = createPresetsButtonItem()
277275
let settings = UIBarButtonItem(image: UIImage(named: "settings"), style: .plain, target: self, action: #selector(onSettingsTapped))
278276

279-
toolbarItems = [
280-
carbs,
281-
space,
282-
meals,
283-
space,
284-
bolus,
285-
space,
286-
presets,
287-
space,
288-
settings
289-
]
277+
let favoriteFoodsEnabled = deviceManager.loopManager.settings.favoriteFoodsEnabled
278+
if favoriteFoodsEnabled {
279+
let meals = UIBarButtonItem(image: UIImage(named: "meals"), style: .plain, target: self, action: #selector(presentMealsScreen))
280+
let presets = createPresetsButtonItem(selected: false, isEnabled: true)
281+
toolbarItems = [
282+
carbs,
283+
space,
284+
meals,
285+
space,
286+
bolus,
287+
space,
288+
presets,
289+
space,
290+
settings
291+
]
292+
}
293+
else {
294+
let preMeal = createPreMealButtonItem(selected: false, isEnabled: true)
295+
let workout = createWorkoutButtonItem(selected: false, isEnabled: true)
296+
toolbarItems = [
297+
carbs,
298+
space,
299+
preMeal,
300+
space,
301+
bolus,
302+
space,
303+
workout,
304+
space,
305+
settings
306+
]
307+
}
290308
}
291309

292310
private func updateToolbarItems() {
@@ -295,18 +313,23 @@ final class StatusTableViewController: LoopChartsTableViewController {
295313
toolbarItems![0].accessibilityLabel = NSLocalizedString("Enter Carbs", comment: "The label of the carb entry button")
296314
toolbarItems![0].isEnabled = isPumpOnboarded
297315
toolbarItems![0].tintColor = UIColor.carbTintColor
298-
// TODO: - Fix localized string here
299-
toolbarItems![0].accessibilityLabel = NSLocalizedString("Enter Carbs", comment: "The label of the carb entry button")
300-
toolbarItems![2].isEnabled = isPumpOnboarded
301-
toolbarItems![2].tintColor = UIColor.carbTintColor
302316
toolbarItems![4].accessibilityLabel = NSLocalizedString("Bolus", comment: "The label of the bolus entry button")
303317
toolbarItems![4].isEnabled = isPumpOnboarded
304318
toolbarItems![4].tintColor = UIColor.insulinTintColor
305-
toolbarItems![6].accessibilityLabel = NSLocalizedString("Presets", comment: "The label of the presets button")
306-
toolbarItems![6].isEnabled = isPumpOnboarded
307-
toolbarItems![6].tintColor = UIColor.presetTintColor
308319
toolbarItems![8].accessibilityLabel = NSLocalizedString("Settings", comment: "The label of the settings button")
309320
toolbarItems![8].tintColor = UIColor.secondaryLabel
321+
322+
let favoriteFoodsEnabled = deviceManager.loopManager.settings.favoriteFoodsEnabled
323+
if favoriteFoodsEnabled {
324+
toolbarItems![2] = createFavoriteFoodsButtonItem()
325+
326+
let selected = (preMealMode == true && preMealModeAllowed) || (workoutMode == true && workoutModeAllowed)
327+
toolbarItems![6] = createPresetsButtonItem(selected: selected, isEnabled: preMealModeAllowed || workoutModeAllowed)
328+
}
329+
else {
330+
toolbarItems![2] = createPreMealButtonItem(selected: preMealMode == true && preMealModeAllowed, isEnabled: preMealModeAllowed)
331+
toolbarItems![6] = createWorkoutButtonItem(selected: workoutMode == true && workoutModeAllowed, isEnabled: workoutModeAllowed)
332+
}
310333
}
311334

312335
public var basalDeliveryState: PumpManagerStatus.BasalDeliveryState? = nil {
@@ -837,35 +860,34 @@ final class StatusTableViewController: LoopChartsTableViewController {
837860
guard oldValue != preMealMode else {
838861
return
839862
}
840-
// updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingStatus.automaticDosingEnabled)
841-
842-
toolbarItems![6] = createPresetsButtonItem()
843-
844-
// updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingStatus.automaticDosingEnabled)
863+
updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingStatus.automaticDosingEnabled)
845864
}
846865
}
866+
private lazy var preMealModeAllowed: Bool = {
867+
onboardingManager.isComplete &&
868+
(automaticDosingStatus.automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled)
869+
&& deviceManager.loopManager.settings.preMealTargetRange != nil
870+
}()
847871

848872
private func updatePreMealModeAvailability(automaticDosingEnabled: Bool) {
849-
let allowed = onboardingManager.isComplete &&
873+
preMealModeAllowed = onboardingManager.isComplete &&
850874
(automaticDosingEnabled || !FeatureFlags.simpleBolusCalculatorEnabled)
851875
&& deviceManager.loopManager.settings.preMealTargetRange != nil
876+
updateToolbarItems()
852877
}
853878

854879
private var workoutMode: Bool? = nil {
855880
didSet {
856881
guard oldValue != workoutMode else {
857882
return
858883
}
859-
// if let workoutMode = workoutMode {
860-
// let allowed = onboardingManager.isComplete
861-
// toolbarItems![6] = createWorkoutButtonItem(selected: workoutMode, isEnabled: allowed)
862-
// } else {
863-
// toolbarItems![6].isEnabled = false
864-
// }
865-
866-
toolbarItems![6] = createPresetsButtonItem()
884+
workoutModeAllowed = workoutMode != nil && onboardingManager.isComplete
885+
updateToolbarItems()
867886
}
868887
}
888+
private lazy var workoutModeAllowed: Bool = {
889+
workoutMode != nil && onboardingManager.isComplete
890+
}()
869891

870892
// MARK: - Table view data source
871893

@@ -1375,7 +1397,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
13751397
hostingController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: navigationWrapper, action: #selector(dismissWithAnimation))
13761398
} else {
13771399
let carbEntryViewController = UIStoryboard(name: "Main", bundle: Bundle(for: AppDelegate.self)).instantiateViewController(withIdentifier: "CarbEntryViewController") as! CarbEntryViewController
1378-
1400+
carbEntryViewController.favoriteFoodsDelegate = self
13791401
carbEntryViewController.deviceManager = deviceManager
13801402
carbEntryViewController.defaultAbsorptionTimes = deviceManager.carbStore.defaultAbsorptionTimes
13811403
carbEntryViewController.preferredCarbUnit = deviceManager.carbStore.preferredUnit
@@ -1421,11 +1443,17 @@ final class StatusTableViewController: LoopChartsTableViewController {
14211443
deviceManager.analyticsServicesManager.didDisplayBolusScreen()
14221444
}
14231445

1424-
private func createPresetsButtonItem() -> UIBarButtonItem {
1425-
let selected = workoutMode == true || preMealMode == true
1426-
1446+
private func createFavoriteFoodsButtonItem() -> UIBarButtonItem {
1447+
let item = UIBarButtonItem(image: UIImage(named: "favorite-foods")!, style: .plain, target: self, action: #selector(presentMealsScreen))
1448+
item.accessibilityLabel = NSLocalizedString("Favorite Foods", comment: "The label of the favorite foods button")
1449+
1450+
item.tintColor = UIColor.carbTintColor
1451+
1452+
return item
1453+
}
1454+
1455+
private func createPresetsButtonItem(selected: Bool, isEnabled: Bool) -> UIBarButtonItem {
14271456
let item = UIBarButtonItem(image: UIImage.presetsImage(selected: selected)!, style: .plain, target: self, action: #selector(onPresetsTapped))
1428-
// MARK: - Needs localization
14291457
item.accessibilityLabel = NSLocalizedString("Presets", comment: "The label of the presets mode toggle button")
14301458

14311459
if selected {
@@ -1436,43 +1464,44 @@ final class StatusTableViewController: LoopChartsTableViewController {
14361464
}
14371465

14381466
item.tintColor = UIColor.presetTintColor
1467+
item.isEnabled = isEnabled
14391468

14401469
return item
14411470
}
14421471

1443-
// private func createPreMealButtonItem(selected: Bool, isEnabled: Bool) -> UIBarButtonItem {
1444-
// let item = UIBarButtonItem(image: UIImage.preMealImage(selected: selected), style: .plain, target: self, action: #selector(togglePreMealMode(_:)))
1445-
// item.accessibilityLabel = NSLocalizedString("Pre-Meal Targets", comment: "The label of the pre-meal mode toggle button")
1446-
//
1447-
// if selected {
1448-
// item.accessibilityTraits.insert(.selected)
1449-
// item.accessibilityHint = NSLocalizedString("Disables", comment: "The action hint of the workout mode toggle button when enabled")
1450-
// } else {
1451-
// item.accessibilityHint = NSLocalizedString("Enables", comment: "The action hint of the workout mode toggle button when disabled")
1452-
// }
1453-
//
1454-
// item.tintColor = UIColor.carbTintColor
1455-
// item.isEnabled = isEnabled
1456-
//
1457-
// return item
1458-
// }
1472+
private func createPreMealButtonItem(selected: Bool, isEnabled: Bool) -> UIBarButtonItem {
1473+
let item = UIBarButtonItem(image: UIImage.preMealImage(selected: selected), style: .plain, target: self, action: #selector(togglePreMealMode(_:)))
1474+
item.accessibilityLabel = NSLocalizedString("Pre-Meal Targets", comment: "The label of the pre-meal mode toggle button")
1475+
1476+
if selected {
1477+
item.accessibilityTraits.insert(.selected)
1478+
item.accessibilityHint = NSLocalizedString("Disables", comment: "The action hint of the workout mode toggle button when enabled")
1479+
} else {
1480+
item.accessibilityHint = NSLocalizedString("Enables", comment: "The action hint of the workout mode toggle button when disabled")
1481+
}
1482+
1483+
item.tintColor = UIColor.carbTintColor
1484+
item.isEnabled = isEnabled
1485+
1486+
return item
1487+
}
14591488

1460-
// private func createWorkoutButtonItem(selected: Bool, isEnabled: Bool) -> UIBarButtonItem {
1461-
// let item = UIBarButtonItem(image: UIImage.workoutImage(selected: selected), style: .plain, target: self, action: #selector(toggleWorkoutMode(_:)))
1462-
// item.accessibilityLabel = NSLocalizedString("Workout Targets", comment: "The label of the workout mode toggle button")
1463-
//
1464-
// if selected {
1465-
// item.accessibilityTraits.insert(.selected)
1466-
// item.accessibilityHint = NSLocalizedString("Disables", comment: "The action hint of the workout mode toggle button when enabled")
1467-
// } else {
1468-
// item.accessibilityHint = NSLocalizedString("Enables", comment: "The action hint of the workout mode toggle button when disabled")
1469-
// }
1470-
//
1471-
// item.tintColor = UIColor.glucoseTintColor
1472-
// item.isEnabled = isEnabled
1473-
//
1474-
// return item
1475-
// }
1489+
private func createWorkoutButtonItem(selected: Bool, isEnabled: Bool) -> UIBarButtonItem {
1490+
let item = UIBarButtonItem(image: UIImage.workoutImage(selected: selected), style: .plain, target: self, action: #selector(toggleWorkoutMode(_:)))
1491+
item.accessibilityLabel = NSLocalizedString("Workout Targets", comment: "The label of the workout mode toggle button")
1492+
1493+
if selected {
1494+
item.accessibilityTraits.insert(.selected)
1495+
item.accessibilityHint = NSLocalizedString("Disables", comment: "The action hint of the workout mode toggle button when enabled")
1496+
} else {
1497+
item.accessibilityHint = NSLocalizedString("Enables", comment: "The action hint of the workout mode toggle button when disabled")
1498+
}
1499+
1500+
item.tintColor = UIColor.glucoseTintColor
1501+
item.isEnabled = isEnabled
1502+
1503+
return item
1504+
}
14761505

14771506
@objc func onPresetsTapped() {
14781507
if preMealMode == true {
@@ -1495,6 +1524,15 @@ final class StatusTableViewController: LoopChartsTableViewController {
14951524
}
14961525

14971526
func presentPresetAlertController() {
1527+
guard workoutModeAllowed else {
1528+
presentPreMealModeAlertController()
1529+
return
1530+
}
1531+
guard preMealModeAllowed else {
1532+
presentWorkoutModeAlertController()
1533+
return
1534+
}
1535+
14981536
let vc = UIAlertController(presetTypeSelectionHandler: { [self] presetType in
14991537
switch presetType {
15001538
case .preMeal:
@@ -1509,15 +1547,15 @@ final class StatusTableViewController: LoopChartsTableViewController {
15091547
present(vc, animated: true, completion: nil)
15101548
}
15111549

1512-
// @IBAction func togglePreMealMode(_ sender: UIBarButtonItem) {
1513-
// if preMealMode == true {
1514-
// deviceManager.loopManager.mutateSettings { settings in
1515-
// settings.clearOverride(matching: .preMeal)
1516-
// }
1517-
// } else {
1518-
// presentPreMealModeAlertController()
1519-
// }
1520-
// }
1550+
@IBAction func togglePreMealMode(_ sender: UIBarButtonItem) {
1551+
if preMealMode == true {
1552+
deviceManager.loopManager.mutateSettings { settings in
1553+
settings.clearOverride(matching: .preMeal)
1554+
}
1555+
} else {
1556+
presentPreMealModeAlertController()
1557+
}
1558+
}
15211559

15221560
func presentPreMealModeAlertController() {
15231561
let vc = UIAlertController(premealDurationSelectionHandler: { duration in
@@ -1544,19 +1582,19 @@ final class StatusTableViewController: LoopChartsTableViewController {
15441582
present(vc, animated: true, completion: nil)
15451583
}
15461584

1547-
// @IBAction func toggleWorkoutMode(_ sender: UIBarButtonItem) {
1548-
// if workoutMode == true {
1549-
// deviceManager.loopManager.mutateSettings { settings in
1550-
// settings.clearOverride()
1551-
// }
1552-
// } else {
1553-
// if FeatureFlags.sensitivityOverridesEnabled {
1554-
// performSegue(withIdentifier: OverrideSelectionViewController.className, sender: toolbarItems![6])
1555-
// } else {
1556-
// presentWorkoutModeAlertController()
1557-
// }
1558-
// }
1559-
// }
1585+
@IBAction func toggleWorkoutMode(_ sender: UIBarButtonItem) {
1586+
if workoutMode == true {
1587+
deviceManager.loopManager.mutateSettings { settings in
1588+
settings.clearOverride()
1589+
}
1590+
} else {
1591+
if FeatureFlags.sensitivityOverridesEnabled {
1592+
performSegue(withIdentifier: OverrideSelectionViewController.className, sender: toolbarItems![6])
1593+
} else {
1594+
presentWorkoutModeAlertController()
1595+
}
1596+
}
1597+
}
15601598

15611599
func presentWorkoutModeAlertController() {
15621600
let vc = UIAlertController(workoutDurationSelectionHandler: { duration in
@@ -1675,7 +1713,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
16751713
}
16761714

16771715
private func automaticDosingStatusChanged(_ automaticDosingEnabled: Bool) {
1678-
// updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingEnabled)
1716+
updatePreMealModeAvailability(automaticDosingEnabled: automaticDosingEnabled)
16791717
hudView?.loopCompletionHUD.loopIconClosed = automaticDosingEnabled
16801718
hudView?.loopCompletionHUD.closedLoopDisallowedLocalizedDescription = deviceManager.closedLoopDisallowedLocalizedDescription
16811719
}
@@ -2282,3 +2320,12 @@ extension StatusTableViewController: ServicesViewModelDelegate {
22822320
show(settingsViewController, sender: self)
22832321
}
22842322
}
2323+
2324+
extension StatusTableViewController: FavoriteFoodsFeatureUnlockDelegate {
2325+
func featureAvailabilityChanged() {
2326+
deviceManager.loopManager.mutateSettings { settings in
2327+
settings.favoriteFoodsEnabled.toggle()
2328+
}
2329+
self.updateToolbarItems()
2330+
}
2331+
}

0 commit comments

Comments
 (0)