diff --git a/ThimraTV.xcodeproj/project.pbxproj b/ThimraTV.xcodeproj/project.pbxproj index 0449cb5..468507f 100644 --- a/ThimraTV.xcodeproj/project.pbxproj +++ b/ThimraTV.xcodeproj/project.pbxproj @@ -262,6 +262,8 @@ 1BB91E0C2E04FD6A00A2C715 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 1BB91CD52E04FD6A00A2C715 /* GoogleService-Info.plist */; }; 1BB91E0E2E04FD6A00A2C715 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1BB91CD82E04FD6A00A2C715 /* LaunchScreen.storyboard */; }; 1BB91E0F2E04FD6A00A2C715 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1BB91CDA2E04FD6A00A2C715 /* Localizable.strings */; }; + 1BC1F0D32E09389000B579A4 /* SPVerisionUpdateAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BC1F0D22E09389000B579A4 /* SPVerisionUpdateAlertView.swift */; }; + 1BC1F0D52E093E9900B579A4 /* SPVersionUpdateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BC1F0D42E093E9900B579A4 /* SPVersionUpdateModel.swift */; }; 1BE7892B2DCB0E530001A8F1 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = 1BE7892A2DCB0E530001A8F1 /* FacebookCore */; }; 1BE7892D2DCB0E530001A8F1 /* FacebookLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 1BE7892C2DCB0E530001A8F1 /* FacebookLogin */; }; 1BF22FD12DC2169B0082429A /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 1BF22FD02DC2169B0082429A /* FirebaseAnalytics */; }; @@ -553,6 +555,8 @@ 1BB91D0A2E04FD6A00A2C715 /* ZKCycleScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZKCycleScrollView.swift; sourceTree = ""; }; 1BB91D0B2E04FD6A00A2C715 /* ZKCycleScrollViewFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZKCycleScrollViewFlowLayout.swift; sourceTree = ""; }; 1BB91D0E2E04FD6A00A2C715 /* ThimraTV.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ThimraTV.entitlements; sourceTree = ""; }; + 1BC1F0D22E09389000B579A4 /* SPVerisionUpdateAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPVerisionUpdateAlertView.swift; sourceTree = ""; }; + 1BC1F0D42E093E9900B579A4 /* SPVersionUpdateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPVersionUpdateModel.swift; sourceTree = ""; }; 1DBC40592DA4EDFC0093FCB0 /* ThimraTV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ThimraTV.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1F666DE0B12C863F26BE5027 /* Pods-MoviaBox.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MoviaBox.debug.xcconfig"; path = "Target Support Files/Pods-MoviaBox/Pods-MoviaBox.debug.xcconfig"; sourceTree = ""; }; A1174E10BCF2C606F7818792 /* Pods-ThimraTV.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ThimraTV.release.xcconfig"; path = "Target Support Files/Pods-ThimraTV/Pods-ThimraTV.release.xcconfig"; sourceTree = ""; }; @@ -915,6 +919,7 @@ children = ( 1BB91C542E04FD6A00A2C715 /* SPLanguageModel.swift */, 1BB91C552E04FD6A00A2C715 /* SPMineItem.swift */, + 1BC1F0D42E093E9900B579A4 /* SPVersionUpdateModel.swift */, ); path = Model; sourceTree = ""; @@ -1137,6 +1142,7 @@ children = ( 1BB91CB02E04FD6A00A2C715 /* SPAlertView.swift */, 1BB91CB12E04FD6A00A2C715 /* SPAlertWindowManager.swift */, + 1BC1F0D22E09389000B579A4 /* SPVerisionUpdateAlertView.swift */, ); path = Alert; sourceTree = ""; @@ -1528,10 +1534,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ThimraTV/Pods-ThimraTV-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ThimraTV/Pods-ThimraTV-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ThimraTV/Pods-ThimraTV-frameworks.sh\"\n"; @@ -1754,6 +1764,7 @@ 1BB91DC92E04FD6A00A2C715 /* SPCoinOrderRecordCell.swift in Sources */, 1BB91DCA2E04FD6A00A2C715 /* SPCoinRechargeBigCell.swift in Sources */, 1BB91DCB2E04FD6A00A2C715 /* SPCoinRechargeCell.swift in Sources */, + 1BC1F0D32E09389000B579A4 /* SPVerisionUpdateAlertView.swift in Sources */, 1BB91DCC2E04FD6A00A2C715 /* SPCoinRechargeSmallCell.swift in Sources */, 1BB91DCD2E04FD6A00A2C715 /* SPCoinRechargeView.swift in Sources */, 1BB91DCE2E04FD6A00A2C715 /* SPConsumptionRecordsCell.swift in Sources */, @@ -1799,6 +1810,7 @@ 1BB91DF62E04FD6A00A2C715 /* JXTransitionDelegateBridge.swift in Sources */, 1BB91DF72E04FD6A00A2C715 /* UIGestureRecognizer+JXTransition.swift in Sources */, 1BB91DF82E04FD6A00A2C715 /* UINavigationController+JXTransition.swift in Sources */, + 1BC1F0D52E093E9900B579A4 /* SPVersionUpdateModel.swift in Sources */, 1BB91DF92E04FD6A00A2C715 /* UIViewController+JXTransition.swift in Sources */, 1BB91DFA2E04FD6A00A2C715 /* JXUUID.m in Sources */, 1BB91DFB2E04FD6A00A2C715 /* PDKeyChain.m in Sources */, @@ -1857,9 +1869,11 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ThimraTV/Source/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ThimraTV; + INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The APP needs to access your location to recommend better short dramas for you"; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; + INFOPLIST_KEY_NSUserTrackingUsageDescription = "We will use your advertising identifier (IDFA) to provide a personalized advertising experience."; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; @@ -1903,9 +1917,11 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ThimraTV/Source/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = ThimraTV; + INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The APP needs to access your location to recommend better short dramas for you"; INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; + INFOPLIST_KEY_NSUserTrackingUsageDescription = "We will use your advertising identifier (IDFA) to provide a personalized advertising experience."; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; diff --git a/ThimraTV/AppDelegate/AppDelegate+OpenApp.swift b/ThimraTV/AppDelegate/AppDelegate+OpenApp.swift index 34ea052..3da54bc 100644 --- a/ThimraTV/AppDelegate/AppDelegate+OpenApp.swift +++ b/ThimraTV/AppDelegate/AppDelegate+OpenApp.swift @@ -47,7 +47,11 @@ extension SceneDelegate { private static var webpageURL: URL? func handleOpenAppMessage(webpageURL: URL?) { - guard SPNetworkReachabilityManager.manager.isReachable == true, AppDelegate.haveBeenShownAPNS, SPAPPTool.isAppOpen else { + guard SPNetworkReachabilityManager.manager.isReachable == true, + AppDelegate.haveBeenShownAPNS, + SPAPPTool.isAppOpen, + SPAPPTool.idfaAuthorizationFinish //idfa授权完成 + else { if let webpageURL = webpageURL { SceneDelegate.webpageURL = webpageURL } diff --git a/ThimraTV/Base/Controller/SPTabBarController.swift b/ThimraTV/Base/Controller/SPTabBarController.swift index 4dd55fc..46d1759 100644 --- a/ThimraTV/Base/Controller/SPTabBarController.swift +++ b/ThimraTV/Base/Controller/SPTabBarController.swift @@ -26,7 +26,14 @@ class SPTabBarController: UITabBarController { self.viewControllers = [nav1, nav2, nav3, nav4, nav5] + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + SPAPPTool.checkUpdates() + } + ///授权idfa + SPAPPTool.requestIDFAAuthorization { idfa in + + } } @@ -91,3 +98,5 @@ extension SPTabBarController { } } + + diff --git a/ThimraTV/Base/Define/SPAPPKey.swift b/ThimraTV/Base/Define/SPAPPKey.swift index bafd847..11e9c6f 100644 --- a/ThimraTV/Base/Define/SPAPPKey.swift +++ b/ThimraTV/Base/Define/SPAPPKey.swift @@ -8,4 +8,4 @@ import UIKit let kSPAppleAppId = "6745007239" -let kSPAppleDownloadPath = "https://apps.apple.com/app/id6670203263" +let kSPAppleDownloadPath = "https://apps.apple.com/app/id6745007239" diff --git a/ThimraTV/Base/Define/SPUserDefaultsKey.swift b/ThimraTV/Base/Define/SPUserDefaultsKey.swift index ab68533..419af4c 100644 --- a/ThimraTV/Base/Define/SPUserDefaultsKey.swift +++ b/ThimraTV/Base/Define/SPUserDefaultsKey.swift @@ -26,3 +26,6 @@ let kSPApnsAlertDefaultsKey = "kSPApnsAlertDefaultsKey" ///vip弹窗时间 let kSPVipAlertDateDefaultsKey = "kSPVipAlertDateDefaultsKey" + +///更新提示 +let kSPVersionUpdateAlertDefaultsKey = "kSPVersionUpdateAlertDefaultsKey" diff --git a/ThimraTV/Base/Networking/API/SPSettingAPI.swift b/ThimraTV/Base/Networking/API/SPSettingAPI.swift index 0ca0c45..e749830 100644 --- a/ThimraTV/Base/Networking/API/SPSettingAPI.swift +++ b/ThimraTV/Base/Networking/API/SPSettingAPI.swift @@ -34,5 +34,16 @@ class SPSettingAPI: NSObject { } + //获取版本更新数据 + static func requestVersionUpdateData(completer: ((_ model: SPVersionUpdateModel?) -> Void)?) { + + var param = SPNetworkParameters(path: "/customer/versionControl") + param.method = .get + param.isToast = false + + SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in + completer?(response.data) + } + } } diff --git a/ThimraTV/Base/Networking/Base/SPApi.swift b/ThimraTV/Base/Networking/Base/SPApi.swift index d4abfc6..b311dae 100644 --- a/ThimraTV/Base/Networking/Base/SPApi.swift +++ b/ThimraTV/Base/Networking/Base/SPApi.swift @@ -89,7 +89,7 @@ extension SPApi: TargetType { "brand" : "apple", //品牌 "app-name" : kSPAPPBundleIdentifier, "system-type" : "ios", - "idfa" : JXUUID.idfa(), + "idfa" : SPAPPTool.getIdfa(), "model" : UIDevice.sp_machineModelName(), // "security" : "false", ] diff --git a/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift b/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift new file mode 100644 index 0000000..2541c0b --- /dev/null +++ b/ThimraTV/Class/Mine/Model/SPVersionUpdateModel.swift @@ -0,0 +1,31 @@ +// +// SPVersionUpdateModel.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/6/23. +// + +import UIKit +import SmartCodable + +class SPVersionUpdateModel: SPModel, SmartCodable { + + var version_code: String? + var des: String? + var version_name: String? + + + + func canUpdate() -> Bool { + let currentCode = NSNumber(string: kSPAPPBundleVersion)?.intValue ?? 0 + let serverCode = NSNumber(string: version_code ?? "0")?.intValue ?? 0 + return serverCode > currentCode + } + + + static func mappingForKey() -> [SmartKeyTransformer]? { + return [ + CodingKeys.des <--- ["description"] + ] + } +} diff --git a/ThimraTV/Libs/APPTool/SPAPPTool.swift b/ThimraTV/Libs/APPTool/SPAPPTool.swift index 67d7016..b5a7e59 100644 --- a/ThimraTV/Libs/APPTool/SPAPPTool.swift +++ b/ThimraTV/Libs/APPTool/SPAPPTool.swift @@ -6,6 +6,8 @@ // import UIKit +import AppTrackingTransparency +import AdSupport class SPAPPTool: NSObject { @@ -119,3 +121,52 @@ extension SPAPPTool { } } + +///检查更新 +extension SPAPPTool { + static func checkUpdates() { +#if !DEBUG + if let date = UserDefaults.standard.object(forKey: kSPVersionUpdateAlertDefaultsKey) as? Date { + if date.vp_isToday { return } + } + UserDefaults.standard.set(Date(), forKey: kSPVersionUpdateAlertDefaultsKey) +#endif + + SPSettingAPI.requestVersionUpdateData { model in + guard let model = model else { return } + if model.canUpdate() { + self.showVersionUpdateAlert(model: model) + } + } + } + + static private func showVersionUpdateAlert(model: SPVersionUpdateModel) { + SPVerisionUpdateAlertView(model: model).show() + } +} + +///idfa授权 +extension SPAPPTool { + ///idfa是否授权结束 + static var idfaAuthorizationFinish = false + static var idfa: String? + + static func getIdfa() -> String { + if let idfa = idfa { + return idfa + } else { + return ASIdentifierManager.shared().advertisingIdentifier.uuidString + } + } + + static func requestIDFAAuthorization(completion: @escaping (String?) -> Void) { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { + ATTrackingManager.requestTrackingAuthorization { status in + idfaAuthorizationFinish = true + SPAPPTool.idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString + SPAPPTool.sceneDelegate?.retryHandleOpenAppMessage() + completion(idfa) + } + } + } +} diff --git a/ThimraTV/Libs/Alert/SPVerisionUpdateAlertView.swift b/ThimraTV/Libs/Alert/SPVerisionUpdateAlertView.swift new file mode 100644 index 0000000..d77f702 --- /dev/null +++ b/ThimraTV/Libs/Alert/SPVerisionUpdateAlertView.swift @@ -0,0 +1,169 @@ +// +// SPVerisionUpdateAlertView.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/6/23. +// + +import UIKit + +class SPVerisionUpdateAlertView: SPAlertView { + + private var model: SPVersionUpdateModel + + private lazy var bgImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "alert_bg_image_03")) + imageView.isUserInteractionEnabled = true + return imageView + }() + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "close_icon_02"), for: .normal) + button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside) + return button + }() + + private lazy var versionContainerView: UIView = { + let view = UIView() + return view + }() + + private lazy var versionTitleLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 18) + label.textColor = .colorFFFFFF() + label.text = "movia_updatenowtitle".localized + return label + }() + + private lazy var versionBgView: UIView = { + let view = UIView() + view.backgroundColor = .colorFF3232() + view.layer.cornerRadius = 9 + view.layer.masksToBounds = true + return view + }() + + private lazy var versionLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.textColor = .colorFFFFFF() + return label + }() + + private lazy var desLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 14) + label.textColor = .colorA8B8C3() + label.numberOfLines = 0 + label.textAlignment = .center + return label + }() + + private lazy var button: UIButton = { + let button = UIButton(type: .custom) + button.backgroundColor = .colorFF3232() + button.setTitle("movia_updatenow".localized, for: .normal) + button.setTitleColor(.colorFFFFFF(), for: .normal) + button.titleLabel?.font = .fontMedium(ofSize: 16) + button.layer.cornerRadius = 21 + button.layer.masksToBounds = true + button.addTarget(self, action: #selector(handleButton), for: .touchUpInside) + return button + }() + + init(model: SPVersionUpdateModel) { + self.model = model + super.init(frame: .zero) + versionLabel.text = "v\(model.version_name ?? "")" + desLabel.text = model.des?.localized + + sp_setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func handleCloseButton() { + self.dismiss() + } + + @objc private func handleButton() { + self.dismiss() + guard let url = URL(string: kSPAppleDownloadPath) else { return } + let application = UIApplication.shared + if application.canOpenURL(url) { + application.open(url) + } + } + +} + +extension SPVerisionUpdateAlertView { + + private func sp_setupUI() { + self.addSubview(contentView) + contentView.addSubview(bgImageView) + contentView.addSubview(closeButton) + contentView.addSubview(versionContainerView) + versionContainerView.addSubview(versionTitleLabel) + versionContainerView.addSubview(versionBgView) + versionBgView.addSubview(versionLabel) + bgImageView.addSubview(desLabel) + bgImageView.addSubview(button) + + contentView.snp.makeConstraints { make in + make.center.equalToSuperview() + } + + bgImageView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview().offset(-24) +// make.bottom.equalToSuperview() + } + + closeButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(bgImageView.snp.bottom).offset(22) + make.bottom.equalToSuperview() + } + + versionContainerView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(80) + } + + versionTitleLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview() + } + + versionBgView.snp.makeConstraints { make in + make.top.bottom.equalToSuperview() + make.height.equalTo(18) + make.left.equalTo(versionTitleLabel.snp.right).offset(6) + make.right.equalToSuperview() + } + + versionLabel.snp.makeConstraints { make in + make.center.equalToSuperview() + make.left.equalToSuperview().offset(8) + } + + desLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-20) + make.centerY.equalToSuperview().offset(5 + 12) + } + + button.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.width.equalTo(243) + make.height.equalTo(42) + make.bottom.equalToSuperview().offset(-32) + } + } + +} diff --git a/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/Contents.json b/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/Contents.json new file mode 100644 index 0000000..69e57cd --- /dev/null +++ b/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "配图@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "配图.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/配图.png b/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/配图.png new file mode 100644 index 0000000..b83e1fd Binary files /dev/null and b/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/配图.png differ diff --git a/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/配图@2x.png b/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/配图@2x.png new file mode 100644 index 0000000..1c23476 Binary files /dev/null and b/ThimraTV/Source/Assets.xcassets/image/alert_bg_image_03.imageset/配图@2x.png differ diff --git a/ThimraTV/Source/Info.plist b/ThimraTV/Source/Info.plist index 80efff0..4e93b72 100644 --- a/ThimraTV/Source/Info.plist +++ b/ThimraTV/Source/Info.plist @@ -29,8 +29,6 @@ $(PRODUCT_NAME) FirebaseAppDelegateProxyEnabled - ITSAppUsesNonExemptEncryption - LSApplicationQueriesSchemes fbapi diff --git a/ThimraTV/Source/en.lproj/Localizable.strings b/ThimraTV/Source/en.lproj/Localizable.strings index 57e2210..0e0ca68 100644 --- a/ThimraTV/Source/en.lproj/Localizable.strings +++ b/ThimraTV/Source/en.lproj/Localizable.strings @@ -122,6 +122,8 @@ "quarter_short_type" = "Quarterly "; "year_short_type" = "Yearly"; "movia_profile_Bonus" = "Bonus"; +"movia_updatenowtitle" = "Discover a new version"; +"movia_updatenow" = "Update Now"; "movia_vip_alert_text_01" = "Short Drama VIP Exclusive";