Skip to content

Commit

Permalink
Added new UI for the "lock" screen, moved some code around to a prope…
Browse files Browse the repository at this point in the history
…r location
  • Loading branch information
bgoncal committed Nov 28, 2023
1 parent e051dd4 commit 63c9c46
Show file tree
Hide file tree
Showing 14 changed files with 672 additions and 405 deletions.
14 changes: 9 additions & 5 deletions HomeAssistant.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,8 @@
368048FC64829A4E4B82B631 /* Pods_watchOS_WatchExtension_Watch.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A90DD8FC6E4726B7E7187C59 /* Pods_watchOS_WatchExtension_Watch.framework */; };
38A4EBA18ADEEE555AD14F52 /* Pods-iOS-App-metadata.plist in Resources */ = {isa = PBXBuildFile; fileRef = 553A33E097387AA44265DB13 /* Pods-iOS-App-metadata.plist */; };
42BDF44B2A8EA5AB00562183 /* SecurityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42BDF44A2A8EA5AB00562183 /* SecurityViewController.swift */; };
42BDF4582A93FC2A00562183 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42BDF44D2A8EAD2700562183 /* AuthenticationService.swift */; };
42BDF4582A93FC2A00562183 /* BiometricsAuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42BDF44D2A8EAD2700562183 /* BiometricsAuthenticationService.swift */; };
42E9ADE42B064AF0003772BC /* BiometricsAuthenticationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42E9ADE32B064AF0003772BC /* BiometricsAuthenticationViewController.swift */; };
491E98FF25D543560077BBE3 /* LogbookEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491E98FE25D543560077BBE3 /* LogbookEntry.swift */; };
491E990025D543560077BBE3 /* LogbookEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 491E98FE25D543560077BBE3 /* LogbookEntry.swift */; };
539AA1653F4BCDB61FE7C696 /* Pods_iOS_Shared_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 213EF66D14F92AF8BF2E9E98 /* Pods_iOS_Shared_iOS.framework */; };
Expand Down Expand Up @@ -1569,10 +1570,11 @@
32DB55A889E2163C52C335D2 /* Pods-iOS-Shared-iOS-Tests-Shared.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-iOS-Shared-iOS-Tests-Shared.debug.xcconfig"; path = "Pods/Target Support Files/Pods-iOS-Shared-iOS-Tests-Shared/Pods-iOS-Shared-iOS-Tests-Shared.debug.xcconfig"; sourceTree = "<group>"; };
392B0C44197C98E2653932A5 /* Pods-iOS-Extensions-Matter-metadata.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "Pods-iOS-Extensions-Matter-metadata.plist"; path = "Pods/Pods-iOS-Extensions-Matter-metadata.plist"; sourceTree = "<group>"; };
3F4DFB087A3A43F9A526B851 /* Pods_iOS_Shared_iOS_Tests_Shared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_iOS_Shared_iOS_Tests_Shared.framework; sourceTree = BUILT_PRODUCTS_DIR; };
42805A132B0226050095414C /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Base; path = Base.lproj/AppIntentVocabulary.plist; sourceTree = "<group>"; };
420310522A852D1800A43E49 /* HomeAssistant.overrides.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = HomeAssistant.overrides.xcconfig; sourceTree = "<group>"; };
42805A132B0226050095414C /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Base; path = Base.lproj/AppIntentVocabulary.plist; sourceTree = "<group>"; };
42BDF44A2A8EA5AB00562183 /* SecurityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityViewController.swift; sourceTree = "<group>"; };
42BDF44D2A8EAD2700562183 /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; };
42BDF44D2A8EAD2700562183 /* BiometricsAuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BiometricsAuthenticationService.swift; sourceTree = "<group>"; };
42E9ADE32B064AF0003772BC /* BiometricsAuthenticationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BiometricsAuthenticationViewController.swift; sourceTree = "<group>"; };
479C2CCB032E2A0ECDE45B87 /* Pods-Tests-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests-App.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests-App/Pods-Tests-App.debug.xcconfig"; sourceTree = "<group>"; };
491E98FE25D543560077BBE3 /* LogbookEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogbookEntry.swift; sourceTree = "<group>"; };
553A33E097387AA44265DB13 /* Pods-iOS-App-metadata.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "Pods-iOS-App-metadata.plist"; path = "Pods/Pods-iOS-App-metadata.plist"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2946,7 +2948,8 @@
42BDF44C2A8EAD1900562183 /* LocalAuthentication */ = {
isa = PBXGroup;
children = (
42BDF44D2A8EAD2700562183 /* AuthenticationService.swift */,
42BDF44D2A8EAD2700562183 /* BiometricsAuthenticationService.swift */,
42E9ADE32B064AF0003772BC /* BiometricsAuthenticationViewController.swift */,
);
path = LocalAuthentication;
sourceTree = "<group>";
Expand Down Expand Up @@ -5800,6 +5803,7 @@
D0C88464211F33CE00CCB501 /* TokenManager.swift in Sources */,
B6B74CB6228397D100D58A68 /* WatchHelpers.swift in Sources */,
B6723344225DBACF0031D629 /* AuthRequestMessage.swift in Sources */,
42E9ADE42B064AF0003772BC /* BiometricsAuthenticationViewController.swift in Sources */,
D0DD2CEE213BCA8900C3D9F7 /* URL+Extensions.swift in Sources */,
11BA5EC92759AC0300FC40E8 /* XCGLogger+Export.swift in Sources */,
11B38EE4275C54A200205C7B /* FireEventIntentHandler.swift in Sources */,
Expand Down Expand Up @@ -5903,7 +5907,7 @@
1104FCBF2532755400B8BE34 /* WatchBackgroundRefreshScheduler.swift in Sources */,
11B38EE8275C54A200205C7B /* WidgetActionsIntentHandler.swift in Sources */,
B6D3B4ED225B26900082BB4F /* SensorContainer.swift in Sources */,
42BDF4582A93FC2A00562183 /* AuthenticationService.swift in Sources */,
42BDF4582A93FC2A00562183 /* BiometricsAuthenticationService.swift in Sources */,
11B38EEE275C54A200205C7B /* FocusStatusIntentHandler.swift in Sources */,
11C4628E24B128EF00031902 /* WebhookResponseUnhandled.swift in Sources */,
1121CD4C271295AD0071C2AA /* Style.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home-assistant-logomark-color-on-light.pdf",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
"idiom" : "universal"
}
],
"info" : {
Expand Down
128 changes: 65 additions & 63 deletions Sources/App/Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -547,41 +547,6 @@
</array>
</dict>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>WebView</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).WebViewSceneDelegate</string>
</dict>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SettingsSceneDelegate</string>
<key>UISceneConfigurationName</key>
<string>Settings</string>
</dict>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).AboutSceneDelegate</string>
<key>UISceneConfigurationName</key>
<string>About</string>
</dict>
</array>
</dict>
</dict>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>FIREBASE_ANALYTICS_COLLECTION_ENABLED</key>
Expand Down Expand Up @@ -623,6 +588,8 @@
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NFCReaderUsageDescription</key>
<string>Reading and writing NFC tags allows you to trigger events.</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
Expand All @@ -634,21 +601,36 @@
<string>_home-assistant._tcp</string>
<string>_matter._tcp</string>
</array>
<key>NSCameraUsageDescription</key>
<string>Take photos and send them to your Home Assistant server.</string>
<key>NSCrossWebsiteTrackingUsageDescription</key>
<string>Optionally enable cross-website tracking if your configuration requires it.</string>
<key>NSFaceIDUsageDescription</key>
<string>We use FaceID to protect the App access.</string>
<key>NSFocusStatusUsageDescription</key>
<string>Report your focus status as a sensor.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Locate and communicate with your Home Assistant instance.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We suggest selecting &quot;Always Allow&quot; for the best location experience.
Selecting &quot;Only While Using the App&quot; will disable iBeacons, geofences,
<string>We suggest selecting "Always Allow" for the best location experience.
Selecting "Only While Using the App" will disable iBeacons, geofences,
background location updates and accurate reporting.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>We always need access to your location for features like iBeacons, geofences,
background location updates and accurate reporting.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Only allowing location access while app is in use will disable iBeacons, geofences,
background location updates and accurate reporting.</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>TemporaryFullAccuracyReasonManualUpdate</key>
<string>[localized in strings file]</string>
</dict>
<key>NSLocationUsageDescription</key>
<string>When enabled, your device location is sent to your Home Assistant server as a device
tracker.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Only allowing location access while app is in use will disable iBeacons, geofences,
background location updates and accurate reporting.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Record audio using your Home Assistant frontend.</string>
<key>NSMotionUsageDescription</key>
<string>Motion is used to improve location updates with current motion type, as well as
provide basic pedometer data.</string>
Expand All @@ -658,24 +640,8 @@
<string>Photo Library access is needed to allow saving photos from the web view.</string>
<key>NSSiriUsageDescription</key>
<string>We use Siri to allow created shortcuts to interact with the app.</string>
<key>NFCReaderUsageDescription</key>
<string>Reading and writing NFC tags allows you to trigger events.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>Used to dictate text to Assist.</string>
<key>NSCameraUsageDescription</key>
<string>Take photos and send them to your Home Assistant server.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Record audio using your Home Assistant frontend.</string>
<key>NSFocusStatusUsageDescription</key>
<string>Report your focus status as a sensor.</string>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>12FC</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>D2760000850101</string>
</array>
<key>NSUserActivityTypes</key>
<array>
<string>CallServiceIntent</string>
Expand All @@ -690,6 +656,41 @@
<string>WidgetOpenPageIntent</string>
<string>AssistIntent</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>WebView</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).WebViewSceneDelegate</string>
</dict>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>Settings</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SettingsSceneDelegate</string>
</dict>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>About</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).AboutSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationShortcutItems</key>
<array>
<dict>
Expand Down Expand Up @@ -731,12 +732,13 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSCrossWebsiteTrackingUsageDescription</key>
<string>Optionally enable cross-website tracking if your configuration requires it.</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>TemporaryFullAccuracyReasonManualUpdate</key>
<string>[localized in strings file]</string>
</dict>
<key>com.apple.developer.nfc.readersession.felica.systemcodes</key>
<array>
<string>12FC</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>D2760000850101</string>
</array>
</dict>
</plist>
2 changes: 2 additions & 0 deletions Sources/App/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ Home Assistant is free and open source home automation software with a focus on
"settings_details.general.security.title" = "Security";
"settings_details.general.security.action" = "Enable biometric lock";
"settings_details.general.security.footer" = "You will be required to authenticate with biometrics every time you open the app.";
"settings_details.general.security.authentication_policy" = "Authentication required";
"settings_details.general.security.unlock_button" = "Unlock";
"settings_details.location.background_refresh.disabled" = "Disabled";
"settings_details.location.background_refresh.enabled" = "Enabled";
"settings_details.location.background_refresh.title" = "Background Refresh";
Expand Down
109 changes: 33 additions & 76 deletions Sources/App/WebView/WebViewWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ class WebViewWindowController {

private var webViewControllerSeal: (WebViewController) -> Void
private var onboardingPreloadWebViewController: WebViewController?
private let biometricOverlay: UIView = {
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
return visualEffectView
}()

init(window: UIWindow, restorationActivity: NSUserActivity?) {
self.window = window
Expand Down Expand Up @@ -413,36 +409,6 @@ class WebViewWindowController {
hud.hide(animated: true, afterDelay: 1.0)
}
}

private func listenForBiometricsLockRelatedEvents() {
if #available(iOS 13.0, *) {
NotificationCenter.default.addObserver(
self,
selector: #selector(checkForBiometrics),
name: UIScene.willEnterForegroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(protectAppIfNeeded),
name: UIScene.didEnterBackgroundNotification,
object: nil
)
} else {
NotificationCenter.default.addObserver(
self,
selector: #selector(checkForBiometrics),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(protectAppIfNeeded),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)
}
}
}

extension WebViewWindowController: OnboardingStateObserver {
Expand Down Expand Up @@ -507,55 +473,46 @@ extension WebViewWindowController: OnboardingStateObserver {
}

// MARK: - Biometrics lock

extension WebViewWindowController {
@objc private func checkForBiometrics() {
if Current.settingsStore.biometricsRequired {
addBiometricOverlayProtection()
Current.authenticationService.delegate = self
Current.authenticationService.authenticate()
} else {
DispatchQueue.main.async { [weak self] in
self?.biometricOverlay.removeFromSuperview()
}
}
}
private func listenForBiometricsLockRelatedEvents() {
if #available(iOS 13.0, *) {
NotificationCenter.default.addObserver(
self,
selector: #selector(checkForBiometrics),
name: UIScene.willEnterForegroundNotification,
object: nil
)

@objc private func protectAppIfNeeded() {
if Current.settingsStore.biometricsRequired {
addBiometricOverlayProtection()
NotificationCenter.default.addObserver(
self,
selector: #selector(protectAppIfNeeded),
name: UIScene.didEnterBackgroundNotification,
object: nil
)
} else {
DispatchQueue.main.async { [weak self] in
self?.biometricOverlay.removeFromSuperview()
}
NotificationCenter.default.addObserver(
self,
selector: #selector(checkForBiometrics),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(protectAppIfNeeded),
name: UIApplication.didEnterBackgroundNotification,
object: nil
)

Check warning on line 505 in Sources/App/WebView/WebViewWindowController.swift

View check run for this annotation

Codecov / codecov/patch

Sources/App/WebView/WebViewWindowController.swift#L494-L505

Added lines #L494 - L505 were not covered by tests
}
}

private func addBiometricOverlayProtection() {
guard let view = window.rootViewController?.view else { return }
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.biometricOverlay.removeFromSuperview()
self.biometricOverlay.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(self.biometricOverlay)
NSLayoutConstraint.activate([
self.biometricOverlay.topAnchor.constraint(equalTo: view.topAnchor),
self.biometricOverlay.bottomAnchor.constraint(equalTo: view.bottomAnchor),
self.biometricOverlay.leadingAnchor.constraint(equalTo: view.leadingAnchor),
self.biometricOverlay.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])
}
@objc private func checkForBiometrics() {
guard let controller = window.rootViewController else { return }
Current.authenticationService.checkForBiometrics(controller: controller)
}
}

// MARK: - AuthenticationServiceDelegate
extension WebViewWindowController: AuthenticationServiceDelegate {
func didFinishAuthentication(authorized: Bool) {
if authorized {
DispatchQueue.main.async { [weak self] in
self?.biometricOverlay.removeFromSuperview()
}
} else {
addBiometricOverlayProtection()
}
@objc private func protectAppIfNeeded() {
guard let controller = window.rootViewController else { return }
Current.authenticationService.protectAppIfNeeded(controller: controller, completion: nil)
}

Check warning on line 517 in Sources/App/WebView/WebViewWindowController.swift

View check run for this annotation

Codecov / codecov/patch

Sources/App/WebView/WebViewWindowController.swift#L514-L517

Added lines #L514 - L517 were not covered by tests
}
Loading

0 comments on commit 63c9c46

Please sign in to comment.