Skip to content

Commit

Permalink
🔀️ Merge branch 'hugo/feature/Add-OS-update-available-alert' into dev…
Browse files Browse the repository at this point in the history
…elop
  • Loading branch information
ladislas committed Nov 28, 2024
2 parents b1fdddb + c404e9b commit c3845a4
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 29 deletions.
90 changes: 90 additions & 0 deletions Apps/LekaApp/Resources/l10n/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,24 @@
}
}
},
"lekaapp.main_view.app_update_alert.reminder": {
"comment": "The action button of the alert to inform the user that an os update is available",
"extractionState": "extracted_with_value",
"localizations": {
"en": {
"stringUnit": {
"state": "new",
"value": "Remind me later"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Me le rappeler plus tard"
}
}
}
},
"lekaapp.main_view.app_update_alert.title": {
"comment": "The title of the alert to inform the user that an update is available",
"extractionState": "extracted_with_value",
Expand Down Expand Up @@ -1820,6 +1838,78 @@
}
}
},
"lekaapp.main_view.os_update_alert.action": {
"comment": "The action button of the alert to inform the user that an os update is available",
"extractionState": "extracted_with_value",
"localizations": {
"en": {
"stringUnit": {
"state": "new",
"value": "Update now"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Mettre \u00e0 jour maintenant"
}
}
}
},
"lekaapp.main_view.os_update_alert.message": {
"comment": "The message of the alert to inform the user that an os update is available",
"extractionState": "extracted_with_value",
"localizations": {
"en": {
"stringUnit": {
"state": "new",
"value": "A new version of iPadOS is available! Update now to enjoy enhanced performance, security, and compatibility with the latest features of our app."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Une nouvelle version d'iPadOS est disponible ! Mettez \u00e0 jour d\u00e8s maintenant pour profiter de meilleures performances, d\u2019une s\u00e9curit\u00e9 renforc\u00e9e et d\u2019une compatibilit\u00e9 optimale avec les derni\u00e8res fonctionnalit\u00e9s de notre application."
}
}
}
},
"lekaapp.main_view.os_update_alert.reminder": {
"comment": "The action button of the alert to inform the user that an os update is available",
"extractionState": "extracted_with_value",
"localizations": {
"en": {
"stringUnit": {
"state": "new",
"value": "Remind me later"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Me le rappeler plus tard"
}
}
}
},
"lekaapp.main_view.os_update_alert.title": {
"comment": "The title of the alert to inform the user that an os update is available",
"extractionState": "extracted_with_value",
"localizations": {
"en": {
"stringUnit": {
"state": "new",
"value": "Update your iPad to the Latest iPadOS Version"
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value": "Mettez \u00e0 jour votre iPad vers la derni\u00e8re version d'iPadOS"
}
}
}
},
"lekaapp.main_view.sidebar.category_label.caregivers": {
"comment": "The title of the category 'Caregivers'",
"extractionState": "extracted_with_value",
Expand Down
36 changes: 27 additions & 9 deletions Apps/LekaApp/Sources/MainApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import AnalyticsKit
import Combine
import ContentKit
import DesignKit
import DeviceKit
import FirebaseKit
import LocalizationKit
import LogKit
Expand All @@ -33,6 +34,15 @@ class AppDelegate: NSObject, UIApplicationDelegate {
}
}

// MARK: - UpdateManager

class UpdateManager: ObservableObject {
static let shared = UpdateManager()

@Published var appUpdateStatus: UpdateStatusFetcher.Status = .upToDate
@Published var osUpdateStatus: UpdateStatusFetcher.Status = .upToDate
}

// MARK: - LekaApp

@main
Expand All @@ -45,16 +55,10 @@ struct LekaApp: App {

// MARK: Internal

class UpdateStatus: ObservableObject {
static let shared = UpdateStatus()

@Published var status: UpdateStatusFetcher.Status = .upToDate
}

@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

@Environment(\.colorScheme) var colorScheme
@StateObject var appUpdateStatus: UpdateStatus = .shared
@StateObject var updateManager: UpdateManager = .shared
@ObservedObject var styleManager: StyleManager = .shared

var body: some Scene {
Expand Down Expand Up @@ -87,16 +91,30 @@ struct LekaApp: App {
guard let status = try? result.get() else {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.showMainView = true
self.appUpdateStatus.status = .upToDate
UpdateManager.shared.appUpdateStatus = .upToDate
}
return
}

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.showMainView = true
self.appUpdateStatus.status = status
UpdateManager.shared.appUpdateStatus = status
}
}

