LNAppConfig.swift 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //
  2. // LNAppConfig.swift
  3. // Lanu
  4. //
  5. // Created by OneeChan on 2025/11/6.
  6. //
  7. import Foundation
  8. import Combine
  9. enum LNAppEnvType: Codable, CaseIterable {
  10. case test
  11. case official
  12. var text: String {
  13. switch self {
  14. case .test: "测试环境"
  15. case .official: "线上环境"
  16. }
  17. }
  18. }
  19. enum LNAppLanguage: Codable {
  20. case chiness
  21. case english
  22. case indonesian
  23. var text: String {
  24. switch self {
  25. case .chiness: "中文"
  26. case .english: "English"
  27. case .indonesian: "Bahasa Indonesia"
  28. }
  29. }
  30. var bundleName: String {
  31. switch self {
  32. case .chiness: "zh-Hans"
  33. case .english: "en"
  34. case .indonesian: "id"
  35. }
  36. }
  37. var languageCode: String {
  38. switch self {
  39. case .chiness: "zh"
  40. case .english: "en"
  41. case .indonesian: "id"
  42. }
  43. }
  44. var countryCode: String {
  45. switch self {
  46. case .chiness: "CN"
  47. case .english: "US"
  48. case .indonesian: "ID"
  49. }
  50. }
  51. var isSelected: Bool {
  52. self == LNAppConfig.shared.curLang
  53. }
  54. static var available: [LNAppLanguage] {
  55. [.chiness, .english, .indonesian]
  56. }
  57. }
  58. class LNAppConfig {
  59. static var shared = LNAppConfig()
  60. @Published
  61. private(set) var hasNewVersion = false
  62. private(set) var isForeground = true {
  63. didSet {
  64. LNEventDeliver.notifyEvent { ($0 as? LNAppMainEvent)?.onAppStateChanged(foreground: self.isForeground) }
  65. }
  66. }
  67. var curEnv: LNAppEnvType = LNUserDefaults[.appEnv, .official] {
  68. didSet {
  69. LNUserDefaults[.appEnv] = curEnv
  70. }
  71. }
  72. var countryCode: String {
  73. if #available(iOS 16.0, *) {
  74. Locale.current.region?.identifier ?? ""
  75. } else {
  76. Locale.current.regionCode ?? ""
  77. }
  78. }
  79. private static var defaultLanguage: LNAppLanguage {
  80. let lang = Locale.preferredLanguages.first ?? "en"
  81. return if lang == LNAppLanguage.chiness.bundleName {
  82. .chiness
  83. } else if lang == LNAppLanguage.indonesian.bundleName {
  84. .indonesian
  85. } else {
  86. .english
  87. }
  88. }
  89. var curLang: LNAppLanguage = LNUserDefaults[.appLanguage, defaultLanguage] {
  90. didSet {
  91. guard oldValue != curLang else { return }
  92. LNUserDefaults[.appLanguage] = curLang
  93. LNEventDeliver.notifyEvent {
  94. ($0 as? LNAppMainEvent)?.onAppLanguageChanged(newLanguage: self.curLang)
  95. }
  96. }
  97. }
  98. var languageBundleMap: [LNAppLanguage: Bundle] = {
  99. LNAppLanguage.available.reduce(into: [LNAppLanguage: Bundle](), { result, language in
  100. let bundle = if let path = Bundle.main.path(forResource: language.bundleName, ofType: "lproj"),
  101. let bundle = Bundle(path: path) {
  102. bundle
  103. } else {
  104. Bundle.main
  105. }
  106. result[language] = bundle
  107. })
  108. }()
  109. var languageBundle: Bundle {
  110. languageBundleMap[curLang] ?? Bundle.main
  111. }
  112. init() {
  113. checkNewVersion()
  114. LNEventDeliver.addObserver(self)
  115. NotificationCenter.default.addObserver(
  116. forName: UIApplication.didEnterBackgroundNotification,
  117. object: nil, queue: .main)
  118. { [weak self] _ in
  119. guard let self else { return }
  120. isForeground = false
  121. }
  122. NotificationCenter.default.addObserver(
  123. forName: UIApplication.willEnterForegroundNotification,
  124. object: nil, queue: .main)
  125. { [weak self] _ in
  126. guard let self else { return }
  127. isForeground = true
  128. }
  129. }
  130. }
  131. extension LNAppConfig {
  132. func jumpToAppStore() {
  133. let appStoreJumpURL = "https://apps.apple.com/us/app/gamigo/id6756352551?action=write-review"
  134. guard let url = URL(string: appStoreJumpURL) else { return }
  135. if UIApplication.shared.canOpenURL(url) {
  136. UIApplication.shared.open(url, options: [:], completionHandler: nil)
  137. }
  138. }
  139. private func checkNewVersion() {
  140. let appStoreLookupURL = "https://itunes.apple.com/lookup?bundleId=\(curAppBundleIdentifier)"
  141. guard let url = URL(string: appStoreLookupURL) else {
  142. return
  143. }
  144. let task = URLSession.shared.dataTask(with: url)
  145. { [weak self] data, response,
  146. error in
  147. guard let self = self else { return }
  148. guard error == nil,
  149. let data else {
  150. return
  151. }
  152. if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
  153. let results = json["results"] as? [[String: Any]],
  154. let appStoreVersion = results.first?["version"] as? String {
  155. hasNewVersion = curAppVersion != appStoreVersion
  156. }
  157. }
  158. task.resume()
  159. }
  160. }
  161. extension LNAppConfig: LNNetworkMonitorNotify {
  162. func onNetworkStateChanged(state: LNNetworkState) {
  163. if case .available = state {
  164. checkNewVersion()
  165. }
  166. }
  167. }