Jelajahi Sumber

1.2(2)打包上架

100Years 1 bulan lalu
induk
melakukan
0828defce4
32 mengubah file dengan 345 tambahan dan 373 penghapusan
  1. 4 8
      AIRingtone.xcodeproj/project.pbxproj
  2. 1 1
      AIRingtone.xcodeproj/xcshareddata/xcschemes/AIRingtone.xcscheme
  3. TEMPAT SAMPAH
      AIRingtone/Assets.xcassets/VIP/vip_icon_white.imageset/vip_icon_white@2x.png
  4. TEMPAT SAMPAH
      AIRingtone/Assets.xcassets/VIP/vip_icon_white.imageset/vip_icon_white@3x.png
  5. 6 16
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVC.swift
  6. 1 0
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/View/TSAIPhotoImageCell.swift
  7. 1 1
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoVC.swift
  8. 2 6
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC.swift
  9. 38 10
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGenneralPicVM.swift
  10. 8 23
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/TSTextGeneralPicVC.swift
  11. 0 1
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/VM/TSTextGeneralPicVM.swift
  12. 11 9
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptTextView.swift
  13. 3 9
      AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVC.swift
  14. 4 16
      AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVM.swift
  15. 7 28
      AIRingtone/Business/TSAIRintoneVC/TSTextGeneralRintoneVC/TSTextGeneralRintoneVC.swift
  16. 5 23
      AIRingtone/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift
  17. 1 1
      AIRingtone/Business/TSSetingVC/SetingVC/TSSetingVC.swift
  18. 2 2
      AIRingtone/Business/TSSetingVC/SetingVC/TSSetingViewModel.swift
  19. 30 29
      AIRingtone/Business/TSSetingVC/SetingVC/View/SettingPurchaseTopView.swift
  20. 1 1
      AIRingtone/Business/TSSetingVC/SetingVC/View/TSSettingListView.swift
  21. 2 9
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/TSThemeBrowseVC.swift
  22. 19 8
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTBBtnView.swift
  23. 1 1
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTSIslandView.swift
  24. 3 4
      AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSThemeSetItemView.swift
  25. 7 12
      AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSThemeSetVC.swift
  26. 18 4
      AIRingtone/Business/TSTutorialsVC/TSTutorialPopupVC.swift
  27. 126 45
      AIRingtone/Business/VIewTool/TSButton.swift
  28. 0 24
      AIRingtone/Business/VIewTool/TSViewTool.swift
  29. 5 0
      AIRingtone/Common/Ex/Notification+TSEx.swift
  30. 1 10
      AIRingtone/Common/Purchase/TSPurchaseManager/TSPurchaseManager.swift
  31. 38 1
      AIRingtone/Common/Purchase/TSPurchaseManager/TSPurchaseTool.swift
  32. 0 71
      AIRingtone/Common/Tool/WindowHelper.swift

+ 4 - 8
AIRingtone.xcodeproj/project.pbxproj

@@ -20,7 +20,6 @@
 		A80EDEE92D718CEA003CD332 /* TSFileManagerTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDEB62D718CEA003CD332 /* TSFileManagerTool.swift */; };
 		A80EDEEA2D718CEA003CD332 /* PaddedLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDEBF2D718CEA003CD332 /* PaddedLabel.swift */; };
 		A80EDEEB2D718CEA003CD332 /* StreamPostRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDE6F2D718CEA003CD332 /* StreamPostRequest.swift */; };
-		A80EDEEC2D718CEA003CD332 /* WindowHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDEB92D718CEA003CD332 /* WindowHelper.swift */; };
 		A80EDEF52D718DEA003CD332 /* TSTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDEF32D718DEA003CD332 /* TSTabBarController.swift */; };
 		A80EDF012D718DF1003CD332 /* TSBusinessWebVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDEF62D718DF1003CD332 /* TSBusinessWebVC.swift */; };
 		A80EDF022D718DF1003CD332 /* TSSettingListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A80EDEF92D718DF1003CD332 /* TSSettingListView.swift */; };
@@ -132,7 +131,6 @@
 		A80EDE6F2D718CEA003CD332 /* StreamPostRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StreamPostRequest.swift; sourceTree = "<group>"; };
 		A80EDEB32D718CEA003CD332 /* TSRandomTextPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSRandomTextPicker.swift; sourceTree = "<group>"; };
 		A80EDEB62D718CEA003CD332 /* TSFileManagerTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSFileManagerTool.swift; sourceTree = "<group>"; };
-		A80EDEB92D718CEA003CD332 /* WindowHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowHelper.swift; sourceTree = "<group>"; };
 		A80EDEBB2D718CEA003CD332 /* TSPhotoPickerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPhotoPickerManager.swift; sourceTree = "<group>"; };
 		A80EDEBF2D718CEA003CD332 /* PaddedLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaddedLabel.swift; sourceTree = "<group>"; };
 		A80EDEF32D718DEA003CD332 /* TSTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTabBarController.swift; sourceTree = "<group>"; };
@@ -362,7 +360,6 @@
 				A80EDEB32D718CEA003CD332 /* TSRandomTextPicker.swift */,
 				A80EDEB62D718CEA003CD332 /* TSFileManagerTool.swift */,
 				A868A8EE2D77040F00F6D884 /* TSLoadingAnimation.swift */,
-				A80EDEB92D718CEA003CD332 /* WindowHelper.swift */,
 			);
 			path = Tool;
 			sourceTree = "<group>";
@@ -1084,7 +1081,6 @@
 				A8272E9D2D7A8F4600F1C814 /* TSGeneralRintoneVC+Event.swift in Sources */,
 				A80EDF072D718DF1003CD332 /* TSSetingViewModel.swift in Sources */,
 				A868A8C72D76A44500F6D884 /* TSThemeSetVC.swift in Sources */,