switch Device.current {
case .iPad5,
.iPadPro9Inch:
UpdateManager.shared.osUpdateStatus = .upToDate
case .iPad6:
if Device.current.systemVersion!.compare("17.7.2") == .orderedAscending {
UpdateManager.shared.osUpdateStatus = .osUpdateAvailable
}
default:
if Device.current.systemVersion!.compare("18.1.1") == .orderedAscending {
UpdateManager.shared.osUpdateStatus = .osUpdateAvailable
}
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions Apps/LekaApp/Sources/Views/MainView/MainView+l10n.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ extension l10n {
static let title = LocalizedString("lekaapp.main_view.app_update_alert.title", value: "New update available", comment: "The title of the alert to inform the user that an update is available")
static let message = LocalizedString("lekaapp.main_view.app_update_alert.message", value: "Enjoy new features by updating to the latest version of Leka!", comment: "The message of the alert to inform the user that an update is available")
static let action = LocalizedString("lekaapp.main_view.app_update_alert.action", value: "Update now", comment: "The action button of the alert to inform the user that an update is available")
static let reminder = LocalizedString("lekaapp.main_view.app_update_alert.reminder", value: "Remind me later", comment: "The action button of the alert to inform the user that an os update is available")
}

enum OSUpdateAlert {
static let title = LocalizedString("lekaapp.main_view.os_update_alert.title", value: "Update your iPad to the Latest iPadOS Version", comment: "The title of the alert to inform the user that an os update is available")
static let message = LocalizedString("lekaapp.main_view.os_update_alert.message", value: "A new version of iPadOS is available! Update now to enjoy enhanced performance, security, and compatibility with the latest features of our app.", comment: "The message of the alert to inform the user that an os update is available")
static let action = LocalizedString("lekaapp.main_view.os_update_alert.action", value: "Update now", comment: "The action button of the alert to inform the user that an os update is available")
static let reminder = LocalizedString("lekaapp.main_view.os_update_alert.reminder", value: "Remind me later", comment: "The action button of the alert to inform the user that an os update is available")
}
}
}
Expand Down
30 changes: 22 additions & 8 deletions Apps/LekaApp/Sources/Views/MainView/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,23 @@ struct MainView: View {
UIApplication.shared.open(url)
}
}),
secondaryButton: .cancel {
AnalyticsManager.logEventAppUpdateSkip()
secondaryButton: .cancel(Text(l10n.MainView.AppUpdateAlert.reminder)) {
AnalyticsManager.logEventAppUpdateRemindLater()
}
)
}
.alert(isPresented: self.$showingOSUpdateAlert) {
Alert(
title: Text(l10n.MainView.OSUpdateAlert.title),
message: Text(l10n.MainView.OSUpdateAlert.message),
primaryButton: .default(Text(l10n.MainView.OSUpdateAlert.action), action: {
AnalyticsManager.logEventOSUpdateOpenSettings()
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
}),
secondaryButton: .cancel(Text(l10n.MainView.OSUpdateAlert.reminder)) {
AnalyticsManager.logEventOSUpdateRemindLater()
}
)
}
Expand Down Expand Up @@ -317,11 +332,10 @@ struct MainView: View {
}
.onDisappear {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
switch self.appUpdateStatus.status {
case .updateAvailable:
self.showingAppUpdateAlert = true
default:
break
if case .appUpdateAvailable = UpdateManager.shared.appUpdateStatus {
self.showingAppUpdateAlert = true
} else if case .osUpdateAvailable = UpdateManager.shared.osUpdateStatus {
self.showingOSUpdateAlert = true
}
}
}
Expand Down Expand Up @@ -418,9 +432,9 @@ struct MainView: View {

@StateObject private var caregiverManagerViewModel = CaregiverManagerViewModel()
@StateObject private var rootAccountViewModel = RootAccountManagerViewModel()
@StateObject var appUpdateStatus: LekaApp.UpdateStatus = .shared

@State private var showingAppUpdateAlert: Bool = false
@State private var showingOSUpdateAlert: Bool = false

private var persistentDataManager: PersistentDataManager = .shared
private var caregiverManager: CaregiverManager = .shared
Expand Down
4 changes: 1 addition & 3 deletions Apps/LekaApp/Sources/Views/MainView/SettingsLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import SwiftUI
struct SettingsLabel: View {
// MARK: Internal

@StateObject var appUpdateStatus: LekaApp.UpdateStatus = .shared

var body: some View {
Label(String(l10n.SettingsLabel.buttonLabel.characters), systemImage: "gear")
.frame(width: 200, height: 44)
Expand All @@ -29,7 +27,7 @@ struct SettingsLabel: View {
.clipShape(.circle)
.offset(x: 95, y: -20)
.opacity({
if case .updateAvailable = self.appUpdateStatus.status {
if case .appUpdateAvailable = UpdateManager.shared.appUpdateStatus {
return 1.0
}
return 0.0
Expand Down
3 changes: 1 addition & 2 deletions Apps/LekaApp/Sources/Views/Settings/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct SettingsView: View {

var body: some View {
Form {
if case .updateAvailable = self.appUpdateStatus.status {
if case .appUpdateAvailable = UpdateManager.shared.appUpdateStatus {
Section {
VStack(alignment: .center) {
HStack(spacing: 20) {
Expand Down Expand Up @@ -246,7 +246,6 @@ struct SettingsView: View {
@ObservedObject private var styleManager: StyleManager = .shared
@ObservedObject private var navigation = Navigation.shared

@StateObject var appUpdateStatus: LekaApp.UpdateStatus = .shared
@StateObject private var rootAccountViewModel = RootAccountManagerViewModel()

private func reset() {
Expand Down
24 changes: 22 additions & 2 deletions Modules/AnalyticsKit/Sources/Analytics/AnalyticsManager+App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import FirebaseAnalytics

public extension AnalyticsManager {
// TODO: (@ladislas) add real versions
static func logEventAppUpdateSkip(currentVersion: String = "(lk_not_set)", newVersion: String = "(lk_not_set)", parameters: [String: Any] = [:]) {
static func logEventAppUpdateRemindLater(currentVersion: String = "(lk_not_set)", newVersion: String = "(lk_not_set)", parameters: [String: Any] = [:]) {
let params: [String: Any] = [
"current_version": currentVersion,
"new_version": newVersion,
].merging(parameters) { _, new in new }

logEvent(.appUpdateSkip, parameters: params)
logEvent(.appUpdateRemindLater, parameters: params)
}

// TODO: (@ladislas) add real versions
Expand All @@ -24,4 +24,24 @@ public extension AnalyticsManager {

logEvent(.appUpdateOpenAppStore, parameters: params)
}

// TODO: (@ladislas) add real versions
static func logEventOSUpdateRemindLater(currentVersion: String = "(lk_not_set)", newVersion: String = "(lk_not_set)", parameters: [String: Any] = [:]) {
let params: [String: Any] = [
"current_version": currentVersion,
"new_version": newVersion,
].merging(parameters) { _, new in new }

logEvent(.osUpdateRemindLater, parameters: params)
}

// TODO: (@ladislas) add real versions
static func logEventOSUpdateOpenSettings(currentVersion: String = "(lk_not_set)", newVersion: String = "(lk_not_set)", parameters: [String: Any] = [:]) {
let params: [String: Any] = [
"current_version": currentVersion,
"new_version": newVersion,
].merging(parameters) { _, new in new }

logEvent(.osUpdateOpenSettings, parameters: params)
}
}
14 changes: 11 additions & 3 deletions Modules/AnalyticsKit/Sources/Analytics/AnalyticsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ public class AnalyticsManager {
case activityStart
case activityEnd

case appUpdateSkip
case appUpdateRemindLater
case appUpdateOpenAppStore

case osUpdateRemindLater
case osUpdateOpenSettings

case login
case logout
case signup
Expand All @@ -52,11 +55,16 @@ public class AnalyticsManager {
case .activityEnd:
"activity_end"

case .appUpdateSkip:
"app_update_skip"
case .appUpdateRemindLater:
"app_update_remind_later"
case .appUpdateOpenAppStore:
"app_update_open_app_store"

case .osUpdateRemindLater:
"os_update_remind_later"
case .osUpdateOpenSettings:
"os_update_open_settings"

case .login:
AnalyticsEventLogin // ? "login"
case .logout:
Expand Down
5 changes: 3 additions & 2 deletions Modules/UtilsKit/Sources/UpdateStatusFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public struct UpdateStatusFetcher {
public enum Status: Equatable {
case newerVersion
case upToDate
case updateAvailable(version: String, storeURL: URL)
case appUpdateAvailable(version: String, storeURL: URL)
case osUpdateAvailable
case underMinimumOsVersion
}

Expand Down Expand Up @@ -116,7 +117,7 @@ public struct UpdateStatusFetcher {
case .orderedSame:
return UpdateStatusFetcher.Status.upToDate
case .orderedAscending:
return UpdateStatusFetcher.Status.updateAvailable(version: appMetadata.version, storeURL: appMetadata.trackViewURL)
return UpdateStatusFetcher.Status.appUpdateAvailable(version: appMetadata.version, storeURL: appMetadata.trackViewURL)
}
}
}

0 comments on commit c3845a4

Please sign in to comment.