Skip to content

Commit

Permalink
feat(LockedAppView): Unlock button should be loading while evaluating…
Browse files Browse the repository at this point in the history
… policy (#1431)
  • Loading branch information
PhilippeWeidmann authored May 24, 2024
2 parents dcfe20d + 3dd0b6b commit a1f951d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 24 deletions.
42 changes: 18 additions & 24 deletions Mail/UserAccountScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import InfomaniakDI
import InfomaniakLogin
import InfomaniakNotifications
import MailCore
import MailCoreUI
import MailResources
import SwiftUI
import UIKit
Expand All @@ -45,29 +46,7 @@ struct UserAccountScene: Scene {
RootView()
.standardWindow()
.environmentObject(rootViewState)
.onReceive(NotificationCenter.default.publisher(for: UIScene.willEnterForegroundNotification)) { _ in
/*
On iOS:
`scenePhase` changes each time a pop-up is presented.
We have to listen to `UIScene.willEnterForegroundNotification` to increase the `appLaunchCounter`
only when the app enters foreground.
On macOS:
`scenePhase` stays always active even when the app is on the background.
*/

appLaunchCounter.increase()
cacheManager.refreshCacheData(account: rootViewState.account)
reviewManager.decreaseOpeningUntilReview()
rootViewState.transitionToLockViewIfNeeded()
checkAppVersion()
}
.onReceive(NotificationCenter.default.publisher(for: UIScene.didEnterBackgroundNotification)) { _ in
refreshAppBackgroundTask.scheduleForBackgroundLaunchIfNeeded()
if UserDefaults.shared.isAppLockEnabled && rootViewState.state != .appLocked {
appLockHelper.setTime()
}
}
.sceneLifecycle(willEnterForeground: willEnterForeground, didEnterBackground: didEnterBackground)
.task(id: rootViewState.account) {
cacheManager.refreshCacheData(account: rootViewState.account)
}
Expand Down Expand Up @@ -95,7 +74,22 @@ struct UserAccountScene: Scene {
}
}

func checkAppVersion() {
private func willEnterForeground() {
appLaunchCounter.increase()
reviewManager.decreaseOpeningUntilReview()
cacheManager.refreshCacheData(account: rootViewState.account)
rootViewState.transitionToLockViewIfNeeded()
checkAppVersion()
}

private func didEnterBackground() {
refreshAppBackgroundTask.scheduleForBackgroundLaunchIfNeeded()
if UserDefaults.shared.isAppLockEnabled && rootViewState.state != .appLocked {
appLockHelper.setTime()
}
}

private func checkAppVersion() {
Task {
do {
let platform: Platform = platformDetector.isMacCatalyst ? .macOS : .ios
Expand Down
8 changes: 8 additions & 0 deletions Mail/Views/LockedAppView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ struct LockedAppView: View {

@EnvironmentObject var navigationState: RootViewState

@State private var isEvaluatingPolicy = false

var body: some View {
ZStack {
VStack(spacing: UIPadding.medium) {
Expand All @@ -49,6 +51,7 @@ struct LockedAppView: View {
.buttonStyle(.ikPlain)
.controlSize(.large)
.ikButtonFullWidth(true)
.ikButtonLoading(isEvaluatingPolicy)
}
.padding(.top, UIPadding.onBoardingLogoTop)
.padding(.bottom, value: .large)
Expand All @@ -61,12 +64,17 @@ struct LockedAppView: View {
}

private func unlockApp() {
guard !isEvaluatingPolicy else { return }

Task {
isEvaluatingPolicy = true
if await (try? appLockHelper.evaluatePolicy(reason: MailResourcesStrings.Localizable.lockAppTitle)) == true {
appLockHelper.setTime()
Task {
navigationState.transitionToRootViewDestination(.mainView)
}
} else {
isEvaluatingPolicy = false
}
}
}
Expand Down
62 changes: 62 additions & 0 deletions MailCoreUI/Utils/SceneLifecycleModifier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
Infomaniak Mail - iOS App
Copyright (C) 2024 Infomaniak Network SA
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import InfomaniakCore
import InfomaniakDI
import SwiftUI

public extension View {
func sceneLifecycle(willEnterForeground: (() -> Void)? = nil, didEnterBackground: (() -> Void)? = nil) -> some View {
return modifier(SceneLifecycleModifier(willEnterForeground: willEnterForeground, didEnterBackground: didEnterBackground))
}
}

struct SceneLifecycleModifier: ViewModifier {
@LazyInjectService private var platformDetector: PlatformDetectable

var willEnterForeground: (() -> Void)?
var didEnterBackground: (() -> Void)?

func body(content: Content) -> some View {
content
.onAppear {
/*
On iOS/iPadOS, the `UIScene.willEnterForegroundNotification` notification is not posted when
the app is opened for the first time.
*/
if !platformDetector.isMac {
willEnterForeground?()
}
}
.onReceive(NotificationCenter.default.publisher(for: UIScene.willEnterForegroundNotification)) { _ in
/*
On iOS/iPadOS:
`scenePhase` changes each time a pop-up is presented.
We have to listen to `UIScene.willEnterForegroundNotification` to increase the `appLaunchCounter`
only when the app enters foreground.
On macOS:
`scenePhase` stays always active even when the app is on the background.
*/
willEnterForeground?()
}
.onReceive(NotificationCenter.default.publisher(for: UIScene.didEnterBackgroundNotification)) { _ in
didEnterBackground?()
}
}
}

0 comments on commit a1f951d

Please sign in to comment.