Преглед изворни кода

Notification of new version, blacklisted version and build expiration

Jonas Björkert пре 2 година
родитељ
комит
4a61029faf

+ 0 - 1
LoopFollow/Application/AppDelegate.swift

@@ -42,7 +42,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
          return true
       }
         
-   
     func applicationWillTerminate(_ application: UIApplication) {
         if UserDefaultsRepository.alertAppInactive.value {
             AlarmSound.setSoundFile(str: "Alarm_Buzzer")

+ 55 - 1
LoopFollow/ViewControllers/MainViewController.swift

@@ -423,9 +423,63 @@ class MainViewController: UIViewController, UITableViewDataSource, ChartViewDele
         }
         
         restartAllTimers()
-
+        checkAndNotifyVersionStatus()
+        checkAppExpirationStatus()
     }
     
+    func checkAndNotifyVersionStatus() {
+        let versionManager = AppVersionManager()
+        versionManager.checkForNewVersion { latestVersion, isNewer, isBlacklisted in
+            let now = Date()
+            
+            // Check if the current version is blacklisted, or if there is a newer version available
+            if isBlacklisted {
+                let lastBlacklistShown = UserDefaultsRepository.lastBlacklistNotificationShown.value ?? Date.distantPast
+                if now.timeIntervalSince(lastBlacklistShown) > 86400 { // 24 hours
+                    self.versionAlert(message: "The current version has a critical issue and should be updated immediately.")
+                    UserDefaultsRepository.lastBlacklistNotificationShown.value = now
+                    UserDefaultsRepository.lastVersionUpdateNotificationShown.value = now
+                }
+            } else if isNewer {
+                let lastVersionUpdateShown = UserDefaultsRepository.lastVersionUpdateNotificationShown.value ?? Date.distantPast
+                if now.timeIntervalSince(lastVersionUpdateShown) > 1209600 { // 2 weeks
+                    self.versionAlert(message: "A new version is available: \(latestVersion ?? "Unknown"). It is recommended to update.")
+                    UserDefaultsRepository.lastVersionUpdateNotificationShown.value = now
+                }
+            }
+        }
+    }
+
+    func versionAlert(title: String = "Update Available", message: String) {
+        DispatchQueue.main.async {
+            let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
+            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
+            self.present(alert, animated: true)
+        }
+    }
+
+    func checkAppExpirationStatus() {
+        let now = Date()
+        let expirationDate = BuildDetails.default.calculateExpirationDate()
+        let weekBeforeExpiration = Calendar.current.date(byAdding: .day, value: -7, to: expirationDate)!
+        
+        if now >= weekBeforeExpiration {
+            let lastExpirationShown = UserDefaultsRepository.lastExpirationNotificationShown.value ?? Date.distantPast
+            if now.timeIntervalSince(lastExpirationShown) > 86400 { // 24 hours
+                expirationAlert()
+                UserDefaultsRepository.lastExpirationNotificationShown.value = now
+            }
+        }
+    }
+
+    func expirationAlert() {
+        DispatchQueue.main.async {
+            let alert = UIAlertController(title: "App Expiration Warning", message: "This app will expire in less than a week. Please rebuild to continue using it.", preferredStyle: .alert)
+            alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
+            self.present(alert, animated: true)
+        }
+    }
+
     @objc override func viewDidAppear(_ animated: Bool) {
         showHideNSDetails()
     }

+ 23 - 13
LoopFollow/helpers/AppVersionManager.swift

@@ -11,23 +11,32 @@ import Foundation
 class AppVersionManager {
     private let githubService = GitHubService()
     
+    /// Checks for the availability of a new app version and if the current version is blacklisted.
+    /// - Parameter completion: Returns latest version, a boolean for newer version existence, and blacklist status.
+    /// Usage: `versionManager.checkForNewVersion { latestVersion, isNewer, isBlacklisted in ... }`
     func checkForNewVersion(completion: @escaping (String?, Bool, Bool) -> Void) {
         let currentVersion = version()
         let now = Date()
-        
-        // Retrieve cache
-        let lastChecked = UserDefaults.standard.object(forKey: "latestVersionChecked") as? Date ?? Date.distantPast
-        let cachedLatestVersion = UserDefaults.standard.string(forKey: "latestVersion")
-        let isBlacklistedCached = UserDefaults.standard.bool(forKey: "isCurrentVersionBlacklisted")
 
+        // Retrieve cache
+        let latestVersionChecked = UserDefaultsRepository.latestVersionChecked.value ?? Date.distantPast
+        let latestVersion = UserDefaultsRepository.latestVersion.value
+        let currentVersionBlackListed = UserDefaultsRepository.currentVersionBlackListed.value
+        let cachedForVersion = UserDefaultsRepository.cachedForVersion.value
+        
         // Check if the cache is still valid
-        if now.timeIntervalSince(lastChecked) < 24 * 3600, let latestVersion = cachedLatestVersion {
+        if let cachedVersion = cachedForVersion, cachedVersion == currentVersion,
+           now.timeIntervalSince(latestVersionChecked) < 24 * 3600, let latestVersion = latestVersion {
             let isNewer = isVersion(latestVersion, newerThan: currentVersion)
-            completion(latestVersion, isNewer, isBlacklistedCached)
+            completion(latestVersion, isNewer, currentVersionBlackListed)
             return
         }
-        
-        // Fetch new data if cache is outdated
+
+        // Fetch new data if cache is outdated or not for current version
+        fetchDataAndUpdateCache(currentVersion: currentVersion, completion: completion)
+    }
+
+    private func fetchDataAndUpdateCache(currentVersion: String, completion: @escaping (String?, Bool, Bool) -> Void) {
         githubService.fetchData(for: .versionConfig) { versionData in
             self.githubService.fetchData(for: .blacklistedVersions) { blacklistData in
                 DispatchQueue.main.async {
@@ -42,6 +51,7 @@ class AppVersionManager {
                     UserDefaults.standard.set(fetchedVersion, forKey: "latestVersion")
                     UserDefaults.standard.set(Date(), forKey: "latestVersionChecked")
                     UserDefaults.standard.set(isBlacklisted, forKey: "isCurrentVersionBlacklisted")
+                    UserDefaults.standard.set(currentVersion, forKey: "cachedForVersion")
                     
                     // Call completion with new data
                     completion(fetchedVersion, isNewer, isBlacklisted)
@@ -62,7 +72,7 @@ class AppVersionManager {
         }
         return nil
     }
-    
+
     private func isVersion(_ fetchedVersion: String, newerThan currentVersion: String) -> Bool {
         let fetchedVersionComponents = fetchedVersion.split(separator: ".").map { Int($0) ?? 0 }
         let currentVersionComponents = currentVersion.split(separator: ".").map { Int($0) ?? 0 }
@@ -79,18 +89,18 @@ class AppVersionManager {
         }
         return false
     }
-    
+
     func version() -> String {
         if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
             return version
         }
         return "Unknown"
     }
-    
+
     struct Blacklist: Decodable {
         let blacklistedVersions: [VersionEntry]
     }
-    
+
     struct VersionEntry: Decodable {
         let version: String
     }

+ 1 - 1
LoopFollow/helpers/BuildDetails.swift

@@ -71,7 +71,7 @@ class BuildDetails {
             if let provision = MobileProvision.read() {
                 return provision.expirationDate
             } else {
-                return Date()
+                return .distantFuture
             }
         }
     }

+ 10 - 0
LoopFollow/repository/UserDefaults.swift

@@ -460,10 +460,20 @@ class UserDefaultsRepository {
     static let alertRecBolusSnoozedTime = UserDefaultsValue<Date?>(key: "alertRecBolusSnoozedTime", default: nil)
     static var deviceRecBolus: UserDefaultsValue<Double> = UserDefaultsValue(key: "deviceRecBolus", default: 0.0)
 
+    //What version is the cache valid for
+    static let cachedForVersion = UserDefaultsValue<String?>(key: "cachedForVersion", default: nil)
+
     //Caching of latest version
     static let latestVersion = UserDefaultsValue<String?>(key: "latestVersion", default: nil)
     static let latestVersionChecked = UserDefaultsValue<Date?>(key: "latestVersionChecked", default: nil)
 
     //Caching of blacklisted version
     static let currentVersionBlackListed = UserDefaultsValue<Bool>(key: "currentVersionBlackListed", default: false)
+
+    // Tracking notifications to manage frequency
+    static let lastBlacklistNotificationShown = UserDefaultsValue<Date?>(key: "lastBlacklistNotificationShown", default: nil)
+    static let lastVersionUpdateNotificationShown = UserDefaultsValue<Date?>(key: "lastVersionUpdateNotificationShown", default: nil)
+    
+    // Tracking the last time the expiration notification was shown
+    static let lastExpirationNotificationShown = UserDefaultsValue<Date?>(key: "lastExpirationNotificationShown", default: nil)
 }