-				A80EDEEC2D718CEA003CD332 /* WindowHelper.swift in Sources */,
 				A868A8D02D76D03900F6D884 /* TSRingToneCellView.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -1111,7 +1107,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 3;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1130,7 +1126,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
-				MARKETING_VERSION = 1.1;
+				MARKETING_VERSION = 1.2;
 				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -1153,7 +1149,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 3;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1172,7 +1168,7 @@
 					"$(inherited)",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
-				MARKETING_VERSION = 1.1;
+				MARKETING_VERSION = 1.2;
 				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

+ 1 - 1
AIRingtone.xcodeproj/xcshareddata/xcschemes/AIRingtone.xcscheme

@@ -31,7 +31,7 @@
       shouldAutocreateTestPlan = "YES">
    </TestAction>
    <LaunchAction
-      buildConfiguration = "Release"
+      buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       launchStyle = "0"

TEMPAT SAMPAH
AIRingtone/Assets.xcassets/VIP/vip_icon_white.imageset/vip_icon_white@2x.png


TEMPAT SAMPAH
AIRingtone/Assets.xcassets/VIP/vip_icon_white.imageset/vip_icon_white@3x.png


+ 6 - 16
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVC.swift

@@ -59,37 +59,31 @@ class TSAIPhotoChildVC: TSBaseVC {
         edgesForExtendedLayout = []
         setNavBarViewHidden(true)
         contentView.addSubview(collectionComponent.collectionView)
-        reloadView()
     }
     
     func reloadView(){
-        collectionComponent.clear()
-        collectionComponent.reloadView(with:vm.colDataArray)
+        kExecuteOnMainThread {
+            self.collectionComponent.clear()
+            self.collectionComponent.reloadView(with:self.vm.colDataArray)
+        }
     }
 
     override func viewDidLayoutSubviews() {
         super.viewDidLayoutSubviews()
-//        print("View did layout subviews")
         self.collectionComponent.collectionView.frame = self.view.bounds
-        self.collectionComponent.collectionView.reloadData()
     }
     
-    
     override func dealThings() {
-    
         reloadView()
-        
         NotificationCenter.default.addObserver(forName: .kReloadUIData, object: nil, queue: nil) { notification in
             if let userInfo = notification.userInfo as? [String: TSGennerateType], let myEnum = userInfo["TSGennerateType"] {
                 if myEnum == self.style {
                     self.vm.setRecentData()
-                    self.collectionComponent.clear()
-                    self.collectionComponent.reloadView(with:self.vm.colDataArray)
+                    self.reloadView()
                 }
             }
         }
     }
-    
 }
 
 
@@ -106,11 +100,7 @@ extension TSAIPhotoChildVC: JXPagingViewListViewDelegate {
     func listView() -> UIView { view }
     
     func listWillAppear() {
-//        print("\(title ?? ""):\(#function)")
-        if collectionComponent.collectionView.visibleCells.count == 0 {
-            debugPrint("遇到空了")
-            reloadView()
-        }
+        
     }
 
     func listDidAppear() {

+ 1 - 0
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/View/TSAIPhotoImageCell.swift

@@ -59,6 +59,7 @@ class TSAIPhotoImageCell: TSBaseCollectionCell {
         super.renderView(with: object, component: component, attributes: attributes)
         if let itemModel = object as? TSColVVMItemModel{
             if let generalPicModel = itemModel.dataModel as? TSActionInfoModel{
+                showImageView.image = nil
                 showImageView.setAsyncImage(urlString: generalPicModel.response.resultUrl,placeholder: kPlaceholderImage,contentMode: .scaleAspectFill)
                 exampleView.isHidden = generalPicModel.modelType == .example ? false : true
             }

+ 1 - 1
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoVC.swift

@@ -26,7 +26,7 @@ class TSAIPhotoVC: TSBaseVC {
     
     var tableHeaderViewHeight: CGFloat{
         get{
-            generalPicVC.viewH <= 10 ? 543.0 : generalPicVC.viewH
+            generalPicVC.viewH <= 10 ? 542.0 : generalPicVC.viewH
         }
     }
     var headerInSectionHeight: Int = 44

+ 2 - 6
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC.swift

@@ -87,9 +87,7 @@ class TSGeneralPicVC: TSBottomAlertVC {
     
     override func clickAgainBtn() {
         //判断 vip
-        if kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: vipFreeNumType) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
+        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: vipFreeNumType, vc: self){ return }
         viewModel.creatImageEmoji(text:aiText)
     }
     
@@ -116,9 +114,7 @@ class TSGeneralPicVC: TSBottomAlertVC {
 
     override func dealThings() {
         //判断 vip
-        if kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: vipFreeNumType) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
+        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: vipFreeNumType, vc: self){ return }
         viewModel.creatImageEmoji(text: self.aiText)
         viewModel.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
             guard let self = self else { return }

+ 38 - 10
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGenneralPicVM.swift

@@ -11,6 +11,32 @@ import Alamofire
 let kTextPicW:Int = 800
 let kTextPicH:Int = 1440
 
+
+
+let actionInfoDictPoster:[String:Any] = [
+    "actionType":"image_create",
+    "comments": "Success",
+    "costTime":9,
+    "createdTimestamp":1742183242,
+    "id":2449,
+    "percent":1,
+    "request":"{\"prompt\": \"Traditional Chinese ink painting style phoenix soaring through misty mountain peaks, dynamic black brushstrokes with crimson accents on rice paper texture, Googie architecture space station, 1950s atomic age aesthetic, curved aluminum panels, starburst patterns, glass dome observatory --edge_threshold 0.5 --atomic_age_style 0.8 --chrome_reflection 1.2\", \"width\": 800, \"height\": 1440, \"countryCode\": \"FR\"}",
+    "response": "{\"resultUrl\": \"https://be-aigc.s3-accelerate.amazonaws.com/4c946f78-b1e7-4ffe-ba18-fff26b10178c.png\"}",
+    "status":"success"
+]
+
+let actionInfoDictPhoto:[String:Any] = [
+    "actionType":"image_create",
+    "comments": "Success",
+    "costTime":7,
+    "createdTimestamp":1742183588,
+    "id":2450,
+    "percent":1,
+    "request":"{\"prompt\": \"Steampunk floating library with brass gears and clockwork mechanisms, leather-bound books flying through amber-lit fog, Victorian-era architecture blended with retro-futurism, retro anime cel-shading, 1980s Toei Animation style, bold black outlines, limited color palette (--color 1980s_anime), visible film grain --edge_threshold 0.4 --cel_shading 0.8, Retain the original stone size of the photo\", \"width\": 800, \"height\": 800, \"countryCode\": \"US\"}",
+    "response":"{\"resultUrl\": \"https://be-aigc.s3-accelerate.amazonaws.com/8b7fcac9-c691-4c3a-b497-401204fad3e9.png\"}",
+    "status":"success"
+]
+
 class TSGenneralPicVM {
     
     var creatRequest:Request?
@@ -22,21 +48,23 @@ class TSGenneralPicVM {
     var gennerateType:TSGennerateType = .poster
     var generatingProgress = 0
     
-    
-    
+//    //模拟数据
 //    func creatImageEmoji(text:String) {
-//
 //        stateDatauPblished = (.start,nil)
 //        stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
-//        
-////        kDelayOnMainThread(2.0) {
-////            self.stateDatauPblished = (.failed("error?.localizedDescription" ?? ""),nil)
-////        }
 //
-//        kDelayOnMainThread(2.0) {
-//            self.stateDatauPblished = (.success(nil),TSActionInfoModel())
+//        kDelayOnMainThread(0.2) {
+//            self.stateDatauPblished = (.progressString(self.generating(progress: 0.5)),nil)
+//        }
+//
+//        kDelayOnMainThread(1.0) {
+//            if Bool.random() {
+//                let infoModel = TSActionInfoModel(JSON: self.gennerateType == .poster ? actionInfoDictPoster : actionInfoDictPhoto)
+//                self.stateDatauPblished = (.success(nil),infoModel)
+//            }else{
+//                self.stateDatauPblished = (.failed("error?.localizedDescription"),nil)
+//            }
 //        }
-//        
 //    }
     
     //width 和 height 必须是 32 的倍数

+ 8 - 23
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/TSTextGeneralPicVC.swift

@@ -43,7 +43,7 @@ class TSTextGeneralPicVC: TSBaseVC {
         photoStyleView.selectedValueBlock = { [weak self] index in
             guard let self = self else { return }
             viewModel.gennerateType = TSGennerateType(rawValue: index) ?? .poster
-            updateVipView()
+            creatBtnView.vipFreeNumType = vipFreeNumType
         }
         photoStyleView.moreInfoBtn.addTarget(self, action: #selector(clickMoreInfoBtn), for: .touchUpInside)
         return photoStyleView
@@ -63,8 +63,9 @@ class TSTextGeneralPicVC: TSBaseVC {
     
     
     //###################################### Button ######################################
-    lazy var creatBtnView:TSCreatBtnView  = {
-        let creatBtnView = TSCreatBtnView {[weak self] in
+    lazy var creatBtnView:TSAppBtnView  = {
+        let creatBtnView = TSAppBtnView()
+        creatBtnView.setUpButton(style: .generate, vipFreeNumType: .posetr) { [weak self] in
             guard let self = self else { return }
             generateImage()
         }
@@ -72,6 +73,8 @@ class TSTextGeneralPicVC: TSBaseVC {
         return creatBtnView
     }()
     
+    
+    
     //###################################### Generate History ######################################
     lazy var historyTitleView: TSTGPTitleView = {
         let historyTitleView = TSTGPTitleView()
@@ -115,29 +118,17 @@ class TSTextGeneralPicVC: TSBaseVC {
     }
     
     override func dealThings() {
-        self.updateVipView()
-        NotificationCenter.default.addObserver(self, selector: #selector(vipInfoChanged), name: .kPurchaseDidChanged, object: nil)
-        self.creatBtnView.setVip(vip: true)
-    }
-    
-    @objc func vipInfoChanged() {
-        kExecuteOnMainThread {
-            self.updateVipView()
-        }
+
     }
     
     func updateVipView() {
-//        self.creatBtnView.setVip(vip: kPurchaseDefault.generateVipShow(type: self.vipFreeNumType))
+        
     }
     
     @objc func clickView() {
         view.endEditing(true)
     }
 
-    
-    @objc func clickCollectionView() {
-        view.endEditing(true)
-    }
     @objc func clickMoreInfoBtn() {
         kPresentModalVC(target: self, modelVC: TSTutorialPopupVC(selectedIndex: tutorialPopupSelectedIndex),transitionStyle: .crossDissolve)
     }
@@ -167,17 +158,11 @@ extension TSTextGeneralPicVC {
 extension TSTextGeneralPicVC {
     func generateImage() {
 
-        //判断 vip
-        if kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: vipFreeNumType) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
-        
         let gennerateVC = TSGeneralPicVC(aiText: viewModel.prompt, gennerateType: viewModel.gennerateType)
         {[weak self] model in
             guard let self = self else { return }
             model.request.promptSort = viewModel.promptText
             viewModel.saveModel(model:model)
-            self.updateVipView()
             NotificationCenter.default.post(name: .kReloadUIData, object: nil, userInfo: ["TSGennerateType": viewModel.gennerateType])
         }
         

+ 0 - 1
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/VM/TSTextGeneralPicVM.swift

@@ -26,7 +26,6 @@ enum TSGennerateType:Int,Equatable{
     case photo  = 1     //头像
 }
 
-
 class TSTextGeneralPicVM {
     
     //选择 prompt 类型组

+ 11 - 9
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptTextView.swift

@@ -56,6 +56,7 @@ class TSPromptTextView : TSBaseView{
             backgroundColor: .clear
         )
         customTextView.delegate = self
+        customTextView.returnKeyType = .done
         return customTextView
     }()
     
@@ -191,24 +192,25 @@ class TSPromptTextView : TSBaseView{
 
     func getVipText()->String{
         return "Generate"
-//        if kPurchaseDefault.isVip {
-//            return "Generate"
-//        }
-//        return "Generate (\(kPurchaseDefault.freeNum(type: .generatePic)))"
     }
     
 }
 
 extension TSPromptTextView: UITextViewDelegate{
-    
-    func textViewDidBeginEditing(_ textView: UITextView) {
-//        self.colComponent?.collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredVertically, animated: true)
-    }
-    
+
     func textViewDidChange(_ textView: UITextView) {
         currenMun = textView.text.count
         clearBtn.isEnabled = currenMun > 0
         textChangedBlock(textView.text)
     }
     
+    // 监听键盘的 Return 键(Done 键)
+     func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
+         if text == "\n" { // 检测到 Return 键
+             textView.resignFirstResponder() // 收起键盘
+             return false // 阻止换行
+         }
+         return true
+     }
+    
 }

+ 3 - 9
AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVC.swift

@@ -89,10 +89,7 @@ class TSGeneralRintoneVC: TSBottomAlertVC {
     
     override func clickAgainBtn() {
         audioPlayer.stop()
-        //判断 vip
-        if kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: .ringtones) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
+        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones, vc: self){ return }//判断 vip
         viewModel.creatRintone(text:aiText)
     }
     
@@ -102,7 +99,7 @@ class TSGeneralRintoneVC: TSBottomAlertVC {
             kShowToastDataMissing()
             return
         }
-
+        audioPlayer.stop()
         ringTool.shareBand(with: model.response.musicUrl, fileName: model.response.title) { success in
             
         }
@@ -117,10 +114,7 @@ class TSGeneralRintoneVC: TSBottomAlertVC {
     }
     
     override func dealThings() {
-        //判断 vip
-        if kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: .ringtones) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
+        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones, vc: self){ return }//判断 vip
         viewModel.creatRintone(text: self.aiText)
         viewModel.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
             guard let self = self else { return }

+ 4 - 16
AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVM.swift

@@ -29,28 +29,16 @@ class TSGeneralRintoneVM {
     @Published var stateDatauPblished:(TSProgressState,TSActionInfoModel?) = (TSProgressState.none,nil)
     var aiText:String = ""
     var generatingProgress = 0
-    
+//    //模拟数据
 //    func creatRintone(text:String) {
 //
 //        stateDatauPblished = (.start,nil)
 //        stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
 //
 //        kDelayOnMainThread(0.2) {
-//            self.stateDatauPblished = (.progressString(self.generating(progress: 0.2)),nil)
-//        }
-//        
-//        kDelayOnMainThread(0.4) {
-//            self.stateDatauPblished = (.progressString(self.generating(progress: 0.4)),nil)
-//        }
-//        
-//        kDelayOnMainThread(0.6) {
-//            self.stateDatauPblished = (.progressString(self.generating(progress: 0.6)),nil)
+//            self.stateDatauPblished = (.progressString(self.generating(progress: 0.5)),nil)
 //        }
-//        
-//        kDelayOnMainThread(0.8) {
-//            self.stateDatauPblished = (.progressString(self.generating(progress: 0.8)),nil)
-//        }
-//        
+//
 //        kDelayOnMainThread(1.0) {
 //            if Bool.random() {
 //                let infoModel = TSActionInfoModel(JSON: actionInfoDict)
@@ -67,7 +55,7 @@ class TSGeneralRintoneVM {
         aiText = text
         let postDict:[String : Any] = [
             "prompt":text,
-            "duration":30
+            "duration":20
         ]
         stateDatauPblished = (.start,nil)
         stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)

+ 7 - 28
AIRingtone/Business/TSAIRintoneVC/TSTextGeneralRintoneVC/TSTextGeneralRintoneVC.swift

@@ -56,8 +56,9 @@ class TSTextGeneralRintoneVC: TSBaseVC {
     
     
     //###################################### Button ######################################
-    lazy var creatBtnView:TSCreatBtnView  = {
-        let creatBtnView = TSCreatBtnView {[weak self] in
+    lazy var creatBtnView:TSAppBtnView  = {
+        let creatBtnView = TSAppBtnView()
+        creatBtnView.setUpButton(style: .generate, vipFreeNumType: .ringtones) { [weak self] in
             guard let self = self else { return }
             generateImage()
         }
@@ -97,46 +98,24 @@ class TSTextGeneralRintoneVC: TSBaseVC {
             make.width.equalTo(k_ScreenWidth)
         }
     }
-    
+
     override func dealThings() {
-        self.updateVipView()
-        NotificationCenter.default.addObserver(self, selector: #selector(vipInfoChanged), name: .kPurchaseDidChanged, object: nil)
-        self.creatBtnView.setVip(vip: true)
-    }
-    
-    @objc func vipInfoChanged() {
-        kExecuteOnMainThread {
-            self.updateVipView()
-        }
-    }
-    
-    @objc func clickView() {
-        view.endEditing(true)
-    }
 
-    func updateVipView() {
-//        self.creatBtnView.setVip(vip: kPurchaseDefault.generateVipShow(type: .ringtones))
     }
-    
-    @objc func clickCollectionView() {
+
+    @objc func clickView() {
         view.endEditing(true)
     }
 }
 
 extension TSTextGeneralRintoneVC {
     func generateImage() {
-        
-        //判断 vip
-        if kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: .ringtones) == false, vc: self) {[weak self] in
-            guard let self = self else { return }
-        }{ return }
-        
+
         let gennerateVC = TSGeneralRintoneVC(aiText:viewModel.prompt)
         {[weak self] model in
             guard let self = self else { return }
             model.request.promptSort = viewModel.promptText
             viewModel.saveModel(model:model)
-            updateVipView()
             reloadUIBlock?()
         }
         

+ 5 - 23
AIRingtone/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift

@@ -182,24 +182,6 @@ class TSPurchaseVC: TSBaseVC {
 }
 
 
-
-
-
-
-func kJudgeVip(externalBool:Bool,
-               vc:UIViewController,
-               closePageBlock:(()->Void)? = nil) -> Bool {
-    //判断 vip
-    if externalBool,
-       kPurchaseDefault.isVip == false
-    {
-        TSPurchaseVC.show(target: vc, closePageBlock: nil)
-        return true
-    }
-    return false
-}
-
-
 extension TSPurchaseVC{
     
     static func show(target:UIViewController,closePageBlock:(()->Void)?){
@@ -222,9 +204,8 @@ struct PurchaseView :View {
 //            Spacer().frame(height: 44)
             
             VStack {
-                Image("vip_big_icon").resizable().frame(width: 163, height: 164)
-                Spacer().frame(height: 13)
-                
+                Image("vip_big_icon").resizable().frame(width: 163, height: 163)
+      
                 Text(" AI Ringtone Pro")
                     .font(.font(name: .PoppinsBlackItalic,size: 30))
                     .gradientForeground(
@@ -264,7 +245,7 @@ struct PurchaseView :View {
          
             }
             
-            Spacer().frame(height: 25)
+            Spacer().frame(height: 48)
             
             
             VStack(spacing: 12) {
@@ -286,7 +267,8 @@ struct PurchaseView :View {
 //                        viewModel.selectedType = .week
 //                    }
 //                }
-
+                
+                Spacer().frame(height: 2)
                 Button {
                     viewModel.buyPublisher.send(true)
                 } label: {

+ 1 - 1
AIRingtone/Business/TSSetingVC/SetingVC/TSSetingVC.swift

@@ -95,7 +95,7 @@ class TSSetingVC: TSBaseVC {
     
     @objc func vipInfoChanged() {
         kExecuteOnMainThread {
-            self.viewModel.isViper = kPurchaseDefault.isVip
+            self.viewModel.isViper = kPurchaseToolShared.isVip
         }
     }
 }

+ 2 - 2
AIRingtone/Business/TSSetingVC/SetingVC/TSSetingViewModel.swift

@@ -10,7 +10,7 @@ import StoreKit
 class TSSetingViewModel: ObservableObject {
     
     @Published var settingTypes: [SettingType] = SettingType.allCases
-    @Published var isViper: Bool = kPurchaseDefault.isVip
+    @Published var isViper: Bool = kPurchaseToolShared.isVip
     
     var appid = "6741563341"
     // todo.kailen-privacy
@@ -80,7 +80,7 @@ class TSSetingViewModel: ObservableObject {
     func pushVipPurchase(parent: UIViewController) {
         TSPurchaseVC.show(target: parent) {[weak self]  in
             guard let self = self else { return }
-            isViper = kPurchaseDefault.isVip
+            isViper = kPurchaseToolShared.isVip
         }
 //        pushTutorials(parent: parent)
     }

+ 30 - 29
AIRingtone/Business/TSSetingVC/SetingVC/View/SettingPurchaseTopView.swift

@@ -16,23 +16,12 @@ struct SettingPurchaseTopView: View {
                     Spacer().frame(width:20)
                     VStack(alignment: .leading,spacing: 16) {
                         HStack {
-                            Text(" AI Ringtone Pro")
-                                .font(.font(name: .PoppinsBlackItalic,size: 20))
-                                .gradientForeground(
-                                    colors: [Color.white, "#F7B7FF".uiColor.color],
-                                    startPoint: UnitPoint.top,
-                                    endPoint: UnitPoint.bottom
-                                )
-                                .frame(height: 20)
-                            
+                            customText(text: " AI Ringtone Pro")
                             Spacer()
                         }
                         
                         HStack {
-                            Text("Due Date:".localized + " \(kPurchaseDefault.expiredDateString)")
-                                .foregroundColor(.white.opacity(0.6))
-                                .font(.font(size: 14,weight: .medium))
-                                .frame(height: 14)
+                            customTimeText(text: "Due Date:".localized + " \(kPurchaseDefault.expiredDateString)")
                             Spacer()
                         }
                     }
@@ -47,24 +36,12 @@ struct SettingPurchaseTopView: View {
                     Spacer().frame(width:20)
                     VStack(alignment: .leading,spacing: 16) {
                         HStack {
-                            Text("Get Pro")
-                                .font(.font(name: .PoppinsBlackItalic,size: 20))
-                                .gradientForeground(
-                                    colors: [Color.white, "#F7B7FF".uiColor.color],
-                                    startPoint: UnitPoint.top,
-                                    endPoint: UnitPoint.bottom
-                                )
-                                .frame(height: 20)
-                            
+                            customText(text: " Get Pro")
                             Spacer()
                         }
                         
                         HStack {
-                            Text("Limited Time Discount")
-                                .font(.font(size: 14))
-                                .frame(height: 14)
-                                .foregroundColor(UIColor.white.withAlphaComponent(0.6).color)
-                            
+                            customTimeText(text: "Limited Time Discount")
                             Spacer()
                         }
                     }
@@ -75,11 +52,11 @@ struct SettingPurchaseTopView: View {
                         .font(.font(size: 14,weight: .medium))
                         .padding(EdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 12))
                         .frame(height: 26) // 设置高度
-                        .foregroundColor("#010101".uiColor.color)
+                        .foregroundColor("#FBDAFF".uiColor.color)
                         .background(UIColor.themeColor.color)
                         .cornerRadius(13.0) // 圆角
                         .onTapGesture {
-                            if kPurchaseDefault.isVip {
+                            if kPurchaseToolShared.isVip {
                                 return
                             }
                             eventPublisher.enterPurchasePublisher.send(true)
@@ -90,4 +67,28 @@ struct SettingPurchaseTopView: View {
             }
         }
     }
+    
+    // 定义一个返回 View 的方法
+    func customText(text:String) -> some View {
+        let gorgeousColor = "#F7B7FF".uiColor.color
+        return Text(" AI Ringtone Pro")
+            .font(.font(name: .PoppinsBlackItalic,size: 20))
+            .gradientForeground(
+                colors: [Color.white, gorgeousColor],
+                startPoint: UnitPoint.top,
+                endPoint: UnitPoint.bottom
+            )
+            .shadow(color: gorgeousColor.opacity(0.7), radius: 6, x: 0, y: 0)
+            .frame(height: 20)
+    }
+
+
+    // 定义一个返回 View 的方法
+    func customTimeText(text:String) -> some View {
+        Text("Limited Time Discount")
+            .font(.font(size: 14))
+            .frame(height: 14)
+            .foregroundColor(UIColor.white.withAlphaComponent(0.6).color)
+        
+    }
 }

+ 1 - 1
AIRingtone/Business/TSSetingVC/SetingVC/View/TSSettingListView.swift

@@ -19,7 +19,7 @@ struct TSSettingListView: View {
                 SettingPurchaseTopView(eventPublisher: publisher, isViper: $viewModel.isViper)
                     .frame(height: 109*kDesignScale)
                     .onTapGesture {
-                        if kPurchaseDefault.isVip {
+                        if kPurchaseToolShared.isVip {
                             return
                         }
                         publisher.enterPurchasePublisher.send(true)

+ 2 - 9
AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/TSThemeBrowseVC.swift

@@ -151,19 +151,12 @@ class TSThemeBrowseVC: TSBaseVC {
             guard let self = self else { return }
             setVipUI()
         }
-        self.btnView.doneBtn.setImage(UIImage(named: "vip_icon_white"), for: .normal)
-        NotificationCenter.default.addObserver(self, selector: #selector(vipInfoChanged), name: .kPurchaseDidChanged, object: nil)
+        
         setVipUI()
     }
     
-    @objc func vipInfoChanged() {
-        self.setVipUI()
-    }
-    
     func setVipUI(){
-        kExecuteOnMainThread {
-            self.btnView.doneBtn.setImage(self.getNeedVip ? UIImage(named: "vip_icon_white"): nil, for: .normal)
-        }
+        self.btnView.doneBtnView.setVip(vip: self.getNeedVip)
     }
     
     var getNeedVip:Bool{

+ 19 - 8
AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTBBtnView.swift

@@ -65,10 +65,21 @@ class TSTBBtnView: TSBaseView {
         return btn
     }()
     
-    lazy var doneBtn: UIButton = {
-        let btn = kCreateNormalSubmitBtn(title: "Set Now".localized)
-        btn.addTarget(targetVC, action: doneSelector, for: .touchUpInside)
-        return btn
+//    lazy var doneBtn: UIButton = {
+//        let btn = kCreateNormalSubmitBtn(title: "Set Now".localized)
+//        btn.addTarget(targetVC, action: doneSelector, for: .touchUpInside)
+//        return btn
+//    }()
+    
+    lazy var doneBtnView: TSAppBtnView = {
+        let doneBtnView = TSAppBtnView()
+        doneBtnView.setUpButton(style: .themeSet, vipFreeNumType: .none) { [weak self]  in
+            guard let self = self else { return }
+            if let targetVC = targetVC {
+                targetVC.perform(doneSelector)
+            }
+        }
+        return doneBtnView
     }()
     
     init(targetVC:UIViewController,
@@ -142,12 +153,12 @@ class TSTBBtnView: TSBaseView {
     
     
     func setDone() {
-        contentView.addSubview(doneBtn)
-        doneBtn.snp.makeConstraints { make in
+        contentView.addSubview(doneBtnView)
+        doneBtnView.snp.makeConstraints { make in
             make.bottom.equalTo(-k_Height_safeAreaInsetsBottom()-10)
             make.centerX.equalToSuperview()
-            make.width.equalTo(doneBtn.width)
-            make.height.equalTo(doneBtn.height)
+            make.width.equalTo(doneBtnView.button.width)
+            make.height.equalTo(doneBtnView.button.height)
         }
     }
     

+ 1 - 1
AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTSIslandView.swift

@@ -35,7 +35,7 @@ class TSTSIslandView: TSBaseView {
         islandImageView.addSubview(showImageView)
         showImageView.snp.makeConstraints { make in
             make.centerY.equalToSuperview()
-            make.leading.equalTo(24)
+            make.leading.equalTo(14)
             make.width.height.equalTo(56)
         }
         

+ 3 - 4
AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSThemeSetItemView.swift

@@ -25,14 +25,13 @@ class TSThemeSetItemView: TSBaseView {
     
     let diyView = UIView()
     
-    let setBtn:UIButton = UIButton.createButton(title: "Set Now".localized,backgroundColor: .themeColor,font: .font(size: 16),titleColor: "#111111".uiColor,corner: 16)
+    let setBtn:UIButton = UIButton.createButton(title: "Set Now".localized,backgroundColor: .themeColor,font: .font(size: 16),titleColor: .white,corner: 16)
     
     let moreInfoBtn = kCreateMoreInfoBtn()
     
     override func creatUI() {
-        
-        setBtn.imageEdgeInsets = UIEdgeInsets(top:0, left: -8, bottom: 0, right: 16)
-        
+
+        setBtn.setTitleImageSpace(spacing: 4)
         contentView.snp.updateConstraints { make in
             make.top.equalTo(16)
         }

+ 7 - 12
AIRingtone/Business/TSThemeVC/TSThemeSetVC/TSThemeSetVC.swift

@@ -116,9 +116,9 @@ class TSThemeSetVC: TSBaseVC {
     }
     
     func setVipUI(){
-        self.ringView.setBtn.setImage(getNeedVip ? UIImage(named: "vip_icon_black"): nil, for: .normal)
-        self.posterView.setBtn.setImage(getNeedVip ? UIImage(named: "vip_icon_black"): nil, for: .normal)
-        self.photoView.setBtn.setImage(getNeedVip ? UIImage(named: "vip_icon_black"): nil, for: .normal)
+        self.ringView.setBtn.setImage(getNeedVip ? UIImage(named: "vip_icon_white"): nil, for: .normal)
+        self.posterView.setBtn.setImage(getNeedVip ? UIImage(named: "vip_icon_white"): nil, for: .normal)
+        self.photoView.setBtn.setImage(getNeedVip ? UIImage(named: "vip_icon_white"): nil, for: .normal)
     }
     
 
@@ -162,10 +162,8 @@ extension TSThemeSetVC {
     }
     
     @objc func clickSetRing(){
-        
-        //判断 vip
-        if kJudgeVip(externalBool: getNeedVip, vc: self) { return }
-        
+        audioPlayer.stop()
+        if kPurchaseToolShared.kJudgeVip(externalBool: getNeedVip, vc: self){ return }//判断 vip
         ringTool.shareBand(with: model.ringtone, fileName: model.name) { success in
             
         }
@@ -173,8 +171,7 @@ extension TSThemeSetVC {
     
     @objc func clickSetPoster(){
         
-        //判断 vip
-        if kJudgeVip(externalBool: getNeedVip, vc: self){ return }
+        if kPurchaseToolShared.kJudgeVip(externalBool: getNeedVip, vc: self){ return }//判断 vip
         
         if let image = posterView.netWorkImageView.image{
             PhotoManagerShared.saveImageToAlbum(image) { success, error in
@@ -191,9 +188,7 @@ extension TSThemeSetVC {
     
     @objc func clickPhoto(){
         
-        //判断 vip
-        if kJudgeVip(externalBool: getNeedVip, vc: self)
-        { return }
+        if kPurchaseToolShared.kJudgeVip(externalBool: getNeedVip, vc: self){ return }//判断 vip
         
         guard let photo = avatarImage else { return }
         contactsTool.setContactsAvatar(avatarImage: photo) { data, error in

+ 18 - 4
AIRingtone/Business/TSTutorialsVC/TSTutorialPopupVC.swift

@@ -89,7 +89,8 @@ class TSTutorialPopupVC: TSBaseVC {
     }()
     
     lazy var pagingView: JXPagingView = {
-        let pagingView = JXPagingView(delegate: self)
+        let pagingView: JXPagingView = JXPagingListRefreshView(delegate: self) //整个刷新
+//        let pagingView = JXPagingView(delegate: self)
         pagingView.mainTableView.backgroundColor = .clear
         pagingView.frame = CGRect(x: 0, y: 25, width:popupContentViewW, height:popupContentViewH-72-25)
         pagingView.listContainerView.listCellBackgroundColor = .clear
@@ -171,6 +172,7 @@ extension TSTutorialPopupVC: JXPagingViewDelegate {
     lazy var stackView: TSCustomStackView = {
         let stackView = TSCustomStackView()
         stackView.scrollView.delegate = self
+        stackView.scrollView.isScrollEnabled = false
         return stackView
     }()
     
@@ -219,7 +221,19 @@ extension TSTutorialPopupVC: JXPagingViewDelegate {
         
         popupContentView.imageView0.image = UIImage(named: imageNamed0)
         popupContentView.imageView1.image = UIImage(named: imageNamed1)
-        popupContentView.infoLabel.text = info
+        
+
+        let attributedString = NSMutableAttributedString(string: info)
+        let paragraphStyle = NSMutableParagraphStyle()
+        paragraphStyle.lineSpacing = 10
+        paragraphStyle.alignment = .center
+        attributedString.addAttribute(
+          .paragraphStyle,
+          value: paragraphStyle,
+          range: NSRange(location: 0, length: attributedString.length)
+        )
+        popupContentView.infoLabel.attributedText = attributedString
+//        popupContentView.infoLabel.text = info
     }
 }
 
@@ -299,8 +313,8 @@ class TSTutorialPopupContentView: TSBaseView {
         
         infoLabel.snp.makeConstraints { make in
             make.top.equalTo(imageView0.snp.bottom).offset(20)
-            make.leading.bottom.equalTo(20)
-            make.trailing.equalTo(-20)
+            make.leading.equalTo(20)
+            make.bottom.trailing.equalTo(-20)
         }
         
     }

+ 126 - 45
AIRingtone/Business/VIewTool/TSButton.swift

@@ -24,77 +24,158 @@ class TSNormalCancelBtn: TSAppBtn {
 
 }
 
-//常用提交按钮
-func kCreateNormalSubmitBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
-    
-    let btn = TSNormalSubmitBtn()
-    btn.setUpButton(title:title,font: UIFont.font(size: 16,weight: .regular),titleColor:.white,corner: 24,action: action)
-    btn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
-    btn.imageEdgeInsets = UIEdgeInsets(top:0, left: -8, bottom: 0, right: 16)
-    btn.frame = CGRectMake(0, 0, 200, 48)
-    btn.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
-    return btn
-}
+////常用取消按钮
+//func kCreateNormalCancelBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
+//    let btn = UIButton.createButton(title:title,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
+//    return btn
+//}
+////常用确定按钮
+//func kCreateNormalConfirmBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
+//    let btn = UIButton.createButton(title:title,backgroundImage:UIImage(named: "submit_btn_small_bg"),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
+//    return btn
+//}
 
 
 class TSAppBtnView: TSBaseView {
     enum ViewStyle {
-        case created   //创造类的按钮
+        case normal
+        case generate   //创造类的按钮
+        case themeSet   //主题页设置按钮
+        
     }
     
     var viewH:CGFloat = 64
-    var style:ViewStyle
-    var clickBlock:()->Void
-    
-    init(style:ViewStyle,clickBlock: @escaping () -> Void) {
-        self.style = style
-        self.clickBlock = clickBlock
-        super.init(frame: .zero)
+    var style:ViewStyle = .normal
+    var vipFreeNumType:VipFreeNumType = .none{
+        didSet{
+            updateVipView()
+        }
     }
+    var clickBlock:(()->Void)?
     
-    @MainActor required init?(coder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
+    //###################################### Button ######################################
+    var button:UIButton = UIButton()
+
+    override func creatUI() {
+
     }
     
+    override func dealThings(){
+        
+    }
+
+    func setUpButton(style:ViewStyle,vipFreeNumType:VipFreeNumType,clickBlock: @escaping () -> Void) {
+        
+        self.style = style
+        self.vipFreeNumType = vipFreeNumType
+        self.clickBlock = clickBlock
+        
+        contentView.removeAllSubviews()
+        
+        switch style {
+        case .generate:
+            setUpGenerate()
+            launchVipLogic()
+        case .themeSet:
+            setUpThemeSet()
+        default:
+            break
+        }
+        
+    }
+}
+
+extension TSAppBtnView{
     
-    //###################################### Button ######################################
-    lazy var creatBtn:UIButton  = {
+    func launchVipLogic(){
+        //监听 Vip 变化
+        NotificationCenter.default.addObserver(forName: .kPurchaseDidChanged, object: nil, queue: OperationQueue.main) { [weak self] notification in
+            guard let self = self else { return }
+            updateVipView()
+        }
         
-        let btn = UIButton.createButton(title:"Create Now",font: UIFont.font(size: 16,weight: .regular),titleColor:.white,corner: 24)
-        {[weak self] in
+        NotificationCenter.default.addObserver(forName: .kVipFreeNumChanged, object: nil, queue: OperationQueue.main) { [weak self] notification in
             guard let self = self else { return }
-            clickBlock()
+            if let userInfo = notification.userInfo as? [String: VipFreeNumType], let myEnum = userInfo["VipFreeNumType"] {
+                if myEnum == self.vipFreeNumType {
+                    self.updateVipView()
+                }
+            }
         }
-        btn.frame = CGRectMake(0, 0, k_ScreenWidth - 32, 48)
-        btn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0)
-        btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -8, bottom: 0, right: 0)
-        btn.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
-        return btn
-    }()
+        
+        updateVipView()
+    }
 
-    
-    override func creatUI() {
-        contentView.addSubview(creatBtn)
-        creatBtn.snp.makeConstraints { make in
-            make.center.equalToSuperview()
-            make.leading.equalTo(16)
-            make.trailing.equalTo(-16)
-            make.height.equalTo(creatBtn.height)
+    func updateVipView() {
+        switch style {
+        case .generate:
+            setVip(vip: kPurchaseToolShared.generateVipShow(type: self.vipFreeNumType))
+        default:
+            break
         }
-        setVip(vip:true)
     }
     
     func setBtnEnabled(isEnabled:Bool) {
-        creatBtn.isEnabled = isEnabled
-        creatBtn.alpha = isEnabled ? 1.0 : 0.6
+        button.isEnabled = isEnabled
+        button.alpha = isEnabled ? 1.0 : 0.6
     }
     
     func setVip(vip:Bool) {
         if vip {
-            creatBtn.setImage(UIImage(named: "vip_icon_white"), for: .normal)
+            button.setImage(UIImage(named: "vip_icon_white"), for: .normal)
         }else{
-            creatBtn.setImage(nil, for: .normal)
+            button.setImage(nil, for: .normal)
         }
     }
     
 }
+//创造按钮
+extension TSAppBtnView{
+    //常用提交按钮
+    func kCreateNormalSubmitBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
+        let btn = TSNormalSubmitBtn()
+        btn.setUpButton(title:title,font: UIFont.font(size: 16,weight: .regular),titleColor:.white,corner: 24,action: action)
+
+        btn.setTitleImageSpace(spacing: 4)
+        return btn
+    }
+
+
+    func setUpGenerate() {
+        button = kCreateNormalSubmitBtn(title: "Create Now", action: { [weak self]  in
+            guard let self = self else { return }
+            if let vc = WindowHelper.getCurrentViewController() {
+                if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: vipFreeNumType, vc: vc){ return }
+            }
+
+            clickBlock?()
+        })
+        button.frame = CGRectMake(0, 0, k_ScreenWidth - 32, 48)
+        button.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
+        contentView.addSubview(button)
+        button.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+            make.width.equalTo(button.width)
+            make.height.equalTo(button.height)
+        }
+   
+        
+        viewH = 64
+    }
+    
+    func setUpThemeSet() {
+        button = kCreateNormalSubmitBtn(title: "Set Now", action: { [weak self]  in
+            guard let self = self else { return }
+            clickBlock?()
+        })
+        button.frame = CGRectMake(0, 0, 200, 48)
+        button.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
+        contentView.addSubview(button)
+        button.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+            make.width.equalTo(button.width)
+            make.height.equalTo(button.height)
+        }
+   
+    }
+}

+ 0 - 24
AIRingtone/Business/VIewTool/TSViewTool.swift

@@ -7,10 +7,8 @@
 
 class TSViewTool: UIView {
     
-
 }
 
-
 func createBlurEffectView(style:UIBlurEffect.Style,backgroundColor:UIColor? = nil) -> UIVisualEffectView {
     let blurEffect = UIBlurEffect(style: style)
     let blurEffectView = UIVisualEffectView(effect: blurEffect)
@@ -23,39 +21,17 @@ func createBlurEffectView(style:UIBlurEffect.Style,backgroundColor:UIColor? = ni
     return blurEffectView
 }
 
-
 func kAddNormalSubmitGradientBg(view:UIView){
     kDelayMainShort {
         view.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
     }
 }
 
-
 func kCreateMoreInfoBtn() -> UIButton{
     let btn = TSUIExpandedTouchButton()
     btn.setImage(UIImage(named: "more_info_white"), for: .normal)
     return btn
 }
 
-
-////常用提交按钮
-//func kCreateNormalSubmitBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
-//    let btn = UIButton.createButton(title:title,backgroundColor: .black,font: UIFont.font(size: 16,weight: .regular),titleColor:.themeColor,corner: 24,action: action)
-//    btn.layer.borderWidth = 1
-//    btn.layer.borderColor = UIColor.themeColor.cgColor
-//    btn.frame = CGRectMake(0, 0, 200, 48)
-//    return btn
-//}
-////常用取消按钮
-//func kCreateNormalCancelBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
-//    let btn = UIButton.createButton(title:title,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
-//    return btn
-//}
-////常用确定按钮
-//func kCreateNormalConfirmBtn(title:String, action: (() -> Void)? = nil) -> UIButton {
-//    let btn = UIButton.createButton(title:title,backgroundImage:UIImage(named: "submit_btn_small_bg"),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 30,action: action)
-//    return btn
-//}
-
 let kPlaceholderImage = UIImage(named: "placeholderImage")
 let kViewBJ = "view_bj"

+ 5 - 0
AIRingtone/Common/Ex/Notification+TSEx.swift

@@ -9,6 +9,11 @@
 extension Notification.Name {
     static let kReloadUIData = Notification.Name("kReloadUIData")   //通知页面刷新数据,具体类型,根据参数来区分
     static let kBusinessAudioStateChange = Notification.Name("kBusinessAudioStateChange")   //通知页面刷新数据,具体类型,根据参数来区分
+    
+    
+    
+    
+    static let kVipFreeNumChanged = Notification.Name("kVipFreeNumChanged")   //Vip免费次数发生变化
 }
 
 

+ 1 - 10
AIRingtone/Common/Purchase/TSPurchaseManager/TSPurchaseManager.swift

@@ -16,12 +16,6 @@ public enum PremiumPeriod: String, CaseIterable {
     case lifetime       = "Lifetime"
 }
 
-public enum VipFreeNumType: String, CaseIterable {
-    case ringtones           = "kRingtonesFreeNum"
-    case posetr              = "kPosetrFreeNum"
-    case photo               = "kPhotoFreeNum"
-}
-
 public struct PurchaseProduct {
     public let productId: String
     public let period: PremiumPeriod
@@ -63,7 +57,7 @@ private let kPremiumExpiredInfoKey = "premiumExpiredInfoKey"
 
 typealias PurchaseStateChangeHandler = (_ manager: PurchaseManager, _ state: PremiumRequestState, _ object: Any?) -> Void
 
-let kPurchaseDefault = PurchaseManager.default
+public let kPurchaseDefault = PurchaseManager.default
 public class PurchaseManager: NSObject {
     @objc public static let `default` = PurchaseManager()
 
@@ -129,9 +123,6 @@ public class PurchaseManager: NSObject {
     }
 
     @objc public var isVip: Bool {
-//        #if DEBUG
-//            return true
-//        #endif
         guard let expiresDate = expiredDate else {
             return false
         }

+ 38 - 1
AIRingtone/Common/Purchase/TSPurchaseManager/TSPurchaseTool.swift

@@ -5,7 +5,14 @@
 //  Created by 100Years on 2025/3/16.
 //
 
-/// 免费生成图片次数
+/// 免费生成图片次
+public enum VipFreeNumType: String, CaseIterable {
+    case none                = "kNone"
+    case ringtones           = "kRingtonesFreeNum"
+    case posetr              = "kPosetrFreeNum"
+    case photo               = "kPhotoFreeNum"
+}
+
 
 let kPurchaseToolShared = TSPurchaseTool.shared
 class TSPurchaseTool {
@@ -20,6 +27,9 @@ class TSPurchaseTool {
     var freeDict:[String:Int] = [:]
     
     var isVip:Bool{
+//        #if DEBUG
+//            return true
+//        #endif
         return kPurchaseDefault.isVip
     }
     /// 使用一次免费次数
@@ -40,6 +50,8 @@ class TSPurchaseTool {
         
         freeDict[type.rawValue] = freeNum
         saveForFree()
+        
+        NotificationCenter.default.post(name: .kVipFreeNumChanged, object: nil, userInfo: ["VipFreeNumType": type])
     }
     
     func freeNum(type:VipFreeNumType) -> Int{
@@ -99,3 +111,28 @@ extension TSPurchaseTool{
     }
     
 }
+
+extension TSPurchaseTool{
+    func kJudgeVipFreeType(vipFreeNumType:VipFreeNumType,
+                   vc:UIViewController,
+                   closePageBlock:(()->Void)? = nil) -> Bool {
+        //判断 vip
+        return kJudgeVip(externalBool: kPurchaseToolShared.freeNumAvailable(type: vipFreeNumType) == false, vc: vc,closePageBlock: closePageBlock)
+    }
+
+
+    func kJudgeVip(externalBool:Bool,
+                   vc:UIViewController,
+                   closePageBlock:(()->Void)? = nil) -> Bool {
+        //判断 vip
+        if externalBool,
+           kPurchaseToolShared.isVip == false
+        {
+            TSPurchaseVC.show(target: vc, closePageBlock: nil)
+            return true
+        }
+        return false
+    }
+
+}
+

+ 0 - 71
AIRingtone/Common/Tool/WindowHelper.swift

@@ -1,71 +0,0 @@
-//
-//  WindowHelper.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-import UIKit
-
-class WindowHelper {
-    
-    /// 获取当前的 keyWindow
-    static func getKeyWindow() -> UIWindow? {
-        // 在 iOS 13 及以上,SceneDelegate 管理窗口
-        if #available(iOS 13.0, *) {
-            return UIApplication.shared.connectedScenes
-                .compactMap { $0 as? UIWindowScene }
-                .flatMap { $0.windows }
-                .first { $0.isKeyWindow }
-        } else {
-            // iOS 13 以下直接获取 keyWindow
-            return UIApplication.shared.keyWindow
-        }
-    }
-    
-    /// 获取当前窗口,兼容 iOS 13 及以上版本
-    static func getCurrentWindow() -> UIWindow? {
-        if #available(iOS 13.0, *) {
-            // iOS 13 及以上使用 `scene` 获取当前 window
-            guard let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene else {
-                return nil
-            }
-            return scene.windows.first { $0.isKeyWindow }
-        } else {
-            // iOS 12 及以下直接从 keyWindow 获取
-            return UIApplication.shared.keyWindow
-        }
-    }
-    
-    /// 获取当前根视图控制器
-    static func getRootViewController() -> UIViewController? {
-        guard let window = getCurrentWindow() else {
-            return nil
-        }
-        return window.rootViewController
-    }
-    
-    /// 获取当前的视图控制器
-    static func getCurrentViewController() -> UIViewController? {
-        var currentViewController = getRootViewController()
-        
-        while let presentedViewController = currentViewController?.presentedViewController {
-            currentViewController = presentedViewController
-        }
-        
-        return currentViewController
-    }
-    
-    
-    static func topViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
-        if let nav = base as? UINavigationController {
-            return topViewController(base: nav.visibleViewController)
-        } else if let tab = base as? UITabBarController {
-            return topViewController(base: tab.selectedViewController)
-        } else if let presented = base?.presentedViewController {
-            return topViewController(base: presented)
-        }
-        debugPrint("当前顶层 VC 是: \(base)")
-        return base
-    }
-}