Skip to content

Commit c3334fd

Browse files
author
Rick Pasetto
authored
LOOP-3647: Shows warning at top of home screen if CA or Notifications permissions are disabled (#420)
* LOOP-3647: Shows warning at top of home screen if CA or Notifications permissions are disabled * Cleaner impl of TempStatusCell * PR Feedback
1 parent 1839506 commit c3334fd

File tree

2 files changed

+75
-35
lines changed

2 files changed

+75
-35
lines changed

Loop/View Controllers/StatusTableViewController.swift

Lines changed: 69 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ final class StatusTableViewController: LoopChartsTableViewController {
3131
lazy var quantityFormatter: QuantityFormatter = QuantityFormatter()
3232

3333
var closedLoopStatus: ClosedLoopStatus!
34+
35+
let notificationsCriticalAlertPermissionsViewModel = NotificationsCriticalAlertPermissionsViewModel()
3436

3537
lazy private var cancellables = Set<AnyCancellable>()
3638

@@ -123,6 +125,20 @@ final class StatusTableViewController: LoopChartsTableViewController {
123125
addScenarioStepGestureRecognizers()
124126

125127
tableView.backgroundColor = .secondarySystemBackground
128+
129+
tableView.register(AlertPermissionsDisabledWarningCell.self, forCellReuseIdentifier: AlertPermissionsDisabledWarningCell.className)
130+
notificationsCriticalAlertPermissionsViewModel.$showWarning
131+
.receive(on: RunLoop.main)
132+
.sink { [weak self] showWarning in
133+
guard let self = self else { return }
134+
let isWarningVisible = self.tableView.numberOfRows(inSection: Section.alertPermissionsDisabledWarning.rawValue) != 0
135+
if !showWarning && isWarningVisible {
136+
self.tableView.deleteRows(at: [IndexPath(row: 0, section: Section.alertPermissionsDisabledWarning.rawValue)], with: .top)
137+
} else if showWarning && !isWarningVisible {
138+
self.tableView.insertRows(at: [IndexPath(row: 0, section: Section.alertPermissionsDisabledWarning.rawValue)], with: .top)
139+
}
140+
}
141+
.store(in: &cancellables)
126142
}
127143

128144
override func didReceiveMemoryWarning() {
@@ -141,6 +157,8 @@ final class StatusTableViewController: LoopChartsTableViewController {
141157
navigationController?.setNavigationBarHidden(true, animated: animated)
142158
navigationController?.setToolbarHidden(false, animated: animated)
143159

160+
notificationsCriticalAlertPermissionsViewModel.updateState()
161+
144162
updateBolusProgress()
145163
}
146164

@@ -572,23 +590,20 @@ final class StatusTableViewController: LoopChartsTableViewController {
572590
}
573591
}
574592

575-
private enum Section: Int {
576-
case hud = 0
593+
private enum Section: Int, CaseIterable {
594+
case alertPermissionsDisabledWarning
595+
case hud
577596
case status
578597
case charts
579-
580-
static let count = 3
581598
}
582599

583600
// MARK: - Chart Section Data
584601

585-
private enum ChartRow: Int {
586-
case glucose = 0
602+
private enum ChartRow: Int, CaseIterable {
603+
case glucose
587604
case iob
588605
case dose
589606
case cob
590-
591-
static let count = 4
592607
}
593608

594609
// MARK: Glucose
@@ -609,10 +624,8 @@ final class StatusTableViewController: LoopChartsTableViewController {
609624

610625
// MARK: - Loop Status Section Data
611626

612-
private enum StatusRow: Int {
627+
private enum StatusRow: Int, CaseIterable {
613628
case status = 0
614-
615-
static let count = 1
616629
}
617630

618631
private enum StatusRowMode {
@@ -791,22 +804,46 @@ final class StatusTableViewController: LoopChartsTableViewController {
791804
// MARK: - Table view data source
792805

793806
override func numberOfSections(in tableView: UITableView) -> Int {
794-
return Section.count
807+
return Section.allCases.count
795808
}
796809

797810
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
798811
switch Section(rawValue: section)! {
812+
case .alertPermissionsDisabledWarning:
813+
return notificationsCriticalAlertPermissionsViewModel.showWarning ? 1 : 0
799814
case .hud:
800815
return shouldShowHUD ? 1 : 0
801816
case .charts:
802-
return ChartRow.count
817+
return ChartRow.allCases.count
803818
case .status:
804-
return shouldShowStatus ? StatusRow.count : 0
819+
return shouldShowStatus ? StatusRow.allCases.count : 0
805820
}
806821
}
807822

823+
private class AlertPermissionsDisabledWarningCell: UITableViewCell {
824+
825+
override func updateConfiguration(using state: UICellConfigurationState) {
826+
super.updateConfiguration(using: state)
827+
let content = NSLocalizedString("Alerts Permissions Disabled", comment: "Warning text for when Notifications or Critical Alerts Permissions is disabled")
828+
var contentConfig = defaultContentConfiguration().updated(for: state)
829+
contentConfig.text = content
830+
contentConfig.textProperties.color = .red
831+
contentConfig.textProperties.font = .systemFont(ofSize: 15, weight: .semibold)
832+
contentConfig.textProperties.adjustsFontSizeToFitWidth = true
833+
contentConfig.image = UIImage(systemName: "exclamationmark.triangle.fill")?.withTintColor(.red)
834+
contentConfig.imageProperties.tintColor = .red
835+
contentConfiguration = contentConfig
836+
var backgroundConfig = backgroundConfiguration?.updated(for: state)
837+
backgroundConfig?.backgroundColor = .secondarySystemBackground
838+
backgroundConfiguration = backgroundConfig
839+
accessoryType = .disclosureIndicator
840+
}
841+
}
842+
808843
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
809844
switch Section(rawValue: indexPath.section)! {
845+
case .alertPermissionsDisabledWarning:
846+
return tableView.dequeueReusableCell(withIdentifier: AlertPermissionsDisabledWarningCell.className, for: indexPath) as! AlertPermissionsDisabledWarningCell
810847
case .hud:
811848
let cell = tableView.dequeueReusableCell(withIdentifier: HUDViewTableViewCell.className, for: indexPath) as! HUDViewTableViewCell
812849
hudView = cell.hudView
@@ -1004,7 +1041,7 @@ final class StatusTableViewController: LoopChartsTableViewController {
10041041
cell.setSubtitleLabel(label: nil)
10051042
}
10061043
}
1007-
case .hud, .status:
1044+
case .hud, .status, .alertPermissionsDisabledWarning:
10081045
break
10091046
}
10101047
}
@@ -1025,24 +1062,18 @@ final class StatusTableViewController: LoopChartsTableViewController {
10251062
case .iob, .dose, .cob:
10261063
return max(106, 0.21 * availableSize)
10271064
}
1028-
case .hud, .status:
1065+
case .hud, .status, .alertPermissionsDisabledWarning:
10291066
return UITableView.automaticDimension
10301067
}
10311068
}
10321069

10331070
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
10341071
switch Section(rawValue: indexPath.section)! {
1035-
case .charts:
1036-
switch ChartRow(rawValue: indexPath.row)! {
1037-
case .glucose:
1038-
if closedLoopStatus.isClosedLoop {
1039-
performSegue(withIdentifier: PredictionTableViewController.className, sender: indexPath)
1040-
}
1041-
case .iob, .dose:
1042-
performSegue(withIdentifier: InsulinDeliveryTableViewController.className, sender: indexPath)
1043-
case .cob:
1044-
performSegue(withIdentifier: CarbAbsorptionViewController.className, sender: indexPath)
1045-
}
1072+
case .alertPermissionsDisabledWarning:
1073+
tableView.deselectRow(at: indexPath, animated: true)
1074+
presentSettings()
1075+
case .hud:
1076+
break
10461077
case .status:
10471078
switch StatusRow(rawValue: indexPath.row)! {
10481079
case .status:
@@ -1118,8 +1149,17 @@ final class StatusTableViewController: LoopChartsTableViewController {
11181149
break
11191150
}
11201151
}
1121-
case .hud:
1122-
break
1152+
case .charts:
1153+
switch ChartRow(rawValue: indexPath.row)! {
1154+
case .glucose:
1155+
if closedLoopStatus.isClosedLoop {
1156+
performSegue(withIdentifier: PredictionTableViewController.className, sender: indexPath)
1157+
}
1158+
case .iob, .dose:
1159+
performSegue(withIdentifier: InsulinDeliveryTableViewController.className, sender: indexPath)
1160+
case .cob:
1161+
performSegue(withIdentifier: CarbAbsorptionViewController.className, sender: indexPath)
1162+
}
11231163
}
11241164
}
11251165

@@ -1319,7 +1359,6 @@ final class StatusTableViewController: LoopChartsTableViewController {
13191359
}
13201360

13211361
private func presentSettings() {
1322-
let notificationsCriticalAlertPermissionsViewModel = NotificationsCriticalAlertPermissionsViewModel()
13231362
let deletePumpDataFunc: () -> PumpManagerViewModel.DeleteTestingDataFunc? = { [weak self] in
13241363
(self?.deviceManager.pumpManager is TestingPumpManager) ? {
13251364
[weak self] in self?.deviceManager.deleteTestingPumpData()

Loop/View Models/NotificationsCriticalAlertPermissionsViewModel.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ public class NotificationsCriticalAlertPermissionsViewModel: ObservableObject {
3333
self.notificationsPermissionsGiven = notificationsPermissionsGiven
3434
self.criticalAlertsPermissionsGiven = criticalAlertsPermissionsGiven
3535

36-
NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: nil) {
37-
[weak self] _ in
38-
self?.updateState()
39-
}
36+
NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
37+
.sink { [weak self] _ in
38+
self?.updateState()
39+
}
40+
.store(in: &cancellables)
4041
updateState()
4142

4243
showWarningPublisher
@@ -45,7 +46,7 @@ public class NotificationsCriticalAlertPermissionsViewModel: ObservableObject {
4546
.store(in: &cancellables)
4647
}
4748

48-
private func updateState() {
49+
func updateState() {
4950
UNUserNotificationCenter.current().getNotificationSettings { settings in
5051
DispatchQueue.main.async {
5152
self.notificationsPermissionsGiven = settings.alertSetting == .enabled

0 commit comments

Comments
 (0)