Skip to content

Instantly share code, notes, and snippets.

@mendesbarreto
Created February 11, 2019 15:37
Show Gist options
  • Save mendesbarreto/3fa1b1838d4387a41ab3f47a960c5574 to your computer and use it in GitHub Desktop.
Save mendesbarreto/3fa1b1838d4387a41ab3f47a960c5574 to your computer and use it in GitHub Desktop.
Tapume Firebase
import Foundation
import Firebase
final class AppUpdateCheckerFactory {
static func make(debugMode: Bool = false) -> AppUpdateChecker {
if debugMode {
activateDebugMode()
}
return AppUpdateChecker(currentAppVersion: Environment.appVersion,
remoteConfig: RemoteConfig.remoteConfig())
}
private static func activateDebugMode() {
if let debugSettings = RemoteConfigSettings(developerModeEnabled: true) {
RemoteConfig.remoteConfig().configSettings = debugSettings
}
}
}
import Foundation
struct AppVersionChecker {
let currentVersion: String
let remoteVersion: String
func hasUpdateAvailable() -> Bool {
let currentVersion = versionNumberFrom(string: self.currentVersion)
let storeAvailableVersion = versionNumberFrom(string: self.remoteVersion)
return storeAvailableVersion > currentVersion
}
func isBlacklistVersion() -> Bool {
let blackList = remoteVersion.split(separator: ";").map {
return String($0).trimmingCharacters(in: .whitespaces)
}
return blackList.contains(currentVersion)
}
func versionNumberFrom(string: String) -> Int {
return Int(string.split { $0 == "." }
.map(String.init)
.joined()) ?? 0
}
}
import Foundation
enum RemoteKey: String {
case blackList = "force_update_black_list"
case minAcceptableVersion = "force_update_min_acceptable"
case serverCurrentVersion = "force_update_current_version"
}
enum AppVersionStatus {
// Should update when the version is on blacklist
case blackList
// User has update available on store
case updateAvailable
// User should update to new version
case forceUpdate
// User has the last updated version
case updated
}
protocol AppUpdateCheckable: class {
var blackListVersions: String { get }
var minRequiredVersion: String { get }
var currentStoreVersion: String { get }
func fetchAppVersionWith(expirationInterval: TimeInterval, onSuccess: @escaping () -> Void, onFail: @escaping () -> Void)
}
final class AppUpdateChecker {
private let remoteConfig: AppUpdateCheckable
private let currentAppVersion: String
private var didFetchAppVersion: ((_ appVersionStatus: AppVersionStatus) -> Void)?
private(set) var hasFetchData: Bool
private let debugMode: Bool
var appVersionState: AppVersionStatus {
if hasAppVersionOn(blackList: remoteConfig.blackListVersions) {
return .blackList
} else if hasAppUpdateAvailableOn(storeVersion: remoteConfig.minRequiredVersion) {
return .forceUpdate
} else if hasAppUpdateAvailableOn(storeVersion: remoteConfig.currentStoreVersion) {
return .updateAvailable
}
return .updated
}
init(currentAppVersion: String,
remoteConfig: AppUpdateCheckable,
debugMode: Bool = false) {
self.currentAppVersion = currentAppVersion
self.remoteConfig = remoteConfig
self.debugMode = debugMode
self.hasFetchData = false
}
func fetchConfig(onComplete: @escaping (_ appVersionStatus: AppVersionStatus) -> Void) {
didFetchAppVersion = onComplete
remoteConfig.fetchAppVersionWith(expirationInterval: 0.0, onSuccess: didFetchAppVersionFromRemoteConfig) { [weak self] in
print("\n\n\n [ERROR] Some thing goes wrong when get last application version \n\n\n")
self?.hasFetchData = false
}
}
private func didFetchAppVersionFromRemoteConfig() {
hasFetchData = true
didFetchAppVersion?(appVersionState)
}
private func hasAppVersionOn(blackList: String) -> Bool {
return AppVersionChecker(currentVersion: currentAppVersion, remoteVersion: blackList).isBlacklistVersion()
}
func hasAppUpdateAvailableOn(storeVersion: String) -> Bool {
let versionChecker = AppVersionChecker(currentVersion: currentAppVersion, remoteVersion: storeVersion)
return versionChecker.hasUpdateAvailable()
}
}
import UIKit
final class RemoteConfigAlertFactory {
static func make(appVersionStatus: AppVersionStatus, alertAction: (() -> Void)? = nil) -> UIAlertController? {
switch appVersionStatus {
case .blackList,
.forceUpdate:
return forceUpdateAlert(alertAction: alertAction)
case .updateAvailable:
return updateAvailableAlert(alertAction: alertAction)
default: return nil
}
}
private static func forceUpdateAlert(alertAction: (() -> Void)? = nil) -> UIAlertController {
let alert = UIAlertController(title: Strings.Tapume.Alert.title,
message: Strings.Tapume.Alert.requiredMessage,
preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: Strings.Tapume.Alert.Button.title,
style: .default) { _ in
alertAction?()
}
alert.addAction(action)
return alert
}
private static func updateAvailableAlert(alertAction: (() -> Void)? = nil) -> UIAlertController {
let alert = UIAlertController(title: Strings.Tapume.Alert.title,
message: Strings.Tapume.Alert.optionalMessage,
preferredStyle: UIAlertControllerStyle.alert)
let action = UIAlertAction(title: Strings.Tapume.Alert.Button.title,
style: .default) { _ in
alertAction?()
}
alert.addAction(action)
alert.addAction(.cancelAction)
return alert
}
}
fileprivate extension UIAlertAction {
static var cancelAction: UIAlertAction {
return UIAlertAction(title: Strings.Common.cancel,
style: .cancel)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment