Bladeren bron

1.4(2)修改bug

100Years 1 maand geleden
bovenliggende
commit
863a92d5a5
42 gewijzigde bestanden met toevoegingen van 412 en 126 verwijderingen
  1. 2 2
      AIRingtone.xcodeproj/project.pbxproj
  2. 1 0
      AIRingtone/AppDelegate.swift
  3. 22 0
      AIRingtone/Assets.xcassets/Common/ringplaceholderImage.imageset/Contents.json
  4. BIN
      AIRingtone/Assets.xcassets/Common/ringplaceholderImage.imageset/ringplaceholderImage@2x.png
  5. BIN
      AIRingtone/Assets.xcassets/Common/ringplaceholderImage.imageset/ringplaceholderImage@3x.png
  6. 1 1
      AIRingtone/Assets.xcassets/Launch/bootPage_0.imageset/Contents.json
  7. BIN
      AIRingtone/Assets.xcassets/Launch/bootPage_0.imageset/bootPage_0 1.png
  8. BIN
      AIRingtone/Assets.xcassets/Launch/bootPage_0.imageset/bootPage_0.png
  9. 1 1
      AIRingtone/Assets.xcassets/Launch/bootPage_1.imageset/Contents.json
  10. BIN
      AIRingtone/Assets.xcassets/Launch/bootPage_1.imageset/bootPage_1 1.png
  11. BIN
      AIRingtone/Assets.xcassets/Launch/bootPage_1.imageset/bootPage_1.png
  12. 1 1
      AIRingtone/Assets.xcassets/Launch/bootPage_2.imageset/Contents.json
  13. BIN
      AIRingtone/Assets.xcassets/Launch/bootPage_2.imageset/bootPage_2 1.png
  14. BIN
      AIRingtone/Assets.xcassets/Launch/bootPage_2.imageset/bootPage_2.png
  15. BIN
      AIRingtone/Assets.xcassets/Tabbar/tabbar_unSelect_discover.imageset/tabbar_unSelect_discover@2x.png
  16. BIN
      AIRingtone/Assets.xcassets/Tabbar/tabbar_unSelect_discover.imageset/tabbar_unSelect_discover@3x.png
  17. 1 1
      AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/Contents.json
  18. BIN
      AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/theme_banner@2x 1.png
  19. BIN
      AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/theme_banner@2x.png
  20. BIN
      AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/theme_banner@3x.png
  21. 2 2
      AIRingtone/Business/Data/TSUserDefaultData.swift
  22. 5 1
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoVC.swift
  23. 0 1
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/Model/TSRingModel.swift
  24. 7 5
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/TSAIRintoneVC.swift
  25. 78 30
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/View/TSAIRintoneHistoryCell.swift
  26. 10 3
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/ViewModel/TSAIRintoneVM.swift
  27. 6 0
      AIRingtone/Business/TSAIRintoneVC/TSGenerateHistoryVC/TSGenerateHistoryVC.swift
  28. 16 12
      AIRingtone/Business/TSDiscoverVC/TSDiscoverListVC/TSDiscoverListVC.swift
  29. 0 4
      AIRingtone/Business/TSDiscoverVC/TSDiscoverListVC/View/TSDiscoverListCell.swift
  30. 1 1
      AIRingtone/Business/TSDiscoverVC/TSDiscoverVC/TSDiscoverVC.swift
  31. 2 1
      AIRingtone/Business/TSDiscoverVC/TSDiscoverVC/View/TSDiscoverCell.swift
  32. 28 5
      AIRingtone/Business/TSDiscoverVC/TSRingDownVC/TSRingDownVC.swift
  33. 3 3
      AIRingtone/Business/TSDiscoverVC/TSRingDownVC/VM/TSRingDownVM.swift
  34. 1 1
      AIRingtone/Business/TSTabBarController/TSTabBarController.swift
  35. 1 1
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/TSThemeBrowseVC.swift
  36. 1 1
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/VM/TSThemeBrowseVM.swift
  37. 7 1
      AIRingtone/Business/TSThemeVC/TSThemeTutorialsVC/TSThemeTutorialsVC.swift
  38. 20 2
      AIRingtone/Business/VIewTool/TSRingToneCellView.swift
  39. 1 0
      AIRingtone/Business/VIewTool/TSViewTool.swift
  40. 2 2
      AIRingtone/Common/Purchase/TSPurchaseManager/TSPurchaseTool.swift
  41. 26 4
      AIRingtone/Common/Tool/TSAudioPlayer/TSAudioPlayer.swift
  42. 166 40
      AIRingtone/Common/Tool/TSBusinessAudioPlayer.swift

+ 2 - 2
AIRingtone.xcodeproj/project.pbxproj

@@ -1271,7 +1271,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1313,7 +1313,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 2;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;

+ 1 - 0
AIRingtone/AppDelegate.swift

@@ -63,6 +63,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 extension AppDelegate {
 
     func applicationDidEnterBackground(_ application: UIApplication) {
+        TSBusinessAudioPlayer.shared.stop()
         beginBackgroundTask()
     }
     

+ 22 - 0
AIRingtone/Assets.xcassets/Common/ringplaceholderImage.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ringplaceholderImage@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ringplaceholderImage@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIRingtone/Assets.xcassets/Common/ringplaceholderImage.imageset/ringplaceholderImage@2x.png


BIN
AIRingtone/Assets.xcassets/Common/ringplaceholderImage.imageset/ringplaceholderImage@3x.png


+ 1 - 1
AIRingtone/Assets.xcassets/Launch/bootPage_0.imageset/Contents.json

@@ -1,11 +1,11 @@
 {
   "images" : [
     {
-      "filename" : "bootPage_0.png",
       "idiom" : "universal",
       "scale" : "1x"
     },
     {
+      "filename" : "bootPage_0 1.png",
       "idiom" : "universal",
       "scale" : "2x"
     },

BIN
AIRingtone/Assets.xcassets/Launch/bootPage_0.imageset/bootPage_0 1.png


BIN
AIRingtone/Assets.xcassets/Launch/bootPage_0.imageset/bootPage_0.png


+ 1 - 1
AIRingtone/Assets.xcassets/Launch/bootPage_1.imageset/Contents.json

@@ -1,11 +1,11 @@
 {
   "images" : [
     {
-      "filename" : "bootPage_1.png",
       "idiom" : "universal",
       "scale" : "1x"
     },
     {
+      "filename" : "bootPage_1 1.png",
       "idiom" : "universal",
       "scale" : "2x"
     },

BIN
AIRingtone/Assets.xcassets/Launch/bootPage_1.imageset/bootPage_1 1.png


BIN
AIRingtone/Assets.xcassets/Launch/bootPage_1.imageset/bootPage_1.png


+ 1 - 1
AIRingtone/Assets.xcassets/Launch/bootPage_2.imageset/Contents.json

@@ -1,11 +1,11 @@
 {
   "images" : [
     {
-      "filename" : "bootPage_2.png",
       "idiom" : "universal",
       "scale" : "1x"
     },
     {
+      "filename" : "bootPage_2 1.png",
       "idiom" : "universal",
       "scale" : "2x"
     },

BIN
AIRingtone/Assets.xcassets/Launch/bootPage_2.imageset/bootPage_2 1.png


BIN
AIRingtone/Assets.xcassets/Launch/bootPage_2.imageset/bootPage_2.png


BIN
AIRingtone/Assets.xcassets/Tabbar/tabbar_unSelect_discover.imageset/tabbar_unSelect_discover@2x.png


BIN
AIRingtone/Assets.xcassets/Tabbar/tabbar_unSelect_discover.imageset/tabbar_unSelect_discover@3x.png


+ 1 - 1
AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/Contents.json

@@ -5,7 +5,7 @@
       "scale" : "1x"
     },
     {
-      "filename" : "theme_banner@2x 1.png",
+      "filename" : "theme_banner@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },

BIN
AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/theme_banner@2x 1.png


BIN
AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/theme_banner@2x.png


BIN
AIRingtone/Assets.xcassets/Theme/theme_banner.imageset/theme_banner@3x.png


+ 2 - 2
AIRingtone/Business/Data/TSUserDefaultData.swift

@@ -193,8 +193,8 @@ class TSAIRintoneHistory{
 
 
 //AI铃声历史记录
-class TSRecommendRintoneHistory{
-    @UserDefault(key: "kRecommendRintoneHistoryListString", defaultValue: "")
+class TSMineRintoneHistory{
+    @UserDefault(key: "kMineRintoneHistoryListString", defaultValue: "")
     static private var historyString: String
     static var listModelArray: [TSRingModel] = {
 

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

@@ -136,7 +136,11 @@ class TSAIPhotoVC: TSBaseVC {
     
     
     override func dealThings() {
-
+        NotificationCenter.default.addObserver(forName: .kReloadUIData, object: nil, queue: nil) { notification in
+            if let userInfo = notification.userInfo as? [String: TSGennerateType], let myEnum = userInfo["TSGennerateType"] {
+                self.segmentedView.selectItemAt(index: myEnum.rawValue)
+            }
+        }
     }
     
 }

+ 0 - 1
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/Model/TSRingModel.swift

@@ -27,7 +27,6 @@ class TSRingModel:TSBaseModel {
     
     var downloadOp:DownloadOperation?
     var audioPlayerFileTool:TSAudioPlayerFileTool?
-    
 }
 
 class TSRingCategoryModel:TSBaseModel {

+ 7 - 5
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/TSAIRintoneVC.swift

@@ -160,9 +160,10 @@ extension TSAIRintoneVC: UICollectionViewDataSource ,UICollectionViewDelegate,UI
             if let model = model as? TSActionInfoModel {
                 _ = kPurchaseToolShared.kshareBand(needVip: model.response.vip, vc: self, urlString: model.response.musicUrl, fileName: model.response.title)
             }else if let ringModel = model as? TSRingModel {
-                _ = kPurchaseToolShared.kshareBand(needVip: ringModel.vip, vc: self, urlString: ringModel.audioUrl, fileName: ringModel.title){[weak self]  in
-                    guard let self = self else { return }
-                    TSRecommendRintoneHistory.saveModel(model: ringModel)
+                _ = kPurchaseToolShared.kshareBand(needVip: ringModel.vip, vc: self, urlString: ringModel.audioUrl, fileName: ringModel.title){ success in
+                    if success {
+                        TSMineRintoneHistory.saveModel(model: ringModel)
+                    }
                 }
             }
         }
@@ -181,12 +182,12 @@ extension TSAIRintoneVC: UICollectionViewDataSource ,UICollectionViewDelegate,UI
                 if let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TSAIRintoneHistorySectionHeaderView.reuseIdentifier, for: indexPath) as? TSAIRintoneHistorySectionHeaderView {
                     header.titleView.titleLab.text = sectionModel.title
                     header.rightBtn.isHidden = true
-                    if indexPath.section == 0 {
+                    if sectionModel.type == .history {
                         header.rightBtn.isHidden = false
                         header.rightBtn.setUpButton{ [weak self]  in
                             guard let self = self else { return }
                             
-                            let vc =  TSGenerateHistoryVC()
+                            let vc = TSGenerateHistoryVC()
                             vc.reloadUIBlock = { [weak self]  in
                                 guard let self = self else { return }
                                 viewModel.updateRecentData()
@@ -249,6 +250,7 @@ extension TSAIRintoneVC: SwipeCollectionViewCellDelegate {
                                 collectionView.deleteItems(at: [indexPath])
                             }
                         })
+                        TSBusinessAudioPlayer.shared.stop()
                     }
                 }
             })

+ 78 - 30
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/View/TSAIRintoneHistoryCell.swift

@@ -4,13 +4,13 @@
 //
 //  Created by 100Years on 2025/3/6.
 //
-
+import Combine
 import SwipeCellKit
 class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
     
     public var colComponent:TSCollectionViewComponent?
     public var colAttributes:[String : Any]?
-    
+
     override init(frame: CGRect) {
         super.init(frame: frame)
         creatUI()
@@ -36,6 +36,21 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
     lazy var ringView: TSRingToneCellView = {
         let ringToneView = TSRingToneCellView()
         ringToneView.backgroundColor = .clear
+        ringToneView.clickPlayHandel = { [weak self] isplay in
+            guard let self = self else { return }
+
+            
+            if TSBusinessAudioPlayer.shared.isPlaying {
+                TSBusinessAudioPlayer.shared.stop()
+            }else{
+                TSBusinessAudioPlayer.shared.playUrlString(modelUrlString,indexPath: indexPath)
+            }
+            if isplay == false{
+                TSBusinessAudioPlayer.shared.playUrlString(modelUrlString,indexPath: indexPath)
+            }else{
+                TSBusinessAudioPlayer.shared.stop()
+            }
+        }
         return ringToneView
     }()
     
@@ -58,7 +73,6 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
         kDelayMainShort {
             exampleView.makeCorner([.topLeft,.bottomLeft], radius: 10)
         }
-//        exampleView.isHidden = true
         return exampleView
     }()
     
@@ -77,6 +91,8 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
             ringView.setCoverImageView(urlString: model.response.coverUrl)
             exampleView.isHidden = model.modelType != .example
             vipView.isHidden = true
+            
+            self.changePlayerState(state: TSBusinessAudioPlayer.shared.currentPlayerState)
         }
     }
     
@@ -88,27 +104,45 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
             ringView.setCoverImageView(urlString: "")
             exampleView.isHidden = true
             vipView.isHidden = !ringModel.vip
+            self.changePlayerState(state: TSBusinessAudioPlayer.shared.currentPlayerState)
         }
     }
     
+    
     override var isSelected: Bool{
         didSet{
-            ringView.isloading = isSelected
-            if isSelected, self.ringView.isPlay == false{
-            
-                if let model = model{
-                    TSBusinessAudioPlayer.shared.playUrlString(model.response.musicUrl)
-                }else if let ringModel = ringModel{
-                    TSBusinessAudioPlayer.shared.playUrlString(ringModel.audioUrl)
-                }
- 
-            }else{
-                TSBusinessAudioPlayer.shared.stop()
-                backgroundColor = .cardColor
-            }
+            debugPrint("isSelected = \(isSelected),indexPath = \(indexPath)")
+//            ringView.isloading = isSelected
+//            if isSelected, self.ringView.isPlay == false{
+//                
+//                if let model = model{
+//                    TSBusinessAudioPlayer.shared.playUrlString(model.response.musicUrl)
+//                }else if let ringModel = ringModel{
+//                    TSBusinessAudioPlayer.shared.playUrlString(ringModel.audioUrl)
+//                }
+//                
+//            }else{
+//                TSBusinessAudioPlayer.shared.stop()
+//                backgroundColor = .cardColor
+//            }
         }
     }
-    
+
+        
+    var playSelf:Bool{
+        return TSBusinessAudioPlayer.shared.isPlayURLString(string: modelUrlString,indexPath: indexPath)
+    }
+
+    var modelUrlString:String{
+        var urlString:String = ""
+        if let model = model{
+            urlString = model.response.musicUrl
+        }else if let ringModel = ringModel{
+            urlString = ringModel.audioUrl
+        }
+        return urlString
+    }
+
     func creatUI() {
         cornerRadius = 16.0
         backgroundColor = .cardColor
@@ -147,15 +181,17 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
                 kExecuteOnMainThread {
                     self.changePlayerState(state: state)
                 }
-                
             }
         }
     }
     
     
     func changePlayerState(state:TSBusinessAudioPlayer.PlayerState){
-        if self.isSelected == false {
+//        if self.isSelected == false {
+//        if self.modelIsSelected == false {
+            if playSelf == false {
             self.ringView.isPlay = false
+            backgroundColor = .cardColor
             return
         }
         
@@ -169,11 +205,8 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
         case .play:
             self.ringView.isPlay = true
             backgroundColor = "#3C213F".uiColor
-            
-            if let ringModel = ringModel {
-                TSRecommendRintoneHistory.saveModel(model: ringModel)
-            }
         case .stop:
+            self.ringView.isloading = false
             self.ringView.isPlay = false
             backgroundColor = .cardColor
         default:
@@ -184,6 +217,21 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell  {
     deinit {
         NotificationCenter.default.removeObserver(self)
     }
+
+    var indexPath:IndexPath? {
+        guard let collectionView = self.superview as? UICollectionView else {
+//            print("Cell 的 indexPath 无法获取 UICollectionView")
+            return nil
+        }
+        
+        if let indexPath = collectionView.indexPath(for: self) {
+//            print("Cell 的 indexPath: \(indexPath)")
+            return indexPath
+        } else {
+//            print("Cell 的 indexPath 无法获取")
+            return nil
+        }
+    }
 }
 
 extension TSAIRintoneHistoryCell : TSComponentView {
@@ -201,13 +249,13 @@ extension TSAIRintoneHistoryCell : TSComponentView {
 
     }
     
-    public var indexPath:IndexPath?{
-        if let attributes = colAttributes , let IndexPath = attributes[kIndexPath] as? IndexPath{
-            return IndexPath
-        }
-        return nil
-    }
-    
+//    public var indexPath:IndexPath?{
+//        if let attributes = colAttributes , let IndexPath = attributes[kIndexPath] as? IndexPath{
+//            return IndexPath
+//        }
+//        return nil
+//    }
+//    
     public var itemActionHandler: ((Any?, IndexPath) -> Void)?{
         if let colComponent = colComponent,let itemActionHandler = colComponent.itemActionHandler {
             return itemActionHandler

+ 10 - 3
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/ViewModel/TSAIRintoneVM.swift

@@ -8,10 +8,17 @@ import ObjectMapper
 class TSAIRintoneHistoryModel {
     var title:String = ""
     var list:[Any] = []
+    var type:ModelStyle = .history
     
-    init(title: String, list: [Any]) {
+    enum ModelStyle:Int {
+        case history
+        case recommend
+    }
+    
+    init(title: String, list: [Any],type:ModelStyle = .history) {
         self.title = title
         self.list = list
+        self.type = type
     }
 }
 
@@ -37,14 +44,14 @@ class TSAIRintoneVM {
     
     //生成的历史
     lazy var aiRintoneHistoryModel: TSAIRintoneHistoryModel = {
-        let model = TSAIRintoneHistoryModel(title: "Generate History", list:TSAIRintoneHistory.listModelArray)
+        let model = TSAIRintoneHistoryModel(title: "Generate History", list:TSAIRintoneHistory.listModelArray,type: .history)
         return model
     }()
     
 
     //每日推荐的歌曲
     lazy var recommendRingtonesModel: TSAIRintoneHistoryModel = {
-        let model = TSAIRintoneHistoryModel(title: "Recommend Ringtones", list:[])
+        let model = TSAIRintoneHistoryModel(title: "Recommend Ringtones", list:[],type: .recommend)
         return model
     }()
 

+ 6 - 0
AIRingtone/Business/TSAIRintoneVC/TSGenerateHistoryVC/TSGenerateHistoryVC.swift

@@ -129,6 +129,11 @@ extension TSGenerateHistoryVC: UICollectionViewDataSource ,UICollectionViewDeleg
                 _ = kPurchaseToolShared.kshareBand(needVip: model.response.vip, vc: self, urlString: model.response.musicUrl, fileName: model.response.title)
             }else if let ringModel = model as? TSRingModel {
                 _ = kPurchaseToolShared.kshareBand(needVip: ringModel.vip, vc: self, urlString: ringModel.audioUrl, fileName: ringModel.title)
+//                { success in
+//                    if success {
+//                        TSMineRintoneHistory.saveModel(model: ringModel)
+//                    }
+//                }
             }
         }
         
@@ -166,6 +171,7 @@ extension TSGenerateHistoryVC: SwipeCollectionViewCellDelegate {
                                 collectionView.deleteItems(at: [indexPath])
                             }
                         })
+                        TSBusinessAudioPlayer.shared.stop()
                     }
                 }
             })

+ 16 - 12
AIRingtone/Business/TSDiscoverVC/TSDiscoverListVC/TSDiscoverListVC.swift

@@ -7,6 +7,8 @@
 
 class TSDiscoverListVC: TSBaseVC {
     
+    var reloadUIBlock:(()->Void)?
+    
     var ringCategoryModel:TSRingCategoryModel
     init(ringCategoryModel: TSRingCategoryModel) {
         self.ringCategoryModel = ringCategoryModel
@@ -46,6 +48,7 @@ class TSDiscoverListVC: TSBaseVC {
         
         collectionView.addRefresh{ [weak self]  in
             guard let self = self else { return }
+            TSBusinessAudioPlayer.shared.stop()
             viewModel.reloadAllData { [weak self] success  in
                 guard let self = self else { return }
                 if success {
@@ -101,6 +104,10 @@ class TSDiscoverListVC: TSBaseVC {
         }
     }
     
+    override func navBarClickLeftAction() {
+        super.navBarClickLeftAction()
+        reloadUIBlock?()
+    }
     func updateListView(){
         collectionView.reloadData()
     }
@@ -145,13 +152,15 @@ extension TSDiscoverListVC: UICollectionViewDataSource ,UICollectionViewDelegate
     @objc func clickSetRingBtn(_ btn:TSUIExpandedTouchButton){
         let indexPath = btn.indexPath
         if let sectionModel = self.viewModel.modelList.safeObj(At: indexPath.section),
-        let model = sectionModel.list.safeObj(At: indexPath.item){
-            if let model = model as? TSActionInfoModel {
-                _ = kPurchaseToolShared.kshareBand(needVip: model.response.vip, vc: self, urlString: model.response.musicUrl, fileName: model.response.title)
-            }else if let ringModel = model as? TSRingModel {
-                _ = kPurchaseToolShared.kshareBand(needVip: ringModel.vip, vc: self, urlString: ringModel.audioUrl, fileName: ringModel.title){[weak self]  in
-                    guard let self = self else { return }
-                    TSRecommendRintoneHistory.saveModel(model: ringModel)
+        let itemModel = sectionModel.list.safeObj(At: indexPath.item){
+//            if let model = itemModel as? TSActionInfoModel {
+//                _ = kPurchaseToolShared.kshareBand(needVip: model.response.vip, vc: self, urlString: model.response.musicUrl, fileName: model.response.title)
+//            }else
+            if let ringModel = itemModel as? TSRingModel {
+                _ = kPurchaseToolShared.kshareBand(needVip: ringModel.vip, vc: self, urlString: ringModel.audioUrl, fileName: ringModel.title){ success in
+                    if success {
+                        TSMineRintoneHistory.saveModel(model: ringModel)
+                    }
                 }
             }
         }
@@ -159,9 +168,4 @@ extension TSDiscoverListVC: UICollectionViewDataSource ,UICollectionViewDelegate
         collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .top)
         TSBusinessAudioPlayer.shared.stop()
     }
-    
-    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        
-    }
-    
 }

+ 0 - 4
AIRingtone/Business/TSDiscoverVC/TSDiscoverListVC/View/TSDiscoverListCell.swift

@@ -148,10 +148,6 @@ extension TSDiscoverListCell{
         case .play:
             self.ringView.isPlay = true
             backgroundColor = "#3C213F".uiColor
-            
-            if let ringModel = ringModel {
-                TSRecommendRintoneHistory.saveModel(model: ringModel)
-            }
         case .stop:
             self.ringView.isPlay = false
             backgroundColor = .cardColor

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

@@ -117,6 +117,6 @@ class TSDiscoverVC: TSBaseVC {
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         
-        redDot.isHidden = !TSRecommendRintoneHistory.isHaveNew
+        redDot.isHidden = !TSMineRintoneHistory.isHaveNew
     }
 }

+ 2 - 1
AIRingtone/Business/TSDiscoverVC/TSDiscoverVC/View/TSDiscoverCell.swift

@@ -23,6 +23,7 @@ class TSDiscoverCell: TSBaseCollectionCell {
     
     lazy var textLabel: UILabel = {
         let textLabel = UILabel.createLabel(font: .font(size: 14),textColor: .white,textAlignment: .center,numberOfLines: 0)
+        textLabel.addShadow(shadowColor: UIColor.black.cgColor, shadowOffset: CGSize(width: 0, height: 2), shadowRadius: 2, shadowOpacity: 0.3)
         return textLabel
     }()
     
@@ -45,7 +46,7 @@ class TSDiscoverCell: TSBaseCollectionCell {
         super.renderView(with: object, component: component, attributes: attributes)
         if let itemModel = object as? TSColVVMItemModel{
             if let dataModel = itemModel.dataModel as? TSRingCategoryModel{
-                imageView.setAsyncImage(urlString: dataModel.cover,placeholder:kPlaceholderImage,contentMode: .scaleAspectFill)
+                imageView.setAsyncImage(urlString: dataModel.cover,placeholder:kRingPlaceholderImage,contentMode: .scaleAspectFill)
                 textLabel.text = dataModel.title
             }
         }

+ 28 - 5
AIRingtone/Business/TSDiscoverVC/TSRingDownVC/TSRingDownVC.swift

@@ -13,9 +13,18 @@ class TSRingDownVC: TSBaseVC {
         ringCategoryModel.title = "Popular"
         ringCategoryModel.cover = "http://d3a93z8fj970a4.cloudfront.net/fbae944d-9e49-46ee-a51f-78f75a1952e8"
         ringCategoryModel.categoryId = "Popular"
-        kPushVC(target: self, modelVC: TSDiscoverListVC(ringCategoryModel: ringCategoryModel))
+        
+        
+        let vc = TSDiscoverListVC(ringCategoryModel: ringCategoryModel)
+        vc.reloadUIBlock = { [weak self]  in
+            guard let self = self else { return }
+            viewModel.updateRecentData()
+            updateListView()
+        }
+        kPushVC(target: self, modelVC:vc)
     }
     
+    var reloadUIBlock:(()->Void)?
     
     lazy var viewModel:TSRingDownVM = {
         let viewModel = TSRingDownVM()
@@ -70,7 +79,7 @@ class TSRingDownVC: TSBaseVC {
     
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
-        TSRecommendRintoneHistory.isHaveNew = false
+        TSMineRintoneHistory.isHaveNew = false
     }
     
     override func viewDidDisappear(_ animated: Bool) {
@@ -82,6 +91,11 @@ class TSRingDownVC: TSBaseVC {
         updateListView()
     }
     
+    override func navBarClickLeftAction() {
+        super.navBarClickLeftAction()
+        reloadUIBlock?()
+    }
+    
     func updateListView(){
         nullView.isHidden = viewModel.modelList.count > 0
         collectionView.reloadData()
@@ -128,10 +142,17 @@ extension TSRingDownVC: UICollectionViewDataSource ,UICollectionViewDelegate,UIC
         let indexPath = btn.indexPath
         if let sectionModel = self.viewModel.modelList.safeObj(At: indexPath.section),
         let model = sectionModel.list.safeObj(At: indexPath.item){
-            if let model = model as? TSActionInfoModel {
-                _ = kPurchaseToolShared.kshareBand(needVip: model.response.vip, vc: self, urlString: model.response.musicUrl, fileName: model.response.title)
-            }else if let ringModel = model as? TSRingModel {
+//            if let model = model as? TSActionInfoModel {
+//                _ = kPurchaseToolShared.kshareBand(needVip: model.response.vip, vc: self, urlString: model.response.musicUrl, fileName: model.response.title)
+//            }else
+
+            if let ringModel = model as? TSRingModel {
                 _ = kPurchaseToolShared.kshareBand(needVip: ringModel.vip, vc: self, urlString: ringModel.audioUrl, fileName: ringModel.title)
+//                { success in
+//                    if success {
+//                        TSMineRintoneHistory.saveModel(model: ringModel)
+//                    }
+//                }
             }
         }
         
@@ -165,6 +186,8 @@ extension TSRingDownVC: SwipeCollectionViewCellDelegate {
                                 collectionView.deleteItems(at: [indexPath])
                             }
                         })
+                        
+                        self.nullView.isHidden = self.viewModel.modelList.count > 0
                     }
                 }
             })

+ 3 - 3
AIRingtone/Business/TSDiscoverVC/TSRingDownVC/VM/TSRingDownVM.swift

@@ -24,7 +24,7 @@ class TSRingDownVM {
     
     //保存的历史
     lazy var aiRintoneHistoryModel: TSAIRintoneHistoryModel = {
-        let model = TSAIRintoneHistoryModel(title: "Generate History", list:TSRecommendRintoneHistory.listModelArray)
+        let model = TSAIRintoneHistoryModel(title: "Generate History", list:TSMineRintoneHistory.listModelArray)
         return model
     }()
     
@@ -33,12 +33,12 @@ class TSRingDownVM {
 extension TSRingDownVM {
     
     func updateRecentData() {
-        aiRintoneHistoryModel.list = TSRecommendRintoneHistory.listModelArray
+        aiRintoneHistoryModel.list = TSMineRintoneHistory.listModelArray
         modelList = getModelList()
     }
     
     func removeModel(model:TSRingModel){
-        TSRecommendRintoneHistory.removeModel(model: model)
+        TSMineRintoneHistory.removeModel(model: model)
         updateRecentData()
         
         if let pathURL = TSCommonTool.getCachedURLString(from: model.audioUrl) {

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

@@ -25,7 +25,7 @@ class TSTabBarController: UITabBarController {
 
     @objc private func setUpData() {
         viewControllerArray = ["TSAIRintoneVC","TSDiscoverVC","TSThemeVC","TSSetingVC"]
-        titleArray = ["RinTone","Discover","Contact","Setting"]
+        titleArray = ["AI","Discover","Contact","Setting"]
         
         selectedImageArray = [
             "tabbar_select_rintone",

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

@@ -213,7 +213,7 @@ extension TSThemeBrowseVC {
         if browseViewModel.audioPlayer?.playerUsable == true {
             browseViewModel.audioPlayer?.play()
         }else{
-            browseViewModel.audioPlayer?.playUrlString( currentModel?.ringtone)
+            browseViewModel.audioPlayer?.playUrlString( currentModel?.ringtone,loop: true)
         }
     }
 }

+ 1 - 1
AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/VM/TSThemeBrowseVM.swift

@@ -18,7 +18,7 @@ class TSThemeBrowseVM {
         if finallyIndex != currentIndex{
             finallyIndex = currentIndex
             audioPlayer?.stop()
-            audioPlayer?.playUrlString( ringtone)
+            audioPlayer?.playUrlString( ringtone,loop: true)
             finallyIndexChange?()
         }
     }

+ 7 - 1
AIRingtone/Business/TSThemeVC/TSThemeTutorialsVC/TSThemeTutorialsVC.swift

@@ -55,11 +55,17 @@ class TSThemeTutorialsVC: TSBaseVC {
         segmentedView.backgroundColor = .clear
         segmentedView.contentEdgeInsetLeft = 26
         segmentedView.listContainer = pagingView.listContainerView
+        
+        let lineView = UIView(frame: CGRect(x: 0, y: CGFloat(headerInSectionHeight)-1, width: k_ScreenWidth, height: 1))
+        lineView.backgroundColor = .white.withAlphaComponent(0.2)
+        segmentedView.addSubview(lineView)
+
         return segmentedView
     }()
  
     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: 0, width: UIScreen.main.bounds.size.width, height: k_ScreenHeight - k_Nav_Height)
         pagingView.listContainerView.listCellBackgroundColor = .clear

+ 20 - 2
AIRingtone/Business/VIewTool/TSRingToneCellView.swift

@@ -8,11 +8,20 @@
 class TSRingToneCellView: TSBaseView {
     
     
+    var clickPlayHandel:((Bool)->Void)?
+    
     let coverImageView:UIImageView = UIImageView()
     let playBtn = UIButton.createButton(image: UIImage(named: "ringtone_play"))
     let nameLab = UILabel.createLabel(text: "--",font: .font(size: 14),textColor: .white)
     let timeLab = UILabel.createLabel(text:"--:--",font: .font(size: 12),textColor: .white.withAlphaComponent(0.6))
     
+    
+    
+    lazy var clearBtn = UIButton.createButton{[weak self]  in
+        guard let self = self else { return }
+        clickPlayHandel?(self.isPlay)
+    }
+    
     var isPlay:Bool = false {
         didSet{
             playBtn.stopRotating()
@@ -58,7 +67,7 @@ class TSRingToneCellView: TSBaseView {
         
         nameLab.snp.makeConstraints { make in
             make.leading.equalTo(76)
-            make.trailing.equalTo(50)
+            make.trailing.equalTo(-60)
             make.top.equalTo(17)
         }
         
@@ -67,11 +76,20 @@ class TSRingToneCellView: TSBaseView {
             make.bottom.equalTo(-17)
             make.height.equalTo(12)
         }
+        
+        
+        clearBtn.backgroundColor = .yellow.withAlphaComponent(0.2)
+        contentView.addSubview(clearBtn)
+        clearBtn.snp.makeConstraints { make in
+            make.leading.top.bottom.equalToSuperview()
+//            make.trailing.equalTo(-200)
+            make.width.equalTo(72)
+        }
     }
     
     
     func setCoverImageView(urlString:String){
-        coverImageView.setAsyncImage(urlString: urlString,placeholder:kPlaceholderImage,contentMode: .scaleAspectFill,showLoading: false)
+        coverImageView.setAsyncImage(urlString: urlString,placeholder:kRingPlaceholderImage,contentMode: .scaleAspectFill,showLoading: false)
     }
 
 }

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

@@ -34,4 +34,5 @@ func kCreateMoreInfoBtn() -> UIButton{
 }
 
 let kPlaceholderImage = UIImage(named: "placeholderImage")
+let kRingPlaceholderImage = UIImage(named: "ringplaceholderImage")
 let kViewBJ = "view_bj"

+ 2 - 2
AIRingtone/Common/Purchase/TSPurchaseManager/TSPurchaseTool.swift

@@ -139,7 +139,7 @@ extension TSPurchaseTool{
                    vc:UIViewController,
                     urlString:String,
                     fileName:String,
-                   closePageBlock:(()->Void)? = nil) -> Bool {
+                    completion:((Bool)->Void)? = nil) -> Bool {
         //判断 vip
         if needVip,
            kPurchaseToolShared.isVip == false
@@ -147,7 +147,7 @@ extension TSPurchaseTool{
             TSPurchaseVC.show(target: vc, closePageBlock: nil)
             return true
         }
-        TSBandRingTool.creatBandRingTool().shareBandVC(vc: vc, fileURLString: urlString, fileName: fileName)
+        TSBandRingTool.creatBandRingTool().shareBandVC(vc: vc, fileURLString: urlString, fileName: fileName,completion: completion)
         return false
     }
 }

+ 26 - 4
AIRingtone/Common/Tool/TSAudioPlayer/TSAudioPlayer.swift

@@ -7,9 +7,13 @@
 
 import AVFoundation
 
-class TSAudioPlayer {
+class TSAudioPlayer : NSObject, AVAudioPlayerDelegate{
     private var audioPlayer: AVAudioPlayer?
-    private var isLooping: Bool = false
+    var isLooping: Bool = false
+    
+    override init() {
+        super.init()
+    }
     
     var isPlaying:Bool{
         if let audioPlayer = audioPlayer {
@@ -43,14 +47,15 @@ class TSAudioPlayer {
     /// 初始化播放器
     /// - Parameter url: 音频文件的 URL
     init?(url: URL) {
+        super.init()
         do {
             audioPlayer = try AVAudioPlayer(contentsOf: url)
             audioPlayer?.prepareToPlay()
-            
+            audioPlayer?.delegate = self
             let audioSession = AVAudioSession.sharedInstance()
             try audioSession.setCategory(.playback) // 设置类别为 playback
             try audioSession.setActive(true) // 激活音频会话
-            
+
         } catch {
             print("音频文件加载失败: \(error.localizedDescription)")
             return nil
@@ -60,6 +65,11 @@ class TSAudioPlayer {
     /// 开始播放音频
     func play() {
         guard let audioPlayer = audioPlayer else { return }
+
+        if AVAudioSession.sharedInstance().outputVolume <= 0.1 {
+            TSToastShared.showToast(text: "Please turn up the volume".localized)
+         }
+    
         audioPlayer.numberOfLoops = isLooping ? -1 : 0
         audioPlayer.play()
     }
@@ -91,4 +101,16 @@ class TSAudioPlayer {
     deinit {
         stop()
     }
+
+    var audioPlayerDidFinishHandle:((Bool)->Void)?
+    // 实现 AVAudioPlayerDelegate 方法
+    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
+        if flag {
+            print("音频播放完成")
+            
+        } else {
+            print("音频播放中断")
+        }
+        audioPlayerDidFinishHandle?(flag)
+    }
 }

+ 166 - 40
AIRingtone/Common/Tool/TSBusinessAudioPlayer.swift

@@ -25,7 +25,7 @@ class TSBusinessAudioPlayer {
     private var audioPlayer: TSAudioPlayer?
     
     var stateChangeBlock:(PlayerState) -> Void
-    
+    var currentPlayerState:PlayerState = .stop
     var duration:Double{
         if let audioPlayer = audioPlayer {
             return audioPlayer.duration
@@ -49,88 +49,214 @@ class TSBusinessAudioPlayer {
         return false
     }
     var currentURLString:String = ""
+    var currentIndexPath:IndexPath? = nil
     //加载音乐可能 2-3 秒有结果,停止加载后播放.
     private var isStopPlayingAfterLoading:Bool = false
-    private var loadingLogic:(show: () -> Void, hide: () -> Void)?
+//    private var loadingLogic:(show: () -> Void, hide: () -> Void)?
     init(stateChangeBlock:@escaping (PlayerState) -> Void) {
         self.stateChangeBlock = stateChangeBlock
     }
     
-    func playUrlString(_ urlString:String?) {
+    func isPlayURLString(string:String,indexPath:IndexPath? = nil) -> Bool {
+
+        if currentURLString == string {
+            if let currentIndexPath = currentIndexPath,
+               let indexPath = indexPath,
+               indexPath != currentIndexPath
+            {
+                return false
+            }else{
+                return true
+            }
+        }
+        return false
+    }
+    
+    
+    
+    func playUrlString(_ urlString:String?,loop:Bool = false,indexPath:IndexPath? = nil) {
+        self.stop()
         if let urlString = urlString {
+            
+//            if self.currentURLString == urlStrin {
+//                self.play()
+//                return
+//            }
             self.currentURLString = urlString
-            loadingLogic = kCreateLoadingLogic { [weak self]  in
-                guard let self = self else { return }
-                self.stateChangeBlock(.loading(0.0))
-            } hideBlock: {[weak self]  in
-                guard let self = self else { return }
-                self.stateChangeBlock(.loading(1.0))
-            }
+            self.currentIndexPath = indexPath
 
-            loadingLogic?.show()
-            isStopPlayingAfterLoading = false
-            TSCommonTool.downloadAndCacheFile(from: urlString) { [weak self] path, error in
+            let palyFile:(URL)->Void = { [weak self] url in
                 guard let self = self else { return }
-                loadingLogic?.hide()
+                debugPrint("正在播放url:\(currentURLString)")
+                debugPrint("正在播放path:\(url)")
+                self.audioPlayer = TSAudioPlayer(url: url)
+                self.audioPlayer?.setLoop(loop)
                 
-                if isStopPlayingAfterLoading == true || currentURLString != urlString{
-                    self.stop()
-                    isStopPlayingAfterLoading = false
-                    return
+                if self.audioPlayer?.volume == 0 {
+                    setVolume(volume: 1.0)
+                }
+                
+                self.play()
+                dePrint(self.audioPlayer?.duration)
+                
+                self.audioPlayer?.audioPlayerDidFinishHandle = { [weak self] flag in
+                    guard let self = self else { return }
+                    
+                    if flag == true, self.audioPlayer?.isLooping == false{
+                        stop()
+                    }
                 }
+            }
+            
+            isStopPlayingAfterLoading = false
+            if let path = TSCommonTool.getCachedURLString(from: urlString) {
+                palyFile(path) //播放
+            }else{
+                self.changePlayerState(.loading(0.0))
+                TSCommonTool.downloadAndCacheFile(from: urlString) { [weak self] path, error in
+                    guard let self = self else { return }
+                    self.changePlayerState(.loading(1.0))
                 
-                if let path = path {
-                    //播放
-                    if let url = URL(string: path) {
-                        self.audioPlayer = TSAudioPlayer(url: url)
-                        self.audioPlayer?.setLoop(true)
-                        setVolume(volume: 1.0)
-                        self.play()
-                        dePrint(self.audioPlayer?.duration)
+                    if isStopPlayingAfterLoading == true || currentURLString != urlString{
+                        self.stop()
+                        isStopPlayingAfterLoading = false
+                        return
                     }
                     
-                }else{
-                    //暂停
-                    self.stop()
+                    if let path = path, let url = URL(string: path) {
+                        palyFile(url) //播放
+                    }else{
+                        //暂停
+                        self.stop()
+                    }
                 }
             }
-        }else{
-            self.stop()
         }
-        
-
     }
     
     
+//
+//    func playUrlString(_ urlString:String?,loop:Bool = false,indexPath:IndexPath? = nil) {
+//        self.stop()
+//        if let urlString = urlString {
+//            
+////            if self.currentURLString == urlStrin {
+////                self.play()
+////                return
+////            }
+//            self.currentURLString = urlString
+//            self.currentIndexPath = indexPath
+//            loadingLogic = kCreateLoadingLogic { [weak self]  in
+//                guard let self = self else { return }
+//                self.changePlayerState(.loading(0.0))
+//            } hideBlock: {[weak self]  in
+//                guard let self = self else { return }
+//                self.changePlayerState(.loading(1.0))
+//            }
+//
+//            loadingLogic?.show()
+//            
+//            
+////            if let path = getCachedURLString(from: urlString) {
+////                
+////            }else{
+////                
+////                
+////            }
+//
+//            
+//            let palyFile:(String)->Void = { [weak self] path in
+//                guard let self = self else { return }
+//            }
+//            palyFile("111")
+//            
+//            isStopPlayingAfterLoading = false
+//            TSCommonTool.downloadAndCacheFile(from: urlString) { [weak self] path, error in
+//                guard let self = self else { return }
+//                loadingLogic?.hide()
+//                
+//                if isStopPlayingAfterLoading == true || currentURLString != urlString{
+//                    self.stop()
+//                    isStopPlayingAfterLoading = false
+//                    return
+//                }
+//                
+//                if let path = path {
+//                    //播放
+//                    if let url = URL(string: path) {
+//                        debugPrint("正在播放url:\(currentURLString)")
+//                        debugPrint("正在播放path:\(url)")
+//                        self.audioPlayer = TSAudioPlayer(url: url)
+//                        self.audioPlayer?.setLoop(loop)
+//                        setVolume(volume: 1.0)
+//                        self.play()
+//                        dePrint(self.audioPlayer?.duration)
+//                        
+//                        self.audioPlayer?.audioPlayerDidFinishHandle = { [weak self] flag in
+//                            guard let self = self else { return }
+//                            
+//                            if flag == true, self.audioPlayer?.isLooping == false{
+//                                stop()
+//                            }
+//                        }
+//                    }
+//                    
+//                }else{
+//                    //暂停
+//                    self.stop()
+//                }
+//            }
+//        }
+//        
+//
+//    }
+//    
+    
+    
     func play() {
         self.audioPlayer?.play()
-        stateChangeBlock(.play)
+        changePlayerState(.play)
     }
     
-    func stop() {
+    func stop(/*_ urlString:String? = nil*/) {
+        
+//        if let urlStr = urlString , currentURLString != urlStr {
+//            return
+//        }
+
         isStopPlayingAfterLoading = true
-        loadingLogic?.hide()
+//        loadingLogic?.hide()
+//        changePlayerState(.loading(1.0))
+        currentURLString = ""
         self.audioPlayer?.stop()
-        stateChangeBlock(.stop)
+        changePlayerState(.stop)
     }
     
     func pause() {
         isStopPlayingAfterLoading = true
-        loadingLogic?.hide()
+//        loadingLogic?.hide()
+//        changePlayerState(.loading(1.0))
         self.audioPlayer?.pause()
-        stateChangeBlock(.pause)
+        changePlayerState(.pause)
     }
     
     func setVolume(volume:Float){
         self.audioPlayer?.setVolume(volume)
-        stateChangeBlock(.volume(volume))
+        changePlayerState(.volume(volume))
     }
     
+
     func changeAudioSwitch()->Float {
         let volume:Float = self.audioPlayer?.volume == 0.0 ? 1.0 : 0.0
         setVolume(volume: volume)
         return volume
     }
+    
+    func changePlayerState(_ state:PlayerState){
+        debugPrint("changePlayerState\(state)")
+        currentPlayerState = state
+        stateChangeBlock(state)
+    }
      
     deinit {
         dePrint("TSBusinessAudioPlayer deinit")