@@ -111,7 +111,31 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
111111 private var shouldDisplayAccurateCarbEntryWarning = false {
112112 didSet {
113113 if shouldDisplayAccurateCarbEntryWarning != oldValue {
114- self . displayAccuracyWarning ( )
114+ if shouldDisplayOverrideEnabledWarning {
115+ self . displayWarningRow ( rowType: WarningRow . carbEntry, isAddingRow: shouldDisplayAccurateCarbEntryWarning)
116+ } else {
117+ self . shouldDisplayWarning = shouldDisplayAccurateCarbEntryWarning || shouldDisplayOverrideEnabledWarning
118+ }
119+ }
120+ }
121+ }
122+
123+ private var shouldDisplayOverrideEnabledWarning = false {
124+ didSet {
125+ if shouldDisplayOverrideEnabledWarning != oldValue {
126+ if shouldDisplayAccurateCarbEntryWarning {
127+ self . displayWarningRow ( rowType: WarningRow . override, isAddingRow: shouldDisplayOverrideEnabledWarning)
128+ } else {
129+ self . shouldDisplayWarning = shouldDisplayOverrideEnabledWarning || shouldDisplayAccurateCarbEntryWarning
130+ }
131+ }
132+ }
133+ }
134+
135+ private var shouldDisplayWarning = false {
136+ didSet {
137+ if shouldDisplayWarning != oldValue {
138+ self . displayWarning ( )
115139 }
116140 }
117141 }
@@ -183,18 +207,20 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
183207 override func viewDidAppear( _ animated: Bool ) {
184208 super. viewDidAppear ( animated)
185209
186- if shouldBeginEditingQuantity, let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . value. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ) as? DecimalTextFieldTableViewCell {
210+ if shouldBeginEditingQuantity, let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . value. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayWarning ) ) ) as? DecimalTextFieldTableViewCell {
187211 shouldBeginEditingQuantity = false
188212 cell. textField. becomeFirstResponder ( )
189213 }
190214
191- // check if the warning should be displayed
215+ // check if either warning should be displayed
192216 updateDisplayAccurateCarbEntryWarning ( )
217+ updateDisplayOverrideEnabledWarning ( )
193218
194219 // monitor loop updates
195220 notificationObservers += [
196221 NotificationCenter . default. addObserver ( forName: . LoopDataUpdated, object: deviceManager. loopManager, queue: nil ) { [ weak self] _ in
197222 self ? . updateDisplayAccurateCarbEntryWarning ( )
223+ self ? . updateDisplayOverrideEnabledWarning ( )
198224 }
199225 ]
200226 }
@@ -243,17 +269,46 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
243269 }
244270 }
245271
246- private func displayAccuracyWarning( ) {
272+ private func updateDisplayOverrideEnabledWarning( ) {
273+ DispatchQueue . main. async {
274+ if let managerSettings = self . deviceManager? . settings {
275+ if !managerSettings. scheduleOverrideEnabled ( at: Date ( ) ) {
276+ self . shouldDisplayOverrideEnabledWarning = false
277+ } else if let overrideSettings = managerSettings. scheduleOverride? . settings {
278+ self . shouldDisplayOverrideEnabledWarning = overrideSettings. effectiveInsulinNeedsScaleFactor != 1.0
279+ }
280+ }
281+ }
282+ }
283+
284+ private func displayWarning( ) {
247285 tableView. beginUpdates ( )
248286
249- if shouldDisplayAccurateCarbEntryWarning {
287+ if shouldDisplayWarning {
250288 tableView. insertSections ( [ Sections . warning. rawValue] , with: . top)
251289 } else {
252290 tableView. deleteSections ( [ Sections . warning. rawValue] , with: . top)
253291 }
254292
255293 tableView. endUpdates ( )
256294 }
295+
296+ private func displayWarningRow( rowType: WarningRow , isAddingRow: Bool = true ) {
297+ if shouldDisplayWarning {
298+ tableView. beginUpdates ( )
299+
300+ // If the accurate carb entry warning is shown, use the positional index of the given row type.
301+ let rowIndex = shouldDisplayAccurateCarbEntryWarning ? rowType. rawValue : 0
302+
303+ if isAddingRow {
304+ tableView. insertRows ( at: [ IndexPath ( row: rowIndex, section: Sections . warning. rawValue) ] , with: UITableView . RowAnimation. top)
305+ } else {
306+ tableView. deleteRows ( at: [ IndexPath ( row: rowIndex, section: Sections . warning. rawValue) ] , with: UITableView . RowAnimation. top)
307+ }
308+
309+ tableView. endUpdates ( )
310+ }
311+ }
257312
258313 // MARK: - Table view data source
259314 fileprivate enum Sections : Int , CaseIterable {
@@ -272,9 +327,9 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
272327 return displayWarningSection ? indexPath. section : indexPath. section + 1
273328 }
274329
275- static func numberOfRows( for section: Int , displayWarningSection : Bool ) -> Int {
276- if section == Sections . warning. rawValue && displayWarningSection {
277- return 1
330+ static func numberOfRows( for section: Int , displayCarbEntryWarning : Bool , displayOverrideWarning : Bool ) -> Int {
331+ if section == Sections . warning. rawValue && ( displayCarbEntryWarning || displayOverrideWarning ) {
332+ return displayCarbEntryWarning && displayOverrideWarning ? WarningRow . allCases . count : WarningRow . allCases . count - 1
278333 }
279334
280335 return DetailsRow . allCases. count
@@ -307,32 +362,54 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
307362 case foodType
308363 case absorptionTime
309364 }
365+
366+ fileprivate enum WarningRow : Int , CaseIterable {
367+ case carbEntry
368+ case override
369+ }
310370
311371 override func numberOfSections( in tableView: UITableView ) -> Int {
312- return Sections . numberOfSections ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning )
372+ return Sections . numberOfSections ( displayWarningSection: shouldDisplayWarning )
313373 }
314374
315375 override func tableView( _ tableView: UITableView , numberOfRowsInSection section: Int ) -> Int {
316- return Sections . numberOfRows ( for: section, displayWarningSection : shouldDisplayAccurateCarbEntryWarning)
376+ return Sections . numberOfRows ( for: section, displayCarbEntryWarning : shouldDisplayAccurateCarbEntryWarning, displayOverrideWarning : shouldDisplayOverrideEnabledWarning )
317377 }
318378
319379 override func tableView( _ tableView: UITableView , cellForRowAt indexPath: IndexPath ) -> UITableViewCell {
320- switch Sections ( rawValue: Sections . section ( for: indexPath, displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ! {
380+ switch Sections ( rawValue: Sections . section ( for: indexPath, displayWarningSection: shouldDisplayWarning ) ) ! {
321381 case . warning:
322382 let cell : UITableViewCell
323- if let existingCell = tableView. dequeueReusableCell ( withIdentifier: " CarbEntryAccuracyWarningCell " ) {
324- cell = existingCell
383+ // if no accurate carb entry warning should be shown OR if the given indexPath is for the override warning row, return the override warning cell.
384+ if !shouldDisplayAccurateCarbEntryWarning || WarningRow ( rawValue: indexPath. row) ! == . override {
385+ if let existingCell = tableView. dequeueReusableCell ( withIdentifier: " CarbEntryOverrideEnabledWarningCell " ) {
386+ cell = existingCell
387+ } else {
388+ cell = UITableViewCell ( style: . default, reuseIdentifier: " CarbEntryOverrideEnabledWarningCell " )
389+ }
390+
391+ cell. imageView? . image = UIImage ( systemName: " exclamationmark.triangle.fill " )
392+ cell. imageView? . tintColor = . warning
393+ cell. textLabel? . numberOfLines = 0
394+ cell. textLabel? . text = NSLocalizedString ( " An active override is modifying your carb ratio and insulin sensitivity. If you don't want this to affect your bolus calculation and projected glucose, consider turning off the override. " , comment: " Warning to ensure the carb entry is accurate during an override " )
395+ cell. textLabel? . font = UIFont . preferredFont ( forTextStyle: . caption1)
396+ cell. textLabel? . textColor = . secondaryLabel
397+ cell. isUserInteractionEnabled = false
325398 } else {
326- cell = UITableViewCell ( style: . default, reuseIdentifier: " CarbEntryAccuracyWarningCell " )
399+ if let existingCell = tableView. dequeueReusableCell ( withIdentifier: " CarbEntryAccuracyWarningCell " ) {
400+ cell = existingCell
401+ } else {
402+ cell = UITableViewCell ( style: . default, reuseIdentifier: " CarbEntryAccuracyWarningCell " )
403+ }
404+
405+ cell. imageView? . image = UIImage ( systemName: " exclamationmark.triangle.fill " )
406+ cell. imageView? . tintColor = . destructive
407+ cell. textLabel? . numberOfLines = 0
408+ cell. textLabel? . text = NSLocalizedString ( " Your glucose is rapidly rising. Check that any carbs you've eaten were logged. If you logged carbs, check that the time you entered lines up with when you started eating. " , comment: " Warning to ensure the carb entry is accurate " )
409+ cell. textLabel? . font = UIFont . preferredFont ( forTextStyle: . caption1)
410+ cell. textLabel? . textColor = . secondaryLabel
411+ cell. isUserInteractionEnabled = false
327412 }
328-
329- cell. imageView? . image = UIImage ( systemName: " exclamationmark.triangle.fill " )
330- cell. imageView? . tintColor = . destructive
331- cell. textLabel? . numberOfLines = 0
332- cell. textLabel? . text = NSLocalizedString ( " Your glucose is rapidly rising. Check that any carbs you've eaten were logged. If you logged carbs, check that the time you entered lines up with when you started eating. " , comment: " Warning to ensure the carb entry is accurate " )
333- cell. textLabel? . font = UIFont . preferredFont ( forTextStyle: . caption1)
334- cell. textLabel? . textColor = . secondaryLabel
335- cell. isUserInteractionEnabled = false
336413 return cell
337414 case . details:
338415 switch DetailsRow ( rawValue: indexPath. row) ! {
@@ -415,7 +492,7 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
415492 }
416493
417494 override func tableView( _ tableView: UITableView , willDisplay cell: UITableViewCell , forRowAt indexPath: IndexPath ) {
418- switch Sections ( rawValue: Sections . section ( for: indexPath, displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) {
495+ switch Sections ( rawValue: Sections . section ( for: indexPath, displayWarningSection: shouldDisplayWarning ) ) {
419496 case . details:
420497 switch DetailsRow ( rawValue: indexPath. row) ! {
421498 case . value, . date:
@@ -434,15 +511,15 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
434511 }
435512
436513 override func tableView( _ tableView: UITableView , titleForFooterInSection section: Int ) -> String ? {
437- return Sections . footer ( for: section, displayWarningSection: shouldDisplayAccurateCarbEntryWarning )
514+ return Sections . footer ( for: section, displayWarningSection: shouldDisplayWarning )
438515 }
439516
440517 override func tableView( _ tableView: UITableView , heightForHeaderInSection section: Int ) -> CGFloat {
441- return Sections . headerHeight ( for: section, displayWarningSection: shouldDisplayAccurateCarbEntryWarning )
518+ return Sections . headerHeight ( for: section, displayWarningSection: shouldDisplayWarning )
442519 }
443520
444521 override func tableView( _ tableView: UITableView , heightForFooterInSection section: Int ) -> CGFloat {
445- return Sections . footerHeight ( for: section, displayWarningSection: shouldDisplayAccurateCarbEntryWarning )
522+ return Sections . footerHeight ( for: section, displayWarningSection: shouldDisplayWarning )
446523 }
447524
448525 // MARK: - UITableViewDelegate
@@ -459,7 +536,7 @@ final class CarbEntryViewController: LoopChartsTableViewController, Identifiable
459536 case is FoodTypeShortcutCell :
460537 usesCustomFoodType = true
461538 shouldBeginEditingFoodType = true
462- tableView. reloadRows ( at: [ IndexPath ( row: DetailsRow . foodType. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ] , with: . none)
539+ tableView. reloadRows ( at: [ IndexPath ( row: DetailsRow . foodType. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayWarning ) ) ] , with: . none)
463540 default :
464541 break
465542 }
@@ -686,14 +763,14 @@ extension CarbEntryViewController: FoodTypeShortcutCellDelegate {
686763 tableView. beginUpdates ( )
687764 usesCustomFoodType = true
688765 shouldBeginEditingFoodType = true
689- tableView. reloadRows ( at: [ IndexPath ( row: DetailsRow . foodType. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ] , with: . fade)
766+ tableView. reloadRows ( at: [ IndexPath ( row: DetailsRow . foodType. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayWarning ) ) ] , with: . fade)
690767 tableView. endUpdates ( )
691768 }
692769
693770 if let absorptionTime = absorptionTime {
694771 self . absorptionTime = absorptionTime
695772
696- if let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . absorptionTime. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ) as? DateAndDurationTableViewCell {
773+ if let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . absorptionTime. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayWarning ) ) ) as? DateAndDurationTableViewCell {
697774 cell. duration = absorptionTime
698775 }
699776 }
@@ -705,7 +782,7 @@ extension CarbEntryViewController: FoodTypeShortcutCellDelegate {
705782
706783extension CarbEntryViewController : EmojiInputControllerDelegate {
707784 func emojiInputControllerDidAdvanceToStandardInputMode( _ controller: EmojiInputController ) {
708- if let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . foodType. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ) as? TextFieldTableViewCell , let textField = cell. textField as? CustomInputTextField , textField. customInput != nil {
785+ if let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . foodType. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayWarning ) ) ) as? TextFieldTableViewCell , let textField = cell. textField as? CustomInputTextField , textField. customInput != nil {
709786 let customInput = textField. customInput
710787 textField. customInput = nil
711788 textField. resignFirstResponder ( )
@@ -723,7 +800,7 @@ extension CarbEntryViewController: EmojiInputControllerDelegate {
723800 // only adjust the absorption time if it wasn't already set.
724801 absorptionTime = orderedAbsorptionTimes [ section]
725802
726- if let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . absorptionTime. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayAccurateCarbEntryWarning ) ) ) as? DateAndDurationTableViewCell {
803+ if let cell = tableView. cellForRow ( at: IndexPath ( row: DetailsRow . absorptionTime. rawValue, section: Sections . indexForDetailsSection ( displayWarningSection: shouldDisplayWarning ) ) ) as? DateAndDurationTableViewCell {
727804 cell. duration = orderedAbsorptionTimes [ section]
728805 }
729806 }
0 commit comments