"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
- MARKETING_VERSION = 1.0.5;
+ MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.deepchords.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
- MARKETING_VERSION = 1.0.5;
+ MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.deepchords.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
+++ /dev/null
-//
-// LanuageCache.swift
-// ShenYin
-//
-// Created by liangshi on 2025/11/11.
-//
-
-class LanuageCache{
- static let key = "LanuageCache"
- static func save(lan:AppSupportLanguage){
- UserDefaults.standard.set(lan.title, forKey: key)
- UserDefaults.standard.synchronize()
- }
- static func get()->AppSupportLanguage{
- if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
- for item in AppSupportLanguage.all {
- if item.title == text{
- return item
- }
- }
- }
-
-
- //手机设置的语言
- let list = NSLocale.preferredLanguages
- Logger.debug(list)
- guard let item = list.first else{
- return .chinse
- }
-
- if item.contains("zh-Hans") {
- return .chinse
- }else if item.contains("zh-Hant") {
- return .Traditional_Chinese
- }else if item.hasPrefix("en") {
- return .english
- }else if item.hasPrefix("ja") {
- return .japanese
- }else if item.hasSuffix("fr") {
- return .french
- }else if item == "es" {
- return .english
- }
- else if item == "vi" {
- return .vietnam
- }
- else if item == "th" {
- return .thai
- }
- else if item == "ms" {
- return .malay
- }
- else if item == "tl" {
- return .Filipino
- }
- else if item == "id" {
- return .indonesian
- }
- else if item == "ru" {
- return .russian
- }
- return .english
- }
-}
-class BannerCache {
- static let shared = BannerCache()
- private let userDefaults = UserDefaults.standard
- private let deviceListKey = "BannerCache"
-
- func saveList(_ list: [BannerModel]) {
- let encoder = NSKeyedArchiver.archivedData(withRootObject: list)
- userDefaults.set(encoder, forKey: deviceListKey)
- userDefaults.synchronize()
- }
-
- func get() -> [BannerModel] {
- if let data = userDefaults.data(forKey: deviceListKey),
- let deviceList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [BannerModel] {
- return deviceList
- }
- return []
- }
-}
+
}
-class CountryCache {
- static let shared = CountryCache()
- private let userDefaults = UserDefaults.standard
- private let deviceListKey = "CountryCache"
-
- func saveList(_ list: [CountryModel]) {
- let encoder = NSKeyedArchiver.archivedData(withRootObject: list)
- userDefaults.set(encoder, forKey: deviceListKey)
- userDefaults.synchronize()
- }
-
- func get() -> [CountryModel] {
- if let data = userDefaults.data(forKey: deviceListKey),
- let deviceList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [CountryModel] {
- return deviceList
- }
- return []
- }
-}
-class SubTitleCache {
- static let shared = SubTitleCache()
- private let userDefaults = UserDefaults.standard
- private let key = "SubTitleCache"
-
- func save(_ model: SubTitleCacheModel) {
- let encoder = NSKeyedArchiver.archivedData(withRootObject: model)
- userDefaults.set(encoder, forKey: key)
- userDefaults.synchronize()
- }
-
- func get() -> SubTitleCacheModel {
- if let data = userDefaults.data(forKey: key),
- let model = NSKeyedUnarchiver.unarchiveObject(with: data) as? SubTitleCacheModel {
- return model
- }
- else{
- let model = SubTitleCacheModel()
- return model
- }
- }
-}
--- /dev/null
+//
+// TipsCache.swift
+// ShenYin
+//
+// Created by liangshi on 2025/9/26.
+//
+
+class TipsCache{
+ static func needShow(type:RecordTipsType,show:Bool){
+ UserDefaults.standard.set(show, forKey: type.title)
+ UserDefaults.standard.synchronize()
+ }
+ static func needShow(type:RecordTipsType)->Bool{
+ if let value = UserDefaults.standard.value(forKey: type.title){
+ return value as? Bool ?? false
+ }
+ return true
+ }
+}
+
+class CommonTipsCache{
+ enum CommonTipsType:Int{
+ case light
+ var title:String{
+ switch self {
+ case .light:
+ return "亮度"
+
+ }
+ }
+ }
+ static func needShow(type:CommonTipsType,show:Bool){
+ UserDefaults.standard.set(show, forKey: type.title)
+ UserDefaults.standard.synchronize()
+ }
+ static func needShow(type:CommonTipsType)->Bool{
+ if let value = UserDefaults.standard.value(forKey: type.title){
+ return value as? Bool ?? false
+ }
+ return true
+ }
+}
+
+class FontCache{
+ static func saveFont(type:FontType){
+ UserDefaults.standard.set(type.rawValue, forKey: "FontCache")
+ UserDefaults.standard.synchronize()
+ }
+ static func getFont()->FontType{
+ if let value = UserDefaults.standard.value(forKey: "FontCache"),let font = value as? Int {
+ return FontType(rawValue: font) ?? .stand
+ }
+ return FontType.stand
+ }
+}
+
+class RoleCache{
+ static let key = "RoleCache"
+ static func save(type:String){
+ UserDefaults.standard.set(type, forKey: key)
+ UserDefaults.standard.synchronize()
+ }
+ static func get()->String?{
+ if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
+ return text
+ }
+ return nil
+ }
+}
+class BackgroundCache{
+ static func save(model:BackgroundModel){
+ UserDefaults.standard.set(model.bgPath, forKey: "BackgroundCache_url")
+ UserDefaults.standard.set(model.themeColor, forKey: "BackgroundCache_color")
+ UserDefaults.standard.synchronize()
+ }
+ static func get()->(BackgroundModel)?{
+ if let url = UserDefaults.standard.value(forKey: "BackgroundCache_url") as? String , let color = UserDefaults.standard.value(forKey: "BackgroundCache_color") as? String{
+ let model = BackgroundModel()
+ model.themeColor = color
+ model.bgPath = url
+ return model
+ }
+ return nil
+ }
+}
+class RecordTipSaveCache{
+ static let key = "AutoRecordCache"
+ static func save(value:Bool){
+ let obj = value ? "1":"0"
+ UserDefaults.standard.set(obj, forKey: key)
+ UserDefaults.standard.synchronize()
+ }
+ static func get()->Bool{
+ if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
+ return text == "1"
+ }
+ return true
+ }
+}
+class FirstLuanceCache{
+ static let key = "FirstLuanceCache"
+ static private func save(){
+ let obj = "1"
+ UserDefaults.standard.set(obj, forKey: key)
+ UserDefaults.standard.synchronize()
+ }
+ static func isFirst()->Bool{
+ if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
+ return false
+ }
+ save()
+ return true
+ }
+}
+class UpdateCache{
+ static let key = "UpdateCache"
+ static func save(version:String){
+ UserDefaults.standard.set("1", forKey: key+version)
+ UserDefaults.standard.synchronize()
+ }
+ static func isSkip(version:String)->Bool{
+ if UserDefaults.standard.value(forKey: key+version) != nil{
+ return true
+ }
+ return false
+ }
+}
+class LanuageCache{
+ static let key = "LanuageCache"
+ static func save(lan:AppSupportLanguage){
+ UserDefaults.standard.set(lan.title, forKey: key)
+ UserDefaults.standard.synchronize()
+ }
+ static func get()->AppSupportLanguage{
+ if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
+ for item in AppSupportLanguage.all {
+ if item.title == text{
+ return item
+ }
+ }
+ }
+
+
+ //手机设置的语言
+ let list = NSLocale.preferredLanguages
+ Logger.debug(list)
+ guard let item = list.first else{
+ return .chinse
+ }
+
+ if item.contains("zh-Hans") {
+ return .chinse
+ }else if item.contains("zh-Hant") {
+ return .Traditional_Chinese
+ }else if item.hasPrefix("en") {
+ return .english
+ }else if item.hasPrefix("ja") {
+ return .japanese
+ }else if item.hasSuffix("fr") {
+ return .french
+ }else if item == "es" {
+ return .english
+ }
+ else if item == "vi" {
+ return .vietnam
+ }
+ else if item == "th" {
+ return .thai
+ }
+ else if item == "ms" {
+ return .malay
+ }
+ else if item == "tl" {
+ return .Filipino
+ }
+ else if item == "id" {
+ return .indonesian
+ }
+ else if item == "ru" {
+ return .russian
+ }
+ return .english
+ }
+}
+class CountryCache {
+ static let shared = CountryCache()
+ private let userDefaults = UserDefaults.standard
+ private let deviceListKey = "CountryCache"
+
+ func saveList(_ list: [CountryModel]) {
+ let encoder = NSKeyedArchiver.archivedData(withRootObject: list)
+ userDefaults.set(encoder, forKey: deviceListKey)
+ userDefaults.synchronize()
+ }
+
+ func get() -> [CountryModel] {
+ if let data = userDefaults.data(forKey: deviceListKey),
+ let deviceList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [CountryModel] {
+ return deviceList
+ }
+ return []
+ }
+}
+class BannerCache {
+ static let shared = BannerCache()
+ private let userDefaults = UserDefaults.standard
+ private let deviceListKey = "BannerCache"
+
+ func saveList(_ list: [BannerModel]) {
+ let encoder = NSKeyedArchiver.archivedData(withRootObject: list)
+ userDefaults.set(encoder, forKey: deviceListKey)
+ userDefaults.synchronize()
+ }
+
+ func get() -> [BannerModel] {
+ if let data = userDefaults.data(forKey: deviceListKey),
+ let deviceList = NSKeyedUnarchiver.unarchiveObject(with: data) as? [BannerModel] {
+ return deviceList
+ }
+ return []
+ }
+}
+class SubTitleCache {
+ static let shared = SubTitleCache()
+ private let userDefaults = UserDefaults.standard
+ private let key = "SubTitleCache"
+
+ func save(_ model: SubTitleCacheModel) {
+ let encoder = NSKeyedArchiver.archivedData(withRootObject: model)
+ userDefaults.set(encoder, forKey: key)
+ userDefaults.synchronize()
+ }
+
+ func get() -> SubTitleCacheModel {
+ if let data = userDefaults.data(forKey: key),
+ let model = NSKeyedUnarchiver.unarchiveObject(with: data) as? SubTitleCacheModel {
+ return model
+ }
+ else{
+ let model = SubTitleCacheModel()
+ return model
+ }
+ }
+}
+++ /dev/null
-//
-// TipsCache.swift
-// ShenYin
-//
-// Created by liangshi on 2025/9/26.
-//
-
-class TipsCache{
- static func needShow(type:RecordTipsType,show:Bool){
- UserDefaults.standard.set(show, forKey: type.title)
- UserDefaults.standard.synchronize()
- }
- static func needShow(type:RecordTipsType)->Bool{
- if let value = UserDefaults.standard.value(forKey: type.title){
- return value as? Bool ?? false
- }
- return true
- }
-}
-
-class CommonTipsCache{
- enum CommonTipsType:Int{
- case light
- var title:String{
- switch self {
- case .light:
- return "亮度"
-
- }
- }
- }
- static func needShow(type:CommonTipsType,show:Bool){
- UserDefaults.standard.set(show, forKey: type.title)
- UserDefaults.standard.synchronize()
- }
- static func needShow(type:CommonTipsType)->Bool{
- if let value = UserDefaults.standard.value(forKey: type.title){
- return value as? Bool ?? false
- }
- return true
- }
-}
-
-class FontCache{
- static func saveFont(type:FontType){
- UserDefaults.standard.set(type.rawValue, forKey: "FontCache")
- UserDefaults.standard.synchronize()
- }
- static func getFont()->FontType{
- if let value = UserDefaults.standard.value(forKey: "FontCache"),let font = value as? Int {
- return FontType(rawValue: font) ?? .stand
- }
- return FontType.stand
- }
-}
-
-class RoleCache{
- static let key = "RoleCache"
- static func save(type:String){
- UserDefaults.standard.set(type, forKey: key)
- UserDefaults.standard.synchronize()
- }
- static func get()->String?{
- if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
- return text
- }
- return nil
- }
-}
-class BackgroundCache{
- static func save(model:BackgroundModel){
- UserDefaults.standard.set(model.bgPath, forKey: "BackgroundCache_url")
- UserDefaults.standard.set(model.themeColor, forKey: "BackgroundCache_color")
- UserDefaults.standard.synchronize()
- }
- static func get()->(BackgroundModel)?{
- if let url = UserDefaults.standard.value(forKey: "BackgroundCache_url") as? String , let color = UserDefaults.standard.value(forKey: "BackgroundCache_color") as? String{
- let model = BackgroundModel()
- model.themeColor = color
- model.bgPath = url
- return model
- }
- return nil
- }
-}
-class RecordTipSaveCache{
- static let key = "AutoRecordCache"
- static func save(value:Bool){
- let obj = value ? "1":"0"
- UserDefaults.standard.set(obj, forKey: key)
- UserDefaults.standard.synchronize()
- }
- static func get()->Bool{
- if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
- return text == "1"
- }
- return true
- }
-}
-class FirstLuanceCache{
- static let key = "FirstLuanceCache"
- static private func save(){
- let obj = "1"
- UserDefaults.standard.set(obj, forKey: key)
- UserDefaults.standard.synchronize()
- }
- static func isFirst()->Bool{
- if let value = UserDefaults.standard.value(forKey: key),let text = value as? String {
- return false
- }
- save()
- return true
- }
-}
static let yonghuBaseURL = "https://pub-tos.deepchords.com"
- static let revokeText = "请您确保您是有权进行本撤回同意隐私政策操作的相关当事人。撤回同意隐私政策,您将放弃以下资产或者权益:\n\n1.数据清空\n将会停止收集您的个人信息。您使用DeepChords应用过程中产生的数据将被清空;手机中DeepChords应用的缓存数据将被清除。\n\n2.设备解除绑定\nDeepChords账号中,所有设备会与您当前登录的账号解除绑定,并清除设备之前存储在服务器的数据。存储在物理设备中的数据请通过人工本地物理重置来清除。如果您需要重新使用设备,需要您再次进行绑定并且重新授权。\n\n3.其他\n此举还将撤回您对用户协议的同意,并退出DeepChords应用。\n\n请您知悉,撤回同意隐私政策不代表撤回同意前的相关行为和责任得到豁免或减轻。若您需要重新在该账号管理设备,需要您重新授权并绑定。请谨慎操作!"
+ static let revokeText = "请您确保您是有权进行本撤回同意隐私政策操作的相关当事人。撤回同意隐私政策,您将放弃以下资产或者权益:\n\n1.数据清空\n将会停止收集您的个人信息。您使用PAXA应用过程中产生的数据将被清空;手机中PAXA应用的缓存数据将被清除。\n\n2.设备解除绑定\nPAXA账号中,所有设备会与您当前登录的账号解除绑定,并清除设备之前存储在服务器的数据。存储在物理设备中的数据请通过人工本地物理重置来清除。如果您需要重新使用设备,需要您再次进行绑定并且重新授权。\n\n3.其他\n此举还将撤回您对用户协议的同意,并退出PAXA应用。\n\n请您知悉,撤回同意隐私政策不代表撤回同意前的相关行为和责任得到豁免或减轻。若您需要重新在该账号管理设备,需要您重新授权并绑定。请谨慎操作!"
static let findText = "查找耳机".l10n
static let deviceType = "耳机".l10n
static let serviceLogo = "logo_2"
LoginVM.fetchCountryList {result in
}
-// AppUpdateVM.shared.checkedUpdate()
+ AppUpdateVM.shared.autoCheckedUpdate()
}
@MainActor static func setupKeyboard(){
cell.bgView.yc.setCorners(withRoundedRect: rect, roundingCorners: [.allCorners], cornerRadii: CGSize(width: 12, height: 12))
}
+
+ if list[indexPath.section][indexPath.row] == .update ,let model = AppUpdateVM.shared.updateModel{
+ cell.unReadIcon.isHidden = !model.newVersioon
+ cell.valueLabel.text = "版本:" + model.targetVersion
+ cell.valueLabel.isHidden = cell.unReadIcon.isHidden
+ }
+ else{
+ cell.unReadIcon.isHidden = true
+ cell.valueLabel.isHidden = cell.unReadIcon.isHidden
+ }
+
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+++ /dev/null
-//
-// BannerModel.swift
-// ShenYin
-//
-// Created by liangshi on 2025/10/21.
-//
-
var description = ""
var fileList = [AppUpdateFileModel]()
required public init() { }
+
+ var newVersioon:Bool{
+ return targetVersion.uppercased() > sourceVersion.uppercased()
+ }
}
class AppUpdateFileModel:HandyJSON {
var url = ""
class AppUpdateVM:BaseVM{
static let shared = AppUpdateVM()
+ var updateModel:AppUpdateModel?
+
func checkedUpdate(){
var params:[String:Any] = [:]
params["sourceVersion"] = Bundle.main.appVersion ?? "1.0.0"
YLprogressHUD.hidden()
guard let self = self else {return}
if model.isSuccess{
- if model.data.targetVersion.uppercased() > model.data.sourceVersion.uppercased(){
+ self.updateModel = model.data
+ if model.data.newVersioon{
if model.data.updateType == "0"{
//可选升级
- optionUpdate()
+ optionUpdate(model: model.data)
}
else{
//强制升级
- forceUpdate()
+ forceUpdate(model: model.data)
}
}
else{
}
}
}
- func optionUpdate(){
- CustomAlert.showWith(title: nil, messgage: "检测到新版本,是否前往更新".l10n) {
+ func autoCheckedUpdate(){
+ var params:[String:Any] = [:]
+ params["sourceVersion"] = Bundle.main.appVersion ?? "1.0.0"
+ params["platform"] = "iOS"
+ YLprogressHUD.showLoading()
+ HttpClient.request(.otaTaskApp(param: params)) {[weak self](model:AppUpdateModelRoot,res) in
+ YLprogressHUD.hidden()
+ guard let self = self else {return}
+ if model.isSuccess{
+ self.updateModel = model.data
+ if model.data.newVersioon{
+ if model.data.updateType == "0"{
+ autoOptionUpdate(model: model.data)
+ }
+ else{
+ forceUpdate(model: model.data)
+ }
+ }
+ else{
+ YLprogressHUD.showAutoHiden("已经是最新版本".l10n)
+ }
+ }
+ else{
+ YLprogressHUD.showAutoHiden("请求失败".l10n)
+ }
+ }
+ }
+
+
+ private func autoOptionUpdate(model:AppUpdateModel){
+ if !UpdateCache.isSkip(version: model.targetVersion) {
+ CustomAlert.showWith(title: "发现新版本".l10n, messgage: model.description,cancel:"稍后".l10n,ok: "立即更新".l10n) {
+ UpdateCache.save(version: model.targetVersion)
+ } okCallback: {
+ guard let url = CCConfig.appStoreLink.yc.asUrl else{
+ return
+ }
+ UIApplication.shared.open(url)
+ }
+ }
+ }
+
+
+ private func optionUpdate(model:AppUpdateModel){
+ CustomAlert.showWith(title: "发现新版本".l10n, messgage: model.description,cancel:"稍后".l10n,ok: "立即更新".l10n) {
} okCallback: {
guard let url = CCConfig.appStoreLink.yc.asUrl else{
}
}
- func forceUpdate(){
- CustomAlert.showWith(title: nil, messgage: "检测到新版本".l10n, ok: "前往更新".l10n,cancelCallback: nil) {
+ private func forceUpdate(model:AppUpdateModel){
+ CustomAlert.showWith(title: "发现新版本".l10n, messgage: model.description, ok: "立即更新".l10n,cancelCallback: nil) {
guard let url = CCConfig.appStoreLink.yc.asUrl else{
return
}
let nextIcon = UIImageView()
let valueIcon = UIImageView()
let valueLabel = UILabel()
+ var unReadIcon = UIView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func setupViews() {
contentView.addSubview(bgView)
- bgView.addSubviews([titleLabel,nextIcon,valueIcon,valueLabel])
+ bgView.addSubviews([titleLabel,nextIcon,valueIcon,valueLabel,unReadIcon])
backgroundColor = .color(.bgColor)
contentView.backgroundColor = .clear
v.isHidden = true
}
nextIcon.image = UIImage(named: "arrow_next")
+ unReadIcon.do { v in
+ v.yc.setCornerRadius(3)
+ v.backgroundColor = .red
+ v.isHidden = true
+ }
}
override func setupLayout() {
m.height.equalToSuperview()
m.left.equalToSuperview().inset(90)
}
+ unReadIcon.snp.makeConstraints { (m) in
+ m.size.equalTo(6)
+ m.right.equalToSuperview().inset(30)
+ m.centerY.equalToSuperview()
+ }
}
}
"用户须知":"",
"首次使用请先开启手机蓝牙,搜索并配对设备。然后打开 APP,点击“添加设备”,找到对应产品完成连接,即可正常使用全部功能。":"",
"了解并继续":"",
+ "发现新版本":"",
+ "立即更新":"",
+ "稍后":"",
+ "版本":"",
]