// // Tools.swift // Crush // // Created by Leon on 2025/7/12. // import Foundation import AdSupport import AppTrackingTransparency /// 常用工具和常用字典。 class CLTool { static let shared = CLTool() var appVersion: AppVersion? static func clearTempFolder() { let fileManager = FileManager.default let tempFolderPath = NSTemporaryDirectory() do { let filePaths = try fileManager.contentsOfDirectory(atPath: tempFolderPath) for filePath in filePaths { // dlog("filaPath: \(filePath)") try fileManager.removeItem(atPath: NSTemporaryDirectory() + filePath) } } catch let error as NSError { print("Could not clear temp folder: \(error.debugDescription)") } } static func feedbackGenerator() { if #available(iOS 13.0, *) { let gen = UIImpactFeedbackGenerator(style: .medium) // light震动效果的强弱 gen.prepare() // 反馈延迟最小化 gen.impactOccurred() // 触发效果 } } static func syncInputTintColor() { UITextField.appearance().tintColor = .blue UITextView.appearance().tintColor = .blue } // MARK: - public public func requestAppVersion(block: ((_ appVer: AppVersion?) -> Void)?) { if let appVer = appVersion { block?(appVer) return } // CommonProvider.request(.appVersionGet, modelType: AppVersion.self, autoShowErrMsg: false) { [weak self] result in // switch result { // case let .success(model): // self?.appVersion = model // block?(model) // break // case .failure: // break // } // } } public func findLocaliezedNameBy(code: String) -> String? { // for per in langNameCodes { // if per.langCode == code { // return per.codeName // } // } return nil } static func syncSystemLanguage() { } /// 多语言适配 static func syncAppLanuage(lan: Languages, completion: ((_ result: Bool) -> Void)?) { // MeProvider.request(.updateLanguage(lang: lan.rawValue), modelType: String.self, autoShowErrMsg: false) { result in // switch result { // case .success: // completion?(true) // break // case .failure: // completion?(false) // break // } // } } /// 通过regionCode来决定国家显示名称 static func getLocalizedCountryName(localeIdentifier: String?) -> String { guard let identi = localeIdentifier else { return "" } var regionCode = "en" // 获取设备的国家Code if let currentRegionCode = Locale.current.regionCode { regionCode = currentRegionCode } let locale = Locale(identifier: regionCode) if let localisedCountryName = locale.localizedString(forRegionCode: identi) { return localisedCountryName } else { dlog("⚠️无法localize国家:\(identi)") return "" } } static func getLocalizedCountryNameByPreferLan(localeIdentifier: String?) -> String { guard let identi = localeIdentifier else { return "" } guard let lan = Languages.preferedLans.first else { return "" } let locale = Locale(identifier: Languages.regionCode(lan: lan)) if let localisedCountryName = locale.localizedString(forRegionCode: identi) { return localisedCountryName } else { dlog("Languages Prefer lan 's locale country name get failed ❌:\(identi) 采用备选方案根据Locale.current来获取") return getLocalizedCountryName(localeIdentifier: localeIdentifier) } } // MARK: - helper. } extension CLTool { static func idfaSetupReport() { if #available(iOS 14, *) { ATTrackingManager.requestTrackingAuthorization { status in switch status { case .denied: debugPrint("【IDFA】用户拒绝") break case .authorized: debugPrint("【IDFA】用户允许:❇️IDFA: \(ASIdentifierManager.shared().advertisingIdentifier.uuidString)❇️") CLTool.tryReportIDFA() break case .notDetermined: debugPrint("【IDFA】用户没有选择") default: break } } } else { // iOS13及之前版本,继续用以前的方式 if ASIdentifierManager.shared().isAdvertisingTrackingEnabled { // debugPrint("可以获取:\(ASIdentifierManager.shared().advertisingIdentifier.uuidString)") CLTool.tryReportIDFA() } else { debugPrint("【IDFA】用户未打开IDFA开关") } } } fileprivate static func tryReportIDFA() { let str = ASIdentifierManager.shared().advertisingIdentifier.uuidString if str.contains("0000-0000-0000") || str.count == 0 { return } if let isSubmmited = AppCache.fetchCache(key: CacheKey.boolIdfaSubmmited.rawValue, type: Bool.self), isSubmmited == true { return } // ComplexProvider.request(.reportIDFA(str: str), modelType: String.self, autoShowErrMsg: false) { result in // switch result { // case let .success(model): // dlog(model) // AppCache.cache(key: CacheKey.boolIdfaSubmmited.rawValue, value: true) // break // case .failure: // break // } // } } } // MARK: Sandbox extension CLTool{ static func m4aFileToBase64(fileURL: URL?) -> String? { guard let fileURL = fileURL else { dlog("文件 URL 为空") return nil } do { let data = try Data(contentsOf: fileURL) let base64String = data.base64EncodedString() return base64String } catch { dlog("读取或转换失败: \(error)") return nil } } }