diff --git a/.package.resolved b/.package.resolved
index 64343e0b9..6aeef83ab 100644
--- a/.package.resolved
+++ b/.package.resolved
@@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/ProxymanApp/atlantis",
"state" : {
- "revision" : "131d757cf8e6e368ad338728379174f7cfff9326",
- "version" : "1.23.0"
+ "revision" : "5145a7041ec71421d09653db87dcc80c81792004",
+ "version" : "1.24.0"
}
},
{
@@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/CocoaLumberjack/CocoaLumberjack",
"state" : {
- "revision" : "363ed23d19a931809ea834a7d722da830353806a",
- "version" : "3.8.2"
+ "revision" : "ae8e475260b978299134d42d739f0ec8241d9af0",
+ "version" : "3.8.3"
}
},
{
@@ -94,8 +94,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/Infomaniak/ios-version-checker",
"state" : {
- "revision" : "821a785fd229afae83c0a982d772fe89542ab502",
- "version" : "1.0.1"
+ "revision" : "deeb4fa8377f9bcf3303216d1ea61c1e893b2abd",
+ "version" : "1.1.0"
}
},
{
@@ -166,8 +166,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/realm-core.git",
"state" : {
- "revision" : "7227d6a447821c28895daa099b6c7cd4c99d461b",
- "version" : "13.25.1"
+ "revision" : "a5e87a39cffdcc591f3203c11cfca68100d0b9a6",
+ "version" : "13.26.0"
}
},
{
@@ -175,8 +175,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/realm/realm-swift",
"state" : {
- "revision" : "836cc4b8619886f979f8961c3f592a82b0741591",
- "version" : "10.45.3"
+ "revision" : "eafdd3720a8cc750bdd38bf776082d2c8cf743fc",
+ "version" : "10.46.0"
}
},
{
@@ -236,10 +236,10 @@
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
- "location" : "https://github.com/apple/swift-log.git",
+ "location" : "https://github.com/apple/swift-log",
"state" : {
- "revision" : "532d8b529501fb73a2455b179e0bbb6d49b652ed",
- "version" : "1.5.3"
+ "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5",
+ "version" : "1.5.4"
}
},
{
@@ -301,8 +301,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/markiv/SwiftUI-Shimmer",
"state" : {
- "revision" : "1f3a620e4abe890d00008cb2af7023d810b433a7",
- "version" : "1.4.0"
+ "revision" : "5659a623567cefe258d1e3e67cb65585fbb6ecb6",
+ "version" : "1.4.2"
}
},
{
diff --git a/Mail/RootView.swift b/Mail/RootView.swift
index 7bc724ee1..46e035a96 100644
--- a/Mail/RootView.swift
+++ b/Mail/RootView.swift
@@ -32,14 +32,16 @@ struct RootView: View {
.environmentObject(mainViewState)
case .onboarding:
OnboardingView()
+ case .authorization:
+ AuthorizationView()
case .noMailboxes:
NoMailboxView()
case .unavailableMailboxes:
UnavailableMailboxesView()
+ case .updateRequired:
+ MailUpdateRequiredView()
case .preloading(let currentAccount):
PreloadingView(currentAccount: currentAccount)
- case .authorization:
- AuthorizationView()
}
}
}
diff --git a/Mail/UserAccountScene.swift b/Mail/UserAccountScene.swift
index def29c496..4192fc7dd 100644
--- a/Mail/UserAccountScene.swift
+++ b/Mail/UserAccountScene.swift
@@ -29,6 +29,7 @@ import MailResources
import Sentry
import SwiftUI
import UIKit
+import VersionChecker
struct UserAccountScene: Scene {
@Environment(\.scenePhase) private var scenePhase
@@ -37,6 +38,7 @@ struct UserAccountScene: Scene {
@LazyInjectService private var accountManager: AccountManager
@LazyInjectService private var appLaunchCounter: AppLaunchCounter
@LazyInjectService private var refreshAppBackgroundTask: RefreshAppBackgroundTask
+ @LazyInjectService private var platformDetector: PlatformDetectable
@StateObject private var rootViewState = RootViewState()
@@ -51,6 +53,7 @@ struct UserAccountScene: Scene {
appLaunchCounter.increase()
refreshCacheData()
rootViewState.transitionToLockViewIfNeeded()
+ checkAppVersion()
UserDefaults.shared.openingUntilReview -= 1
case .background:
refreshAppBackgroundTask.scheduleForBackgroundLaunchIfNeeded()
@@ -108,4 +111,25 @@ struct UserAccountScene: Scene {
}
}
}
+
+ func checkAppVersion() {
+ Task {
+ do {
+ let platform: Platform = platformDetector.isMacCatalyst ? .macOS : .ios
+ let versionStatus = try await VersionChecker.standard.checkAppVersionStatus(platform: platform)
+ switch versionStatus {
+ case .updateIsRequired:
+ rootViewState.transitionToRootViewDestination(.updateRequired)
+ case .canBeUpdated:
+ if case .mainView(let mainViewState) = rootViewState.state {
+ mainViewState.isShowingUpdateAvailable = true
+ }
+ case .isUpToDate:
+ break
+ }
+ } catch {
+ DDLogError("Error while checking version status: \(error)")
+ }
+ }
+ }
}
diff --git a/Mail/Views/MailUpdateRequiredView.swift b/Mail/Views/MailUpdateRequiredView.swift
new file mode 100644
index 000000000..061b278fa
--- /dev/null
+++ b/Mail/Views/MailUpdateRequiredView.swift
@@ -0,0 +1,51 @@
+/*
+ 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 .
+ */
+
+import MailCore
+import MailResources
+import SwiftUI
+import VersionChecker
+
+struct MailUpdateRequiredView: View {
+ @Environment(\.openURL) private var openURL
+
+ private let sharedStyle = TemplateSharedStyle(
+ background: MailResourcesAsset.backgroundColor.swiftUIColor,
+ titleTextStyle: .init(font: MailTextStyle.header2.font, color: MailTextStyle.header2.color),
+ descriptionTextStyle: .init(font: MailTextStyle.bodySecondary.font, color: MailTextStyle.bodySecondary.color),
+ buttonStyle: .init(
+ background: .accentColor,
+ textStyle: .init(font: MailTextStyle.bodyAccent.font, color: UserDefaults.shared.accentColor.onAccent.swiftUIColor),
+ height: UIConstants.buttonLargeHeight,
+ radius: UIConstants.buttonsRadius
+ )
+ )
+
+ var body: some View {
+ UpdateRequiredView(image: MailResourcesAsset.updateRequired.swiftUIImage, sharedStyle: sharedStyle, handler: updateApp)
+ }
+
+ private func updateApp() {
+ let url: URLConstants = Bundle.main.isRunningInTestFlight ? .testFlight : .appStore
+ openURL(url.url)
+ }
+}
+
+#Preview {
+ MailUpdateRequiredView()
+}
diff --git a/Mail/Views/SplitView.swift b/Mail/Views/SplitView.swift
index 710d2ed85..60b2462b4 100644
--- a/Mail/Views/SplitView.swift
+++ b/Mail/Views/SplitView.swift
@@ -26,7 +26,6 @@ import MailResources
import NavigationBackport
import RealmSwift
import SwiftUI
-import VersionChecker
@_spi(Advanced) import SwiftUIIntrospect
public class SplitViewManager: ObservableObject {
@@ -64,7 +63,6 @@ struct SplitView: View {
@LazyInjectService private var platformDetector: PlatformDetectable
@LazyInjectService private var appLaunchCounter: AppLaunchCounter
- @State private var isShowingUpdateAvailable = false
@State private var isShowingSyncDiscovery = false
@State private var isShowingSyncProfile = false
@@ -120,7 +118,7 @@ struct SplitView: View {
}
}
}
- .discoveryPresenter(isPresented: $isShowingUpdateAvailable) {
+ .discoveryPresenter(isPresented: $mainViewState.isShowingUpdateAvailable) {
DiscoveryView(item: .updateDiscovery) { willUpdate in
guard willUpdate else { return }
let url: URLConstants = Bundle.main.isRunningInTestFlight ? .testFlight : .appStore
@@ -166,8 +164,7 @@ struct SplitView: View {
}
guard !platformDetector.isDebug else { return }
// We don't want to show both DiscoveryView at the same time
- isShowingUpdateAvailable = try await VersionChecker.standard.showUpdateVersion()
- isShowingSyncDiscovery = isShowingUpdateAvailable ? false : showSync()
+ isShowingSyncDiscovery = mainViewState.isShowingUpdateAvailable ? false : showSync()
}
}
.onOpenURL { url in
diff --git a/MailCore/Cache/MainViewState.swift b/MailCore/Cache/MainViewState.swift
index 90c167ad5..1edfc7ac2 100644
--- a/MailCore/Cache/MainViewState.swift
+++ b/MailCore/Cache/MainViewState.swift
@@ -29,6 +29,7 @@ public class MainViewState: ObservableObject, SelectedThreadOwnable {
@Published public var isShowingSearch = false
@Published public var isShowingReviewAlert = false
+ @Published public var isShowingUpdateAvailable = false
@Published public var isShowingSetAppAsDefaultDiscovery = false
@Published public var isShowingChristmasEasterEgg = false
diff --git a/MailCore/Cache/RootViewState.swift b/MailCore/Cache/RootViewState.swift
index ba6d73544..112df3119 100644
--- a/MailCore/Cache/RootViewState.swift
+++ b/MailCore/Cache/RootViewState.swift
@@ -37,6 +37,8 @@ public enum RootViewType: Equatable {
return true
case (.unavailableMailboxes, .unavailableMailboxes):
return true
+ case (.updateRequired, .updateRequired):
+ return true
case (.mainView(let lhsMainViewState), .mainView(let rhsMainViewState)):
return lhsMainViewState.mailboxManager == rhsMainViewState.mailboxManager
case (.preloading(let lhsAccount), .preloading(let rhsAccount)):
@@ -52,6 +54,7 @@ public enum RootViewType: Equatable {
case authorization
case noMailboxes
case unavailableMailboxes
+ case updateRequired
case preloading(Account)
}
@@ -61,6 +64,7 @@ public enum RootViewDestination {
case onboarding
case noMailboxes
case unavailableMailboxes
+ case updateRequired
}
/// Something that represents the state of the root view
@@ -127,6 +131,8 @@ public class RootViewState: ObservableObject {
state = .noMailboxes
case .unavailableMailboxes:
state = .unavailableMailboxes
+ case .updateRequired:
+ state = .updateRequired
}
}
}
diff --git a/MailResources/Assets.xcassets/update-required.imageset/Contents.json b/MailResources/Assets.xcassets/update-required.imageset/Contents.json
new file mode 100644
index 000000000..d51d2bd80
--- /dev/null
+++ b/MailResources/Assets.xcassets/update-required.imageset/Contents.json
@@ -0,0 +1,25 @@
+{
+ "images" : [
+ {
+ "filename" : "update-required-light.svg",
+ "idiom" : "universal"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "filename" : "update-required-dark.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true
+ }
+}
diff --git a/MailResources/Assets.xcassets/update-required.imageset/update-required-dark.svg b/MailResources/Assets.xcassets/update-required.imageset/update-required-dark.svg
new file mode 100644
index 000000000..fe91a0dc3
--- /dev/null
+++ b/MailResources/Assets.xcassets/update-required.imageset/update-required-dark.svg
@@ -0,0 +1,32 @@
+
diff --git a/MailResources/Assets.xcassets/update-required.imageset/update-required-light.svg b/MailResources/Assets.xcassets/update-required.imageset/update-required-light.svg
new file mode 100644
index 000000000..11e2c653e
--- /dev/null
+++ b/MailResources/Assets.xcassets/update-required.imageset/update-required-light.svg
@@ -0,0 +1,32 @@
+
diff --git a/Project.swift b/Project.swift
index eb0c12303..574cc99e3 100644
--- a/Project.swift
+++ b/Project.swift
@@ -36,7 +36,7 @@ let project = Project(name: "Mail",
.package(url: "https://github.com/Infomaniak/ios-bug-tracker", .upToNextMajor(from: "2.0.0")),
.package(url: "https://github.com/Infomaniak/SQRichTextEditor", .upToNextMajor(from: "1.1.1")),
.package(url: "https://github.com/Infomaniak/SwiftSoup", .upToNextMajor(from: "1.1.0")),
- .package(url: "https://github.com/Infomaniak/ios-version-checker", .upToNextMajor(from: "1.0.1")),
+ .package(url: "https://github.com/Infomaniak/ios-version-checker", .upToNextMajor(from: "1.1.0")),
.package(url: "https://github.com/ProxymanApp/atlantis", .upToNextMajor(from: "1.21.0")),
.package(url: "https://github.com/Alamofire/Alamofire", .upToNextMajor(from: "5.2.2")),
.package(url: "https://github.com/CocoaLumberjack/CocoaLumberjack", .upToNextMajor(from: "3.7.0")),