Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Add home screen risk cell update button countdown #866

Merged
merged 10 commits into from Jul 9, 2020
Expand Up @@ -73,18 +73,28 @@ final class HomeHighRiskCellConfigurator: HomeRiskLevelCellConfigurator {
cell.configureRiskViews(cellConfigurators: itemCellConfigurators)
cell.configureBackgroundColor(color: color)

let intervalString = "\(validityDuration)"
let intervalTitle = String(format: AppStrings.Home.riskCardIntervalUpdateTitle, intervalString)
let intervalTitle = String(format: AppStrings.Home.riskCardIntervalUpdateTitle, "\(validityDuration)")
cell.configureDetectionIntervalLabel(
text: intervalTitle,
isHidden: detectionIntervalLabelHidden
)


configureButton(for: cell)
setupAccessibility(cell)
}

override func configureButton(for cell: RiskLevelCollectionViewCell) {
let buttonTitle: String
if isLoading {
buttonTitle = AppStrings.Home.riskCardStatusCheckButton
} else {
let intervalDisabledButtonTitle = String(format: AppStrings.Home.riskCardIntervalDisabledButtonTitle, intervalString)
let intervalDisabledButtonTitle: String
johannesrohwer marked this conversation as resolved.
Show resolved Hide resolved
if let timeUntilUpdate = timeUntilUpdate {
intervalDisabledButtonTitle = String(format: AppStrings.ExposureDetection.refreshIn, timeUntilUpdate)
} else {
intervalDisabledButtonTitle = String(format: AppStrings.Home.riskCardIntervalDisabledButtonTitle, "\(validityDuration)")
}
buttonTitle = isButtonEnabled ? AppStrings.Home.riskCardHighButton : intervalDisabledButtonTitle
}
cell.configureUpdateButton(
Expand All @@ -93,7 +103,5 @@ final class HomeHighRiskCellConfigurator: HomeRiskLevelCellConfigurator {
isHidden: isButtonHidden,
accessibilityIdentifier: AccessibilityIdentifiers.Home.riskCardIntervalUpdateTitle
)

setupAccessibility(cell)
}
}
Expand Up @@ -108,18 +108,27 @@ final class HomeLowRiskCellConfigurator: HomeRiskLevelCellConfigurator {
cell.configureRiskViews(cellConfigurators: itemCellConfigurators)
cell.configureBackgroundColor(color: color)

let intervalString = "\(detectionInterval)"
let intervalTitle = String(format: AppStrings.Home.riskCardIntervalUpdateTitle, intervalString)
let intervalTitle = String(format: AppStrings.Home.riskCardIntervalUpdateTitle, "\(detectionInterval)")
cell.configureDetectionIntervalLabel(
text: intervalTitle,
isHidden: detectionIntervalLabelHidden
)

configureButton(for: cell)
setupAccessibility(cell)
}

override func configureButton(for cell: RiskLevelCollectionViewCell) {
let buttonTitle: String
if isLoading {
buttonTitle = AppStrings.Home.riskCardStatusCheckButton
} else {
let intervalDisabledButtonTitle = String(format: AppStrings.Home.riskCardIntervalDisabledButtonTitle, intervalString)
let intervalDisabledButtonTitle: String
johannesrohwer marked this conversation as resolved.
Show resolved Hide resolved
if let timeUntilUpdate = timeUntilUpdate {
intervalDisabledButtonTitle = String(format: AppStrings.ExposureDetection.refreshIn, timeUntilUpdate)
} else {
intervalDisabledButtonTitle = String(format: AppStrings.Home.riskCardIntervalDisabledButtonTitle, "\(detectionInterval)")
}
buttonTitle = isButtonEnabled ? AppStrings.Home.riskCardLowButton : intervalDisabledButtonTitle
}
cell.configureUpdateButton(
Expand All @@ -128,7 +137,5 @@ final class HomeLowRiskCellConfigurator: HomeRiskLevelCellConfigurator {
isHidden: isButtonHidden,
accessibilityIdentifier: AccessibilityIdentifiers.Home.riskCardIntervalUpdateTitle
)

setupAccessibility(cell)
}
}
Expand Up @@ -29,6 +29,7 @@ class HomeRiskLevelCellConfigurator: HomeRiskCellConfigurator {
var isButtonHidden: Bool
var detectionIntervalLabelHidden: Bool
var lastUpdateDate: Date?
var timeUntilUpdate: String?

private static let lastUpdateDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
Expand Down Expand Up @@ -109,8 +110,11 @@ class HomeRiskLevelCellConfigurator: HomeRiskCellConfigurator {
cell.bodyLabel.accessibilityIdentifier = AccessibilityIdentifiers.RiskCollectionViewCell.bodyLabel
cell.detectionIntervalLabel.accessibilityIdentifier = AccessibilityIdentifiers.RiskCollectionViewCell.detectionIntervalLabel
cell.updateButton.accessibilityIdentifier = AccessibilityIdentifiers.RiskCollectionViewCell.updateButton

}

/// Convenience method that can be overwritten to configure the button without running the full configure(_:) method.
/// This is handy when very frequent updates such as the update countdown are applied to the button.
func configureButton(for cell: RiskLevelCollectionViewCell) { }
melloskitten marked this conversation as resolved.
Show resolved Hide resolved
}

extension HomeRiskLevelCellConfigurator: RiskLevelCollectionViewCellDelegate {
Expand Down
31 changes: 31 additions & 0 deletions src/xcode/ENA/ENA/Source/Scenes/Home/HomeInteractor.swift
Expand Up @@ -19,6 +19,8 @@ import ExposureNotification
import Foundation
import UIKit

// swiftlint:disable file_length

final class HomeInteractor: RequiresAppDependencies {
typealias SectionDefinition = (section: HomeViewController.Section, cellConfigurators: [CollectionViewCellConfiguratorAny])
typealias SectionConfiguration = [SectionDefinition]
Expand All @@ -42,6 +44,7 @@ final class HomeInteractor: RequiresAppDependencies {
) {
didSet {
homeViewController.setStateOfChildViewControllers()
scheduleCountdownTimer()
buildSections()
}
}
Expand All @@ -64,6 +67,7 @@ final class HomeInteractor: RequiresAppDependencies {
private var testResultConfigurator = HomeTestResultCellConfigurator()
private var riskLevelConfigurator: HomeRiskLevelCellConfigurator?
private var inactiveConfigurator: HomeInactiveRiskCellConfigurator?
private var countdownTimer: CountdownTimer?

private(set) var testResult: TestResult?

Expand Down Expand Up @@ -427,3 +431,30 @@ extension HomeInteractor {
homeViewController.showExposureNotificationSetting()
}
}

// MARK: - CountdownTimerDelegate methods.
johannesrohwer marked this conversation as resolved.
Show resolved Hide resolved

/// The `CountdownTimerDelegate` is used to update the remaining time that is shown on the risk cell button until a manual refresh is allowed.
extension HomeInteractor: CountdownTimerDelegate {
private func scheduleCountdownTimer() {
let nextUpdate = riskProvider.nextExposureDetectionDate()
countdownTimer = CountdownTimer(countdownTo: nextUpdate)
countdownTimer?.delegate = self
countdownTimer?.start()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, the timer invalidate is only called in the CoutdownTimer class:

 deinit {
		timer?.invalidate()
		timer = nil
	} 

My question is, if the app goes background, the Timer still runs? What will happened if the user opens the App after 2 days?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for bringing this up, I discovered a bug in my implementation where the timer was not stopped as I expected due to a reference cycle. I added a manual invalidate() method to make sure the timer is handled correctly.
Regarding the opening of the app after some time has passed: The timer is guaranteed to be up-to-date since the scene delegate will trigger the updateExposureState() method of the home VC when the app comes into foreground.
To make sure the timer does not drain the users battery when the app goes into background, I added a few lines that invalidate the handler when the app goes into background.

}

func update(time: String) {
guard let indexPath = self.indexPathForRiskCell() else { return }
guard let cell = homeViewController.cellForItem(at: indexPath) as? RiskLevelCollectionViewCell else { return }

// We pass the time and let the configurator decide whether the button can be activated or not.
riskLevelConfigurator?.timeUntilUpdate = time
riskLevelConfigurator?.configureButton(for: cell)
}

func done() {
johannesrohwer marked this conversation as resolved.
Show resolved Hide resolved
// Reload action section to trigger full refresh of the risk cell configurator (updates
// the isButtonEnabled attribute).
self.reloadActionSection()
}
}
4 changes: 4 additions & 0 deletions src/xcode/ENA/ENA/Source/Scenes/Home/HomeViewController.swift
Expand Up @@ -345,6 +345,10 @@ final class HomeViewController: UIViewController {
collectionView.backgroundColor = .enaColor(for: .separator)
}
}

func cellForItem(at indexPath: IndexPath) -> UICollectionViewCell? {
return self.collectionView.cellForItem(at: indexPath)
}
}

// MARK: - Update test state.
Expand Down