// // LNAppConfig.swift // Lanu // // Created by OneeChan on 2025/11/6. // import Foundation import Combine enum LNAppEnvType: Codable, CaseIterable { case test case official var text: String { switch self { case .test: "测试环境" case .official: "线上环境" } } } enum LNAppLanguage: Codable { case chiness case english case indonesian var text: String { switch self { case .chiness: "中文" case .english: "English" case .indonesian: "Bahasa Indonesia" } } var bundleName: String { switch self { case .chiness: "zh-Hans" case .english: "en" case .indonesian: "id" } } var languageCode: String { switch self { case .chiness: "zh" case .english: "en" case .indonesian: "id" } } var countryCode: String { switch self { case .chiness: "CN" case .english: "US" case .indonesian: "ID" } } var isSelected: Bool { self == LNAppConfig.shared.curLang } static var available: [LNAppLanguage] { [.chiness, .english, .indonesian] } } class LNAppConfig { static var shared = LNAppConfig() @Published private(set) var hasNewVersion = false private(set) var isForeground = true { didSet { LNEventDeliver.notifyEvent { ($0 as? LNAppMainEvent)?.onAppStateChanged(foreground: self.isForeground) } } } var curEnv: LNAppEnvType = LNUserDefaults[.appEnv, .official] { didSet { LNUserDefaults[.appEnv] = curEnv } } var countryCode: String { if #available(iOS 16.0, *) { Locale.current.region?.identifier ?? "" } else { Locale.current.regionCode ?? "" } } private static var defaultLanguage: LNAppLanguage { let lang = Locale.preferredLanguages.first ?? "en" return if lang == LNAppLanguage.chiness.bundleName { .chiness } else if lang == LNAppLanguage.indonesian.bundleName { .indonesian } else { .english } } var curLang: LNAppLanguage = LNUserDefaults[.appLanguage, defaultLanguage] { didSet { guard oldValue != curLang else { return } LNUserDefaults[.appLanguage] = curLang LNEventDeliver.notifyEvent { ($0 as? LNAppMainEvent)?.onAppLanguageChanged(newLanguage: self.curLang) } } } var languageBundleMap: [LNAppLanguage: Bundle] = { LNAppLanguage.available.reduce(into: [LNAppLanguage: Bundle](), { result, language in let bundle = if let path = Bundle.main.path(forResource: language.bundleName, ofType: "lproj"), let bundle = Bundle(path: path) { bundle } else { Bundle.main } result[language] = bundle }) }() var languageBundle: Bundle { languageBundleMap[curLang] ?? Bundle.main } init() { checkNewVersion() LNEventDeliver.addObserver(self) NotificationCenter.default.addObserver( forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: .main) { [weak self] _ in guard let self else { return } isForeground = false } NotificationCenter.default.addObserver( forName: UIApplication.willEnterForegroundNotification, object: nil, queue: .main) { [weak self] _ in guard let self else { return } isForeground = true } } } extension LNAppConfig { func jumpToAppStore() { let appStoreJumpURL = "https://apps.apple.com/us/app/gamigo/id6756352551?action=write-review" guard let url = URL(string: appStoreJumpURL) else { return } if UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } } private func checkNewVersion() { let appStoreLookupURL = "https://itunes.apple.com/lookup?bundleId=\(curAppBundleIdentifier)" guard let url = URL(string: appStoreLookupURL) else { return } let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in guard let self = self else { return } guard error == nil, let data else { return } if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let results = json["results"] as? [[String: Any]], let appStoreVersion = results.first?["version"] as? String { hasNewVersion = curAppVersion != appStoreVersion } } task.resume() } } extension LNAppConfig: LNNetworkMonitorNotify { func onNetworkStateChanged(state: LNNetworkState) { if case .available = state { checkNewVersion() } } }