Преглед изворни кода

修改自测的 bug,打包提测

100Years пре 2 недеља
родитељ
комит
5b77735de8

+ 8 - 4
AIRingtone.xcodeproj/project.pbxproj

@@ -63,6 +63,7 @@
 		A840A8112D94057B0044B8B9 /* ZHWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A840A80C2D94057B0044B8B9 /* ZHWaveformView.swift */; };
 		A840A8112D94057B0044B8B9 /* ZHWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A840A80C2D94057B0044B8B9 /* ZHWaveformView.swift */; };
 		A840A8122D94057B0044B8B9 /* ZHCroppedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A840A80D2D94057B0044B8B9 /* ZHCroppedDelegate.swift */; };
 		A840A8122D94057B0044B8B9 /* ZHCroppedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A840A80D2D94057B0044B8B9 /* ZHCroppedDelegate.swift */; };
 		A840A8132D94057B0044B8B9 /* ZHTrackProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A840A80B2D94057B0044B8B9 /* ZHTrackProcessing.swift */; };
 		A840A8132D94057B0044B8B9 /* ZHTrackProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A840A80B2D94057B0044B8B9 /* ZHTrackProcessing.swift */; };
+		A85ACE112D9A6AD200ED56A1 /* TSEditAudioVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85ACE102D9A6ACD00ED56A1 /* TSEditAudioVC.swift */; };
 		A868A89A2D75505E00F6D884 /* TSThemeBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */; };
 		A868A89A2D75505E00F6D884 /* TSThemeBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */; };
 		A868A89C2D75506C00F6D884 /* TSThemeContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */; };
 		A868A89C2D75506C00F6D884 /* TSThemeContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */; };
 		A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89D2D7560B900F6D884 /* TSPageNullView.swift */; };
 		A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A89D2D7560B900F6D884 /* TSPageNullView.swift */; };
@@ -210,6 +211,7 @@
 		A840A80B2D94057B0044B8B9 /* ZHTrackProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHTrackProcessing.swift; sourceTree = "<group>"; };
 		A840A80B2D94057B0044B8B9 /* ZHTrackProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHTrackProcessing.swift; sourceTree = "<group>"; };
 		A840A80C2D94057B0044B8B9 /* ZHWaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHWaveformView.swift; sourceTree = "<group>"; };
 		A840A80C2D94057B0044B8B9 /* ZHWaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHWaveformView.swift; sourceTree = "<group>"; };
 		A840A80D2D94057B0044B8B9 /* ZHCroppedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHCroppedDelegate.swift; sourceTree = "<group>"; };
 		A840A80D2D94057B0044B8B9 /* ZHCroppedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHCroppedDelegate.swift; sourceTree = "<group>"; };
+		A85ACE102D9A6ACD00ED56A1 /* TSEditAudioVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSEditAudioVC.swift; sourceTree = "<group>"; };
 		A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeBannerCell.swift; sourceTree = "<group>"; };
 		A868A8992D75505800F6D884 /* TSThemeBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeBannerCell.swift; sourceTree = "<group>"; };
 		A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeContentCell.swift; sourceTree = "<group>"; };
 		A868A89B2D75506500F6D884 /* TSThemeContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeContentCell.swift; sourceTree = "<group>"; };
 		A868A89D2D7560B900F6D884 /* TSPageNullView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPageNullView.swift; sourceTree = "<group>"; };
 		A868A89D2D7560B900F6D884 /* TSPageNullView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPageNullView.swift; sourceTree = "<group>"; };
@@ -677,6 +679,7 @@
 		A840A8062D9404060044B8B9 /* TSEditAudioVideoVC */ = {
 		A840A8062D9404060044B8B9 /* TSEditAudioVideoVC */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A85ACE102D9A6ACD00ED56A1 /* TSEditAudioVC.swift */,
 				A8A93A922D954C0800ABF9C6 /* TSEditAudioSliderView.swift */,
 				A8A93A922D954C0800ABF9C6 /* TSEditAudioSliderView.swift */,
 				A840A8072D9404480044B8B9 /* TSEditAudioVideoBaseVC.swift */,
 				A840A8072D9404480044B8B9 /* TSEditAudioVideoBaseVC.swift */,
 			);
 			);
@@ -1295,6 +1298,7 @@
 				A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */,
 				A868A8A22D7560B900F6D884 /* TSPageNullView.swift in Sources */,
 				A868A8CE2D76AAC600F6D884 /* TSThemeSetRingToneView.swift in Sources */,
 				A868A8CE2D76AAC600F6D884 /* TSThemeSetRingToneView.swift in Sources */,
 				A868A90E2D7846D600F6D884 /* TSSavePhotoSuccessTool.swift in Sources */,
 				A868A90E2D7846D600F6D884 /* TSSavePhotoSuccessTool.swift in Sources */,
+				A85ACE112D9A6AD200ED56A1 /* TSEditAudioVC.swift in Sources */,
 				A8C6436C2D79A8C8001068D0 /* TSAIRintoneHistoryCell.swift in Sources */,
 				A8C6436C2D79A8C8001068D0 /* TSAIRintoneHistoryCell.swift in Sources */,
 				A868A8A32D7560B900F6D884 /* TSViewTool.swift in Sources */,
 				A868A8A32D7560B900F6D884 /* TSViewTool.swift in Sources */,
 				A83F871D2D79409B00D29B1B /* TSUserDefaultData.swift in Sources */,
 				A83F871D2D79409B00D29B1B /* TSUserDefaultData.swift in Sources */,
@@ -1371,7 +1375,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 5;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1390,7 +1394,7 @@
 					"$(inherited)",
 					"$(inherited)",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
 				);
-				MARKETING_VERSION = 1.7;
+				MARKETING_VERSION = 1.9;
 				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -1413,7 +1417,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 5;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1432,7 +1436,7 @@
 					"$(inherited)",
 					"$(inherited)",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
 				);
-				MARKETING_VERSION = 1.7;
+				MARKETING_VERSION = 1.9;
 				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

+ 6 - 6
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/View/TSAIRintoneHistoryCell.swift

@@ -357,13 +357,13 @@ extension TSAIRintoneHistoryCell {
             editRingModel = TSRingModel.getTSRingModel(TSActionInfoModel: model)
             editRingModel = TSRingModel.getTSRingModel(TSActionInfoModel: model)
         }
         }
 
 
-        if let editRingModel = editRingModel{
-            let urlString = editRingModel.audioUrl
-            
-            TSDownloadManager.getDownLoadRing(urlString: urlString) { [weak self] url, downLoad in
+        if let editRingModel = editRingModel,let copyRingModel = editRingModel.copy() as? TSRingModel{
+            let urlString = copyRingModel.audioUrl
+            TSDownloadManager.getDownLoadRing(ringModel: copyRingModel)
+            { [weak self] url, downLoad in
                 guard let self = self else { return }
                 guard let self = self else { return }
                 if let path = url {
                 if let path = url {
-                    pushVCTSEditAudioVideo(targetVC: targetVC, modelVC: TSEditAudioVideoBaseVC(ringModel: editRingModel, editOriginalURL: path))
+                    pushVCTSEditAudioVideo(targetVC: targetVC, modelVC: TSEditAudioVC(ringModel: copyRingModel, editOriginalURL: path))
                 }else{
                 }else{
                     kShowToastDataMissing()
                     kShowToastDataMissing()
                 }
                 }
@@ -371,7 +371,7 @@ extension TSAIRintoneHistoryCell {
         }
         }
     }
     }
     
     
-    func pushVCTSEditAudioVideo(targetVC:UIViewController,modelVC:TSEditAudioVideoBaseVC){
+    func pushVCTSEditAudioVideo(targetVC:UIViewController,modelVC:TSEditAudioVC){
     
     
         if let fileInfo = TSBusinessAudioPlayer.getAudioFileInfo(path: modelVC.editOriginalURL.path) {
         if let fileInfo = TSBusinessAudioPlayer.getAudioFileInfo(path: modelVC.editOriginalURL.path) {
             if let size = fileInfo.sizeInBytes {
             if let size = fileInfo.sizeInBytes {

+ 6 - 5
AIRingtone/Business/TSCollectionViewVM/TSCollectionViewVM+Config.swift

@@ -5,6 +5,7 @@
 //  Created by 100Years on 2025/2/28.
 //  Created by 100Years on 2025/2/28.
 //
 //
 
 
+private let widthReduction:CGFloat = 1.0
 
 
 struct TSColVVMSizeConfig {
 struct TSColVVMSizeConfig {
     
     
@@ -41,7 +42,7 @@ let themeGuideConfig:TSColVVMSizeConfig = {
     let cellRowNum = 1
     let cellRowNum = 1
     
     
     let originalScale = originalSize.width/originalSize.height
     let originalScale = originalSize.width/originalSize.height
-    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right-widthReduction
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w/CGFloat(cellRowNum)
     w = w/CGFloat(cellRowNum)
     let h = w/originalScale
     let h = w/originalScale
@@ -84,7 +85,7 @@ let themeContentConfig:TSColVVMSizeConfig = {
     let cellRowNum = 2
     let cellRowNum = 2
     
     
     let originalScale = originalSize.width/originalSize.height
     let originalScale = originalSize.width/originalSize.height
-    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right-widthReduction
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w/CGFloat(cellRowNum)
     w = w/CGFloat(cellRowNum)
     let h = w/originalScale
     let h = w/originalScale
@@ -128,7 +129,7 @@ let posterHistoryConfig:TSColVVMSizeConfig = {
     let cellRowNum = 3
     let cellRowNum = 3
     
     
     let originalScale = originalSize.width/originalSize.height
     let originalScale = originalSize.width/originalSize.height
-    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right-widthReduction
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w/CGFloat(cellRowNum)
     w = w/CGFloat(cellRowNum)
     let h = w/originalScale
     let h = w/originalScale
@@ -171,7 +172,7 @@ let photoHistoryConfig:TSColVVMSizeConfig = {
     let cellRowNum = 3
     let cellRowNum = 3
     
     
     let originalScale = originalSize.width/originalSize.height
     let originalScale = originalSize.width/originalSize.height
-    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right-widthReduction
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w/CGFloat(cellRowNum)
     w = w/CGFloat(cellRowNum)
     let h = w/originalScale
     let h = w/originalScale
@@ -214,7 +215,7 @@ let ringCategoriesConfig:TSColVVMSizeConfig = {
     let cellRowNum = 3
     let cellRowNum = 3
     
     
     let originalScale = originalSize.width/originalSize.height
     let originalScale = originalSize.width/originalSize.height
-    var w = k_ScreenWidth-sectionInset.left-sectionInset.right
+    var w = k_ScreenWidth-sectionInset.left-sectionInset.right-widthReduction
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w - lineSpacing * CGFloat((cellRowNum-1))
     w = w/CGFloat(cellRowNum)
     w = w/CGFloat(cellRowNum)
     let h = w/originalScale
     let h = w/originalScale

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

@@ -18,8 +18,8 @@ class TSRingDownVC: TSBaseVC {
         let vc = TSDiscoverListVC(ringCategoryModel: ringCategoryModel)
         let vc = TSDiscoverListVC(ringCategoryModel: ringCategoryModel)
         vc.reloadUIBlock = { [weak self]  in
         vc.reloadUIBlock = { [weak self]  in
             guard let self = self else { return }
             guard let self = self else { return }
-            viewModel.updateRecentData()
-            updateListView()
+//            viewModel.updateRecentData()
+//            updateListView()
         }
         }
         kPushVC(target: self, modelVC:vc)
         kPushVC(target: self, modelVC:vc)
     }
     }
@@ -80,6 +80,8 @@ class TSRingDownVC: TSBaseVC {
     override func viewWillAppear(_ animated: Bool) {
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
         super.viewWillAppear(animated)
         TSMineRintoneHistory.shared.isHaveNew = false
         TSMineRintoneHistory.shared.isHaveNew = false
+        viewModel.updateRecentData()
+        updateListView()
     }
     }
     
     
     override func viewWillDisappear(_ animated: Bool) {
     override func viewWillDisappear(_ animated: Bool) {
@@ -88,7 +90,7 @@ class TSRingDownVC: TSBaseVC {
     }
     }
     
     
     override func dealThings() {
     override func dealThings() {
-        updateListView()
+//        updateListView()
     }
     }
     
     
     override func navBarClickLeftAction() {
     override func navBarClickLeftAction() {

+ 792 - 0
AIRingtone/Business/TSEditAudioVideoVC/TSEditAudioVC.swift

@@ -0,0 +1,792 @@
+//
+//  TSEditAudioVC.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/30.
+//
+import AVFoundation
+class TSEditAudioVC: TSEditAudioVideoBaseVC , ZHCroppedDelegate, ZHWaveformViewDelegate {
+    //#################################### 数据区域 ####################################//
+    override var titleName:String{
+        "Edit Ringtone".localized
+    }
+    
+    var ringModel: TSRingModel //请传递副本过来,会修改数据的
+
+    init(ringModel: TSRingModel,editOriginalURL:URL) {
+        self.ringModel = ringModel
+        super.init(editOriginalURL: editOriginalURL)
+    }
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    lazy var ringDuration:Double = Double(ringModel.duration)
+    //#################################### 名字 ####################################//
+    lazy var nameLabel: UILabel = {
+        let nameLabel = UILabel.createLabel(text: ringModel.title, font: .font(size: 14),textColor: .white.withAlphaComponent(0.8),textAlignment: .center)
+        return nameLabel
+    }()
+    
+    weak var nameInputTextField: UITextField?
+    lazy var nameButton: UIButton = {
+        let nameButton = UIButton.createButton(image: UIImage(named: "edit_field")) { [weak self]  in
+            guard let self = self else { return }
+            
+            let alertVC = UIAlertController(title: nil, message: "Ringtone Name".localized, preferredStyle: .alert)
+            alertVC.addTextField { textField in
+                textField.placeholder = "input name".localized
+                textField.font = UIFont.systemFont(ofSize: 16)
+                textField.text = self.ringModel.title
+                self.nameInputTextField = textField
+            }
+            let ok = UIAlertAction(title: "OK".localized, style: .default) { [weak self] _ in
+                guard let self = self else { return }
+                nameLabel.text = nameInputTextField?.text
+                
+                if let text = nameLabel.text{
+                    ringModel.title = text
+                }
+            }
+            let cancel = UIAlertAction(title: "Cancel".localized, style: .cancel)
+            alertVC.addAction(cancel)
+            alertVC.addAction(ok)
+            present(alertVC, animated: true) {
+                self.nameInputTextField?.becomeFirstResponder()
+            }
+            
+        }
+        return nameButton
+    }()
+    
+    lazy var nameView: UIView = {
+        let nameView = UIView()
+        
+        let nameContentView = UIView()
+        nameView.addSubview(nameContentView)
+        nameContentView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+        
+        nameContentView.addSubview(nameLabel)
+        nameContentView.addSubview(nameButton)
+        
+        nameLabel.snp.makeConstraints { make in
+            make.leading.equalToSuperview()
+            make.width.greaterThanOrEqualTo(220*kDesignScale)
+            make.height.equalTo(23)
+            make.top.bottom.equalTo(0)
+        }
+        nameButton.snp.makeConstraints { make in
+            make.trailing.equalToSuperview()
+            make.leading.equalTo(nameLabel.snp.trailing)
+            make.width.height.equalTo(23)
+            make.top.bottom.equalTo(0)
+        }
+        
+        return nameView
+    }()
+    
+    //#################################### track编辑视频 ####################################//\
+    let trackContentViewLeft:CGFloat = 24.0
+    let trackViewH:CGFloat = 210.0
+    lazy var trackViewW:CGFloat = k_ScreenWidth - trackContentViewLeft * 2
+    lazy var trackView: ZHWaveformView = {
+        let waveform = ZHWaveformView(frame: CGRect(x: 0, y: 0, width: trackViewW, height:trackViewH),fileURL: editOriginalURL)
+        waveform.backgroundColor = .clear
+        waveform.beginningPartColor = .white.withAlphaComponent(0.2) // color
+        waveform.endPartColor = .white.withAlphaComponent(0.2)
+        waveform.wavesColor = "#7E57F4".uiColor
+        waveform.trackScale = 0.2// 0 ~ 1
+        waveform.waveformDelegate = self
+        waveform.croppedDelegate = self
+        
+        return waveform
+    }()
+    
+    lazy var trackContentView: UIView = {
+        let trackContentView = UIView(frame: CGRectMake(24, 0, k_ScreenWidth-48, trackViewH+12))
+
+        trackContentView.addSubview(trackView)
+        trackView.snp.makeConstraints { make in
+            make.top.centerX.equalToSuperview()
+            make.width.equalTo(trackView.width)
+            make.height.equalTo(trackView.height)
+        }
+        return trackContentView
+    }()
+    
+    
+    func creatDragView()->UIView{
+        let bgView = UIView()
+        
+        let view1 = UIView.creatColor(color: .white)
+        bgView.addSubview(view1)
+        let view2 = UIView.creatColor(color: .white)
+        view2.cornerRadius = 6
+        bgView.addSubview(view2)
+        
+        view1.snp.makeConstraints { make in
+            make.width.equalTo(2)
+            make.height.equalTo(trackViewH)
+            make.centerX.equalToSuperview()
+            make.top.equalToSuperview()
+        }
+        
+        view2.snp.makeConstraints { make in
+            make.top.equalTo(view1.snp.bottom)
+            make.width.height.equalTo(12)
+            make.bottom.equalToSuperview()
+            make.leading.equalTo(12)
+            make.trailing.equalTo(-12)
+        }
+        return bgView
+    }
+    lazy var dragLeftView: UIView = creatDragView()
+    lazy var dragRightView: UIView = creatDragView()
+    var progressLine: UIView = UIView.creatColor(color: .themeColor)
+    
+    
+    lazy var startTimeLabel: UILabel = {
+        let label = UILabel.createLabel(text: "00:00s",font: .font(size: 14.0),textColor: .lesserText)
+        return label
+    }()
+    var endTimeLabel: UILabel = {
+        let label = UILabel.createLabel(text: "10:00s",font: .font(size: 14.0),textColor: .lesserText)
+        return label
+    }()
+    var timeLabel: UILabel = {
+        let label = UILabel.createLabel(text: "00:00",font: .font(size: 26.0),textColor: .lesserText)
+        return label
+    }()
+    
+    
+    lazy var timeView: UIView = {
+        let timeView = UIView()
+        
+        timeView.addSubview(startTimeLabel)
+        timeView.addSubview(endTimeLabel)
+        timeView.addSubview(timeLabel)
+        
+        startTimeLabel.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.top.equalTo(12)
+            make.height.equalTo(20)
+        }
+        
+        endTimeLabel.snp.makeConstraints { make in
+            make.trailing.equalTo(-16)
+            make.top.equalTo(12)
+            make.height.equalTo(20)
+        }
+        
+        timeLabel.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.top.equalTo(45)
+            make.height.equalTo(26)
+        }
+        
+        return timeView
+    }()
+    
+    lazy var trackBgView: UIView  = {
+        let trackBgView = UIView()
+        
+        let leftPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.leftPanRecognizer(sender:)))
+        dragLeftView.addGestureRecognizer(leftPanRecognizer)
+        dragLeftView.isUserInteractionEnabled = true
+
+        let rightPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.rightPanRecognizer(sender:)))
+        dragRightView.addGestureRecognizer(rightPanRecognizer)
+        dragRightView.isUserInteractionEnabled = true
+        
+        let gradientImageView = UIImageView.createImageView(imageName: "trackBg_gradient",contentMode: .scaleToFill)
+        trackBgView.addSubview(gradientImageView)
+        gradientImageView.snp.makeConstraints { make in
+            make.leading.top.trailing.equalToSuperview()
+            make.height.equalTo(trackViewH)
+        }
+
+        trackBgView.addSubview(trackContentView)
+        trackContentView.snp.makeConstraints { make in
+            make.top.equalToSuperview()
+            make.leading.equalTo(trackContentView.x)
+            make.trailing.equalTo(-trackContentView.x)
+            make.height.equalTo(trackViewH)
+        }
+        
+   
+        trackBgView.addSubview(dragLeftView)
+        dragLeftView.snp.makeConstraints { make in
+            make.top.leading.equalToSuperview()
+        }
+        
+        trackBgView.addSubview(dragRightView)
+        dragRightView.snp.makeConstraints { make in
+            make.top.equalToSuperview()
+            make.trailing.equalToSuperview()
+        }
+        progressLine.isHidden = true
+        trackBgView.addSubview(progressLine)
+        progressLine.snp.makeConstraints { make in
+            make.top.leading.equalToSuperview()
+            make.width.equalTo(1)
+            make.height.equalTo(trackViewH)
+        }
+        
+        trackBgView.addSubview(timeView)
+        timeView.snp.makeConstraints { make in
+            make.top.equalTo(trackContentView.bottom)
+            make.trailing.leading.equalToSuperview()
+            make.height.equalTo(71)
+            make.bottom.equalTo(0)
+        }
+        
+        return trackBgView
+    }()
+    
+
+    //#################################### Fade in ####################################//
+    lazy var fadeinSliderView: TSEditAudioSliderView = {
+        let fadeinSliderView = TSEditAudioSliderView()
+        fadeinSliderView.leftLabel.text = "Fade in".localized
+        fadeinSliderView.rightLabel.text = "0s"
+        fadeinSliderView.slider.maximumValue = 5
+//        fadeinSliderView.slider.value = 3
+        return fadeinSliderView
+    }()
+    lazy var fadeinSlider: UISlider = {
+        let slider = fadeinSliderView.slider
+        slider.addTarget(self, action: #selector(sliderBeginTap(_:)), for: .touchDown)
+        slider.addTarget(self, action: #selector(sliderEndTap(_:)), for: .touchUpInside)
+        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
+        return slider
+    }()
+    //#################################### Fade out ####################################//
+    
+    lazy var fadeoutSliderView: TSEditAudioSliderView = {
+        let fadeoutSliderView = TSEditAudioSliderView()
+        fadeoutSliderView.leftLabel.text = "Fade out".localized
+        fadeoutSliderView.rightLabel.text = "0s"
+        fadeoutSliderView.slider.maximumValue = 5
+//        fadeoutSliderView.slider.value = 3
+        return fadeoutSliderView
+    }()
+    lazy var fadeoutSlider: UISlider = {
+        let slider = fadeoutSliderView.slider
+        slider.addTarget(self, action: #selector(sliderBeginTap(_:)), for: .touchDown)
+        slider.addTarget(self, action: #selector(sliderEndTap(_:)), for: .touchUpInside)
+        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
+        return slider
+    }()
+    //#################################### Output Volume ####################################//
+    lazy var outputVolumeSliderView: TSEditAudioSliderView = {
+        let outputVolumeSliderView = TSEditAudioSliderView()
+        outputVolumeSliderView.leftLabel.text = "Output Volume".localized
+        outputVolumeSliderView.rightLabel.text = "100%"
+        outputVolumeSliderView.slider.minimumValue = 1.0
+        outputVolumeSliderView.slider.maximumValue = 2.0
+//        outputVolumeSliderView.slider.value = 1.5
+        return outputVolumeSliderView
+    }()
+    lazy var outputVolumeSlider: UISlider = {
+        let slider = outputVolumeSliderView.slider
+        slider.addTarget(self, action: #selector(sliderBeginTap(_:)), for: .touchDown)
+        slider.addTarget(self, action: #selector(sliderEndTap(_:)), for: .touchUpInside)
+        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
+        return slider
+    }()
+    
+
+    
+
+    //#################################### viewDidLoad####################################//
+    override func createData() {
+
+    }
+    
+    override func createView() {
+        super.createView()
+        setUpCusStackView()
+    }
+    
+    func setUpCusStackView() {
+        cusStackView.addSubviewToStack(nameView)
+        nameView.snp.makeConstraints { make in
+            make.height.equalTo(56)
+            make.width.equalTo(k_ScreenWidth)
+        }
+        cusStackView.addSubviewToStack(trackBgView)
+        trackBgView.snp.makeConstraints { make in
+            make.height.equalTo(300)
+            make.width.equalTo(k_ScreenWidth)
+        }
+        
+        cusStackView.addSubviewToStack(playButtonView)
+        playButtonView.snp.makeConstraints { make in
+            make.height.equalTo(playButtonView.height)
+            make.width.equalTo(playButtonView.width)
+        }
+        
+        cusStackView.addSubviewToStack(fadeinSliderView)
+        fadeinSliderView.snp.makeConstraints { make in
+            make.height.equalTo(fadeinSliderView.height)
+        }
+        
+        let spaceView = UIView()
+        cusStackView.addSubviewToStack(spaceView)
+        spaceView.snp.makeConstraints { make in
+            make.height.equalTo(8)
+        }
+        
+        cusStackView.addSubviewToStack(fadeoutSliderView)
+        fadeoutSliderView.snp.makeConstraints { make in
+            make.height.equalTo(fadeinSliderView.height)
+        }
+        
+        let spaceView1 = UIView()
+        cusStackView.addSubviewToStack(spaceView1)
+        spaceView1.snp.makeConstraints { make in
+            make.height.equalTo(8)
+        }
+        
+        cusStackView.addSubviewToStack(outputVolumeSliderView)
+        outputVolumeSliderView.snp.makeConstraints { make in
+            make.height.equalTo(fadeinSliderView.height)
+            make.bottom.equalToSuperview()
+        }
+    
+        _ = fadeinSlider
+        _ = fadeoutSlider
+        _ = outputVolumeSlider
+    }
+    
+    override func dealThings() {
+        
+        dePrint("TSEditAudioVC ringModel = \(String(describing: ringModel.toJSONString())),editOriginalURL = \(editOriginalURL)")
+        
+        if player.duration != 0 {
+            ringDuration = player.duration
+            if ringModel.duration == 0{
+                ringModel.duration = Int(player.duration)
+            }
+        }
+
+        operationCache.append(ringModel)
+        reloadTrackView()
+    }
+
+    private lazy var player:TSBusinessAudioPlayer = {
+        let player = TSBusinessAudioPlayer()
+        player.loadLoactionURL(url: self.editOriginalURL)
+        player.currentTimeChangedHandle = { [weak self] current,total in
+            guard let self = self else { return }
+            handlePlayer(progressChanged: current, total: total)
+        }
+        
+        player.stateChangedHandle = { [weak self] state in
+            guard let self = self else { return }
+            handlePlayer(state: state)
+        }
+        
+        return player
+    }()
+    private lazy var audioTool = AudioTool()
+    private var maxVolume:Float{
+        return outputVolume * 0.5
+    }
+    
+    func reloadTrackView() {
+    
+        tempMp3Path = editOriginalURL.path
+
+        startCropRate = 0
+        endCropRate = 1.0
+        
+        DispatchQueue.main.async {
+            self.dragLeftView.centerX = self.trackContentView.x
+            self.dragRightView.centerX = self.trackContentView.frame.maxX
+            self.previousRightX = self.dragRightView.centerX
+            self.trackView.updateLeftCroppedPosition(1)
+        }
+
+        timeLabel.text = ringDuration.mmss
+        cutButton.setBtnEnabled(isEnabled: false)
+        doneButton.setBtnEnabled(isEnabled: false)
+    }
+
+
+    //#################################### UI 储存属性 ####################################//
+    lazy var fadeInDuration: Int = 0 {
+        didSet {
+            fadeinSliderView.rightLabel.text = "\(fadeInDuration)s"
+        }
+    }
+    lazy var fadeOutDuration: Int = 0 {
+        didSet {
+            fadeoutSliderView.rightLabel.text = "\(fadeOutDuration)s"
+        }
+    }
+    
+    lazy var outputVolume: Float = 1.0 {
+        didSet {
+            outputVolumeSliderView.rightLabel.text = "\(Int(outputVolume*100.0))%"
+        }
+    }
+    lazy var previousLeftX: CGFloat = 0
+    lazy var startCropRate: CGFloat = 0 {
+        didSet {
+            let time = startDuration
+            cutButton.setBtnEnabled(isEnabled: true)
+            doneButton.setBtnEnabled(isEnabled: true)
+            
+            //            print("---start: \(time)")
+            startTimeLabel.text = time.mmss
+            timeLabel.text = (endDuration - startDuration).mmss
+        }
+    }
+    // 拖拽时被暂停,拖拽结束后,继续播放
+    lazy var isSuspendByAction = false
+    lazy var endCropRate: CGFloat = 1.0 {
+        didSet {
+            cutButton.setBtnEnabled(isEnabled: true)
+            doneButton.setBtnEnabled(isEnabled: true)
+            let time = endDuration
+            endTimeLabel.text = time.mmss
+            timeLabel.text = (endDuration - startDuration).mmss
+        }
+    }
+    lazy var previousRightX: CGFloat = 0
+    
+    
+
+    override func startPlay() {
+        playButton.isSelected = !playButton.isSelected
+        if player.isPlaying {
+            player.pause()
+        } else {
+            player.playUrlString(ringModel.audioUrl,localURL: editOriginalURL)
+            player.playUrlString(ringModel.audioUrl,localURL: editOriginalURL)
+            self.player.seek(to:self.startDuration)
+            player.setVolume(volume: fadeInDuration > 0 ? 0 : maxVolume)
+
+            if UIApplication.getSystemVolume() == 0.0 {
+                TSToastShared.showToast(text:"Please turn up the volume".localized)
+            }
+            
+        }
+    }
+    
+    override func saveButtonClick() {
+        handleSaveCutAudio()
+    }
+    
+    override func setButtonClick() {
+        handleSaveCutAudio { model in
+            if let ringModel = model {
+                kDelayMainShort {
+                    let path = ringModel.documentPath.fillDocumentURL
+                    if let vc = WindowHelper.topViewController(){
+                        _ = kPurchaseToolShared.kshareBand(needVip: false, vc: vc, fileURL: path, fileName: ringModel.title)
+                    }
+                }
+            }
+        }
+    }
+    
+}
+
+
+extension TSEditAudioVC {
+    
+
+    
+    @objc func sliderBeginTap(_ slider: UISlider) {
+        suspendPlay()
+    }
+    
+    @objc func sliderEndTap(_ slider: UISlider) {
+        autoPlayAfterMove()
+    }
+    
+    @objc func sliderValueChanged(_ slider: UISlider) {
+        //        print("---\(slider.value)")
+        if player.isPlaying {
+            player.pause()
+        }
+        if slider == fadeinSlider {
+            fadeInDuration = Int(slider.value.rounded(.toNearestOrEven))
+        } else if slider == fadeoutSlider {
+            fadeOutDuration = Int(slider.value.rounded(.toNearestOrEven))
+        } else if slider == outputVolumeSlider {
+            outputVolume = slider.value
+        }
+    }
+
+    
+    // 裁剪起始时间
+    var startDuration: Double {
+        return startCropRate * CGFloat(ringDuration)
+    }
+    
+
+    
+    var startMinCenterX: CGFloat {
+        return trackContentView.x
+    }
+    
+    var startMaxCenterX: CGFloat {
+        let ratio = (endCropRate * CGFloat(ringDuration) - 10) / CGFloat(ringDuration)
+        return ratio * trackContentView.width + trackContentView.x
+    }
+    
+    var endMinCenterX: CGFloat {
+        let ratio = (startCropRate * CGFloat(ringDuration) + 10) / CGFloat(ringDuration)
+        return ratio * trackContentView.width + trackContentView.x
+    }
+    
+    var endMaxCenterX: CGFloat {
+        return trackContentView.frame.maxX
+    }
+
+    @objc private func leftPanRecognizer(sender: UIPanGestureRecognizer) {
+        
+        dePrint("TSEditAudioVC leftPanRecognizer=\(sender)")
+        let limitMinCenterX: CGFloat = startMinCenterX
+        let limitMaxCenterX: CGFloat = startMaxCenterX
+        guard limitMaxCenterX > limitMinCenterX else {
+            if sender.state == .began {
+                dePrint("TSEditAudioVC rightPanRecognizer No less than 10s")
+                TSToastShared.showToast(text:"No less than 10s".localized)
+            }
+            return
+        }
+        
+        if sender.state == .began {
+            suspendPlay()
+        } else if sender.state == .changed {
+            // 修改位置
+            let newPoint = sender.translation(in: trackBgView)
+            var center = dragLeftView.center
+            center.x = previousLeftX + newPoint.x
+            guard center.x > limitMinCenterX,
+                  center.x < limitMaxCenterX else {
+                // 越界,拖不动了, 最少10s
+                if endDuration - startDuration < 11 {
+                    TSToastShared.showToast(text:"No less than 10s".localized)
+                }
+                return
+            }
+            dragLeftView.center = center
+            
+        } else if sender.state == .ended || sender.state == .failed {
+            previousLeftX = dragLeftView.center.x
+            autoPlayAfterMove()
+        }
+        
+        // 边界校验
+        if dragLeftView.centerX < limitMinCenterX {
+            dragLeftView.centerX = limitMinCenterX
+        }
+        if dragLeftView.centerX > limitMaxCenterX {
+            dragLeftView.centerX = limitMaxCenterX
+        }
+        
+        let position = dragLeftView.centerX - trackContentView.x
+        trackView.updateLeftCroppedPosition(position)
+        startCropRate = position / trackContentView.width
+        progressLine.centerX = dragLeftView.centerX
+    }
+    
+
+    var endDuration: Double {
+        return endCropRate * CGFloat(CGFloat(ringDuration))
+    }
+    
+
+    @objc private func rightPanRecognizer(sender: UIPanGestureRecognizer) {
+//        dePrint("TSEditAudioVC rightPanRecognizer=\(sender)")
+        let limitMinCenterX: CGFloat = endMinCenterX
+        let limitMaxCenterX: CGFloat = endMaxCenterX
+        
+
+        guard limitMaxCenterX > limitMinCenterX else {
+            if sender.state == .began {
+                dePrint("TSEditAudioVC rightPanRecognizer No less than 10s")
+                // 越界,拖不动了
+                TSToastShared.showToast(text:"No less than 10s".localized)
+            }
+            return
+        }
+        
+        if sender.state == .began {
+            suspendPlay()
+        } else if sender.state == .changed {
+            let newPoint = sender.translation(in: trackBgView)
+            //dePrint("rightPanRecognizer newPoint = \(newPoint)")
+            var center = dragRightView.center
+            //dePrint("rightPanRecognizer dragRightView.center = \(dragRightView.center)")
+            //dePrint("rightPanRecognizer previousRightX = \(previousRightX)")
+            center.x = previousRightX + newPoint.x
+            //dePrint("rightPanRecognizer center.x = \(center.x)")
+            //dePrint("rightPanRecognizer limitMinCenterX = \(limitMinCenterX),limitMaxCenterX = \(limitMaxCenterX)")
+            guard center.x > limitMinCenterX, center.x < limitMaxCenterX else {
+                // 越界,拖不动了, 最少10s
+                if endDuration - startDuration < 11 {
+                    TSToastShared.showToast(text:"No less than 10s".localized)
+                }
+                return
+            }
+            dragRightView.center = center
+            //dePrint("rightPanRecognizer center = \(center)")
+        } else if sender.state == .ended || sender.state == .failed {
+            previousRightX = dragRightView.centerX
+            autoPlayAfterMove()
+        }
+        
+        // 边界校验
+        if dragRightView.centerX > limitMaxCenterX {
+            dragRightView.centerX = limitMaxCenterX
+            //dePrint("rightPanRecognizer limitMaxCenterX = \(limitMaxCenterX)")
+        }
+        if dragRightView.centerX < limitMinCenterX {
+            dragRightView.centerX = limitMinCenterX
+            //dePrint("rightPanRecognizer limitMinCenterX = \(limitMinCenterX)")
+        }
+        
+        let position = dragRightView.centerX - trackContentView.x
+        //dePrint("rightPanRecognizer position = \(position)")
+        trackView.updateRightCroppedPosition(position)
+        endCropRate = position / trackContentView.width
+        //dePrint("rightPanRecognizer endCropRate = \(endCropRate)")
+    }
+    
+    // 拖拽,暂停
+    func suspendPlay() {
+        if player.isPlaying {
+            isSuspendByAction = true
+            player.pause()
+        }
+    }
+    
+    // 停止拖拽,继续播放
+    func autoPlayAfterMove() {
+        startPlay()
+        isSuspendByAction = false
+    }
+
+    
+    func handleSaveCutAudio(completion:((TSRingModel?)->Void)? = nil){
+        player.pause()
+        // 保存音频
+        startCutAudio { result, errMsg,savePath in
+            if let ringModel = result {
+                // 裁剪的音频,使用本地文件播放,清空网络url
+                dePrint("TSEditAudioVC saveModel ringModel = \(ringModel.toJSONString())")
+                TSMineRintoneHistory.shared.saveModel(model: ringModel)
+                DispatchQueue.main.async {
+                    self.pop()
+                    if let window = WindowHelper.getKeyWindow() {
+                        kSaveSuccesswShared.show(atView:window,text: "Saved in “My Ringtone”".localized) {
+                            if let vc = WindowHelper.topViewController(){
+                                if vc is TSRingDownVC {
+                                    dePrint("vc 是 TSRingDownVC 类型")
+                                }else{
+                                    kPushVC(target: vc, modelVC: TSRingDownVC())
+                                }
+                            }
+                        }
+                    }
+                }
+                completion?(ringModel)
+            } else {
+                DispatchQueue.main.async {
+                    TSToastShared.showToast(text: errMsg ?? "Sorry, Save Failure".localized)
+                }
+                completion?(nil)
+            }
+        }
+    }
+
+    // 裁剪
+    func startCutAudio(completion: ((TSRingModel?, String?,URL?) -> Void)?) {
+        let copyModel = ringModel
+       let savePath = TSDownloadManager.generateRingSaveLocalURL(name: copyModel.title)
+        TSFileManagerTool.checkFolderAndCreate(from: savePath)
+        
+        copyModel.duration = Int(endDuration - startDuration)
+        TSRingLoadingView.shared.showWindow()
+        audioTool.startTansformAudio(url:editOriginalURL.path, from: startDuration, to: endDuration, fadeIn: Double(fadeInDuration), fadeOut: Double(fadeOutDuration),addVolume: Double(outputVolume) ,savePath: savePath.path) { filePath, errMsg in
+            DispatchQueue.main.async {
+                TSRingLoadingView.shared.remove()
+            }
+            if let filePath = filePath {
+                let url = URL(fileURLWithPath: filePath)
+                copyModel.documentPath = filePath.documentLastURLString
+                
+                if let fileInfo = TSBusinessAudioPlayer.getAudioFileInfo(path: url.path) {
+                    if let size = fileInfo.sizeInBytes {
+                        copyModel.size = Int(size)
+                    }
+                    if let duration = fileInfo.durationInSeconds {
+                        copyModel.duration = Int(duration)
+                    }
+                }
+    
+                completion?(copyModel, errMsg, savePath)
+            } else {
+                completion?(nil, errMsg, nil)
+            }
+        }
+    }
+    
+}
+extension TSEditAudioVC {
+    func handlePlayer(state: TSBusinessAudioPlayer.PlayerState) {
+        playButton.isSelected = player.isPlaying
+        progressLine.isHidden = !playButton.isSelected
+        if player.currentPlayerState == .play {
+            progressLine.centerX = dragLeftView.centerX
+        }
+    }
+
+    func handlePlayer(progressChanged current: Double, total: Double) {
+        dePrint("TSEditAudioVC progressChanged=\(current),total=\(total)")
+        let range = endDuration - startDuration
+        let rangeWidth = trackContentView.width * range / total
+        let progress = max(0, current - startDuration) / range
+
+        if player.isPlaying {
+            progressLine.centerX = dragLeftView.centerX + progress * rangeWidth
+        }
+
+        if current >= endDuration {
+            player.pause()
+        }
+
+        // 淡入
+        if fadeInDuration > 0, current - startDuration < Double(fadeInDuration) {
+            let fadeProgress = Float(current - startDuration) / Float(fadeInDuration)
+            let newVolume = min(fadeProgress * maxVolume * 100, 100.0)
+            print("---volume: \(newVolume)")
+            player.setVolume(volume:newVolume / 100)
+        }
+
+        // 淡出
+        if fadeOutDuration > 0, current > (endDuration - Double(fadeOutDuration)) {
+            let fadeProgress = Float(endDuration - current) / Float(fadeOutDuration)
+            let newVolume = max(fadeProgress * maxVolume * 100, 0.0)
+            print("---volume: \(newVolume)")
+            player.setVolume(volume: newVolume / 10)
+        }
+    }
+
+    func sanitizeFilePath(_ path: String) -> String {
+        let illegalFileNameCharacters = CharacterSet(charactersIn: "/\\?%*|\"<>: ")
+        let sanitizedPath = path.components(separatedBy: illegalFileNameCharacters).joined(separator: "_")
+        return sanitizedPath
+    }
+}
+
+

+ 7 - 789
AIRingtone/Business/TSEditAudioVideoVC/TSEditAudioVideoBaseVC.swift

@@ -5,15 +5,14 @@
 //  Created by 100Years on 2025/3/26.
 //  Created by 100Years on 2025/3/26.
 //
 //
 import AVFoundation
 import AVFoundation
-class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelegate {
+class TSEditAudioVideoBaseVC: TSBaseVC {
     //#################################### 数据区域 ####################################//
     //#################################### 数据区域 ####################################//
-    var titleName:String = "Edit".localized
-    
-    var ringModel: TSRingModel
+    var titleName:String{
+        "Edit".localized
+    }
     var editOriginalURL:URL
     var editOriginalURL:URL
     
     
-    init(ringModel: TSRingModel,editOriginalURL:URL) {
-        self.ringModel = ringModel
+    init(editOriginalURL:URL) {
         self.editOriginalURL = editOriginalURL
         self.editOriginalURL = editOriginalURL
         super.init()
         super.init()
     }
     }
@@ -21,240 +20,14 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
     @MainActor required init?(coder: NSCoder) {
     @MainActor required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
         fatalError("init(coder:) has not been implemented")
     }
     }
-    
-    
     //#################################### TSCustomStackView ####################################//
     //#################################### TSCustomStackView ####################################//
     lazy var cusStackView: TSCustomStackView = {
     lazy var cusStackView: TSCustomStackView = {
         let cusStackView = TSCustomStackView(axis: .vertical,spacing: 0)
         let cusStackView = TSCustomStackView(axis: .vertical,spacing: 0)
         return cusStackView
         return cusStackView
     }()
     }()
     
     
-    
-    //#################################### 名字 ####################################//
-    lazy var nameLabel: UILabel = {
-        let nameLabel = UILabel.createLabel(text: ringModel.title, font: .font(size: 14),textColor: .white.withAlphaComponent(0.8),textAlignment: .center)
-        return nameLabel
-    }()
-    
-    weak var nameInputTextField: UITextField?
-    lazy var nameButton: UIButton = {
-        let nameButton = UIButton.createButton(image: UIImage(named: "edit_field")) { [weak self]  in
-            guard let self = self else { return }
-            
-            let alertVC = UIAlertController(title: nil, message: "Ringtone Name".localized, preferredStyle: .alert)
-            alertVC.addTextField { textField in
-                textField.placeholder = "input name".localized
-                textField.font = UIFont.systemFont(ofSize: 16)
-                textField.text = self.ringModel.title
-                self.nameInputTextField = textField
-            }
-            let ok = UIAlertAction(title: "OK".localized, style: .default) { [weak self] _ in
-                guard let self = self else { return }
-                nameLabel.text = nameInputTextField?.text
-                
-                if let text = nameLabel.text{
-                    ringModel.title = text
-                }
-            }
-            let cancel = UIAlertAction(title: "Cancel".localized, style: .cancel)
-            alertVC.addAction(cancel)
-            alertVC.addAction(ok)
-            present(alertVC, animated: true) {
-                self.nameInputTextField?.becomeFirstResponder()
-            }
-            
-        }
-        return nameButton
-    }()
-    
-    lazy var nameView: UIView = {
-        let nameView = UIView()
-        
-        let nameContentView = UIView()
-        nameView.addSubview(nameContentView)
-        nameContentView.snp.makeConstraints { make in
-            make.center.equalToSuperview()
-        }
-        
-        nameContentView.addSubview(nameLabel)
-        nameContentView.addSubview(nameButton)
-        
-        nameLabel.snp.makeConstraints { make in
-            make.leading.equalToSuperview()
-            make.width.greaterThanOrEqualTo(220*kDesignScale)
-            make.height.equalTo(23)
-            make.top.bottom.equalTo(0)
-        }
-        nameButton.snp.makeConstraints { make in
-            make.trailing.equalToSuperview()
-            make.leading.equalTo(nameLabel.snp.trailing)
-            make.width.height.equalTo(23)
-            make.top.bottom.equalTo(0)
-        }
-        
-        return nameView
-    }()
-    
-    //#################################### track编辑视频 ####################################//\
-    let trackContentViewLeft:CGFloat = 24.0
-    let trackViewH:CGFloat = 210.0
-    lazy var trackViewW:CGFloat = k_ScreenWidth - trackContentViewLeft * 2
-    lazy var trackView: ZHWaveformView = {
-        let waveform = ZHWaveformView(frame: CGRect(x: 0, y: 0, width: trackViewW, height:trackViewH),fileURL: editOriginalURL)
-        waveform.backgroundColor = .clear
-        waveform.beginningPartColor = .white.withAlphaComponent(0.2) // color
-        waveform.endPartColor = .white.withAlphaComponent(0.2)
-        waveform.wavesColor = "#7E57F4".uiColor
-        waveform.trackScale = 0.2// 0 ~ 1
-        waveform.waveformDelegate = self
-        waveform.croppedDelegate = self
-        
-        return waveform
-    }()
-    
-    lazy var trackContentView: UIView = {
-        let trackContentView = UIView(frame: CGRectMake(24, 0, k_ScreenWidth-48, trackViewH+12))
-
-        trackContentView.addSubview(trackView)
-        trackView.snp.makeConstraints { make in
-            make.top.centerX.equalToSuperview()
-            make.width.equalTo(trackView.width)
-            make.height.equalTo(trackView.height)
-        }
-        return trackContentView
-    }()
-    
-    
-    func creatDragView()->UIView{
-        let bgView = UIView()
-        
-        let view1 = UIView.creatColor(color: .white)
-        bgView.addSubview(view1)
-        let view2 = UIView.creatColor(color: .white)
-        view2.cornerRadius = 6
-        bgView.addSubview(view2)
-        
-        view1.snp.makeConstraints { make in
-            make.width.equalTo(2)
-            make.height.equalTo(trackViewH)
-            make.centerX.equalToSuperview()
-            make.top.equalToSuperview()
-        }
-        
-        view2.snp.makeConstraints { make in
-            make.top.equalTo(view1.snp.bottom)
-            make.width.height.equalTo(12)
-            make.bottom.equalToSuperview()
-            make.leading.equalTo(12)
-            make.trailing.equalTo(-12)
-        }
-        return bgView
-    }
-    lazy var dragLeftView: UIView = creatDragView()
-    lazy var dragRightView: UIView = creatDragView()
-    var progressLine: UIView = UIView.creatColor(color: .themeColor)
-    
-    
-    lazy var startTimeLabel: UILabel = {
-        let label = UILabel.createLabel(text: "00:00s",font: .font(size: 14.0),textColor: .lesserText)
-        return label
-    }()
-    var endTimeLabel: UILabel = {
-        let label = UILabel.createLabel(text: "10:00s",font: .font(size: 14.0),textColor: .lesserText)
-        return label
-    }()
-    var timeLabel: UILabel = {
-        let label = UILabel.createLabel(text: "00:00",font: .font(size: 26.0),textColor: .lesserText)
-        return label
-    }()
-    
-    
-    lazy var timeView: UIView = {
-        let timeView = UIView()
-        
-        timeView.addSubview(startTimeLabel)
-        timeView.addSubview(endTimeLabel)
-        timeView.addSubview(timeLabel)
-        
-        startTimeLabel.snp.makeConstraints { make in
-            make.leading.equalTo(16)
-            make.top.equalTo(12)
-            make.height.equalTo(20)
-        }
-        
-        endTimeLabel.snp.makeConstraints { make in
-            make.trailing.equalTo(-16)
-            make.top.equalTo(12)
-            make.height.equalTo(20)
-        }
-        
-        timeLabel.snp.makeConstraints { make in
-            make.centerX.equalToSuperview()
-            make.top.equalTo(45)
-            make.height.equalTo(26)
-        }
-        
-        return timeView
-    }()
-    
-    lazy var trackBgView: UIView  = {
-        let trackBgView = UIView()
-        
-        let leftPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.leftPanRecognizer(sender:)))
-        dragLeftView.addGestureRecognizer(leftPanRecognizer)
-        dragLeftView.isUserInteractionEnabled = true
 
 
-        let rightPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.rightPanRecognizer(sender:)))
-        dragRightView.addGestureRecognizer(rightPanRecognizer)
-        dragRightView.isUserInteractionEnabled = true
-        
-        let gradientImageView = UIImageView.createImageView(imageName: "trackBg_gradient",contentMode: .scaleToFill)
-        trackBgView.addSubview(gradientImageView)
-        gradientImageView.snp.makeConstraints { make in
-            make.leading.top.trailing.equalToSuperview()
-            make.height.equalTo(trackViewH)
-        }
-
-        trackBgView.addSubview(trackContentView)
-        trackContentView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.leading.equalTo(trackContentView.x)
-            make.trailing.equalTo(-trackContentView.x)
-            make.height.equalTo(trackViewH)
-        }
-        
-   
-        trackBgView.addSubview(dragLeftView)
-        dragLeftView.snp.makeConstraints { make in
-            make.top.leading.equalToSuperview()
-        }
-        
-        trackBgView.addSubview(dragRightView)
-        dragRightView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.trailing.equalToSuperview()
-        }
-        progressLine.isHidden = true
-        trackBgView.addSubview(progressLine)
-        progressLine.snp.makeConstraints { make in
-            make.top.leading.equalToSuperview()
-            make.width.equalTo(1)
-            make.height.equalTo(trackViewH)
-        }
-        
-        trackBgView.addSubview(timeView)
-        timeView.snp.makeConstraints { make in
-            make.top.equalTo(trackContentView.bottom)
-            make.trailing.leading.equalToSuperview()
-            make.height.equalTo(71)
-            make.bottom.equalTo(0)
-        }
-        
-        return trackBgView
-    }()
-    
-    
-    //#################################### paly按钮 ####################################//
+    //#################################### play按钮 ####################################//
     
     
     lazy var playButtonView: UIView = {
     lazy var playButtonView: UIView = {
         let playButtonView = UIView(frame: CGRectMake(0, 0, k_ScreenWidth, 18+80+18))
         let playButtonView = UIView(frame: CGRectMake(0, 0, k_ScreenWidth, 18+80+18))
@@ -277,7 +50,6 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
         return playButtonView
         return playButtonView
     }()
     }()
     
     
-    
     lazy var playButton: UIButton = {//editaudio_play //editaudio_pause
     lazy var playButton: UIButton = {//editaudio_play //editaudio_pause
         let playButton = UIButton.createButton(image: UIImage(named: "editaudio_play")){ [weak self]  in
         let playButton = UIButton.createButton(image: UIImage(named: "editaudio_play")){ [weak self]  in
             guard let self = self else { return }
             guard let self = self else { return }
@@ -287,58 +59,6 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
         return playButton
         return playButton
     }()
     }()
     
     
-    
-    //#################################### Fade in ####################################//
-    lazy var fadeinSliderView: TSEditAudioSliderView = {
-        let fadeinSliderView = TSEditAudioSliderView()
-        fadeinSliderView.leftLabel.text = "Fade in".localized
-        fadeinSliderView.rightLabel.text = "0s"
-        fadeinSliderView.slider.maximumValue = 5
-//        fadeinSliderView.slider.value = 3
-        return fadeinSliderView
-    }()
-    lazy var fadeinSlider: UISlider = {
-        let slider = fadeinSliderView.slider
-        slider.addTarget(self, action: #selector(sliderBeginTap(_:)), for: .touchDown)
-        slider.addTarget(self, action: #selector(sliderEndTap(_:)), for: .touchUpInside)
-        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
-        return slider
-    }()
-    //#################################### Fade out ####################################//
-    
-    lazy var fadeoutSliderView: TSEditAudioSliderView = {
-        let fadeoutSliderView = TSEditAudioSliderView()
-        fadeoutSliderView.leftLabel.text = "Fade out".localized
-        fadeoutSliderView.rightLabel.text = "0s"
-        fadeoutSliderView.slider.maximumValue = 5
-//        fadeoutSliderView.slider.value = 3
-        return fadeoutSliderView
-    }()
-    lazy var fadeoutSlider: UISlider = {
-        let slider = fadeoutSliderView.slider
-        slider.addTarget(self, action: #selector(sliderBeginTap(_:)), for: .touchDown)
-        slider.addTarget(self, action: #selector(sliderEndTap(_:)), for: .touchUpInside)
-        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
-        return slider
-    }()
-    //#################################### Output Volume ####################################//
-    lazy var outputVolumeSliderView: TSEditAudioSliderView = {
-        let outputVolumeSliderView = TSEditAudioSliderView()
-        outputVolumeSliderView.leftLabel.text = "Output Volume".localized
-        outputVolumeSliderView.rightLabel.text = "100%"
-        outputVolumeSliderView.slider.minimumValue = 1.0
-        outputVolumeSliderView.slider.maximumValue = 2.0
-//        outputVolumeSliderView.slider.value = 1.5
-        return outputVolumeSliderView
-    }()
-    lazy var outputVolumeSlider: UISlider = {
-        let slider = outputVolumeSliderView.slider
-        slider.addTarget(self, action: #selector(sliderBeginTap(_:)), for: .touchDown)
-        slider.addTarget(self, action: #selector(sliderEndTap(_:)), for: .touchUpInside)
-        slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged)
-        return slider
-    }()
-    
     //#################################### 底部保存按钮等 ####################################//
     //#################################### 底部保存按钮等 ####################################//
     lazy var cutButton: TSAppBtnView = { //保存
     lazy var cutButton: TSAppBtnView = { //保存
         let cutButton = TSAppBtnView()
         let cutButton = TSAppBtnView()
@@ -360,9 +80,6 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
         return doneButton
         return doneButton
     }()
     }()
     
     
-    
-    var undoButton: UIButton!//暂时没用
-    
     lazy var bottomBtnView: UIView = {
     lazy var bottomBtnView: UIView = {
         let bottomBtnView = UIView()
         let bottomBtnView = UIView()
         
         
@@ -405,93 +122,8 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
             make.top.leading.bottom.trailing.equalTo(0)
             make.top.leading.bottom.trailing.equalTo(0)
             make.bottom.equalTo(bottomBtnView.snp.top)
             make.bottom.equalTo(bottomBtnView.snp.top)
         }
         }
-        setUpCusStackView()
-    }
-    
-    func setUpCusStackView() {
-        cusStackView.addSubviewToStack(nameView)
-        nameView.snp.makeConstraints { make in
-            make.height.equalTo(56)
-            make.width.equalTo(k_ScreenWidth)
-        }
-        cusStackView.addSubviewToStack(trackBgView)
-        trackBgView.snp.makeConstraints { make in
-            make.height.equalTo(300)
-            make.width.equalTo(k_ScreenWidth)
-        }
-        
-        cusStackView.addSubviewToStack(playButtonView)
-        playButtonView.snp.makeConstraints { make in
-            make.height.equalTo(playButtonView.height)
-            make.width.equalTo(playButtonView.width)
-        }
-        
-        cusStackView.addSubviewToStack(fadeinSliderView)
-        fadeinSliderView.snp.makeConstraints { make in
-            make.height.equalTo(fadeinSliderView.height)
-        }
-        
-        let spaceView = UIView()
-        cusStackView.addSubviewToStack(spaceView)
-        spaceView.snp.makeConstraints { make in
-            make.height.equalTo(8)
-        }
-        
-        cusStackView.addSubviewToStack(fadeoutSliderView)
-        fadeoutSliderView.snp.makeConstraints { make in
-            make.height.equalTo(fadeinSliderView.height)
-        }
-        
-        let spaceView1 = UIView()
-        cusStackView.addSubviewToStack(spaceView1)
-        spaceView1.snp.makeConstraints { make in
-            make.height.equalTo(8)
-        }
-        
-        cusStackView.addSubviewToStack(outputVolumeSliderView)
-        outputVolumeSliderView.snp.makeConstraints { make in
-            make.height.equalTo(fadeinSliderView.height)
-            make.bottom.equalToSuperview()
-        }
-    
-        _ = fadeinSlider
-        _ = fadeoutSlider
-        _ = outputVolumeSlider
-    }
-    
-    override func dealThings() {
-        
-        dePrint("TSEditAudioVideoBaseVC ringModel = \(String(describing: ringModel.toJSONString())),editOriginalURL = \(editOriginalURL)")
-        
-        if ringModel.duration == 0, player.duration != 0 {
-            ringModel.duration = Int(player.duration)
-        }
-        
-        operationCache.append(ringModel)
-        reloadTrackView()
     }
     }
 
 
-    private lazy var player:TSBusinessAudioPlayer = {
-        let player = TSBusinessAudioPlayer()
-        player.loadLoactionURL(url: self.editOriginalURL)
-        player.currentTimeChangedHandle = { [weak self] current,total in
-            guard let self = self else { return }
-            handlePlayer(progressChanged: current, total: total)
-        }
-        
-        player.stateChangedHandle = { [weak self] state in
-            guard let self = self else { return }
-            handlePlayer(state: state)
-        }
-        
-        return player
-    }()
-    private lazy var audioTool = AudioTool()
-    private var maxVolume:Float{
-        return outputVolume * 0.5
-    }
-    
-    
     lazy var operationCache: [TSRingModel] = []
     lazy var operationCache: [TSRingModel] = []
     var tempMp3Path: String?
     var tempMp3Path: String?
     var needClearTemp : Bool = false
     var needClearTemp : Bool = false
@@ -531,37 +163,10 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
 
 
     }
     }
     
     
-    //    lazy var previousBounds: CGRect = .zero
-    //    override func viewDidLayoutSubviews() {
-    //        super.viewDidLayoutSubviews()
-    //
-    //        if previousBounds == .zero {
-    //            previousBounds = view.bounds
-    //            DispatchQueue.main.async {
-    //                self.reloadTrackView()
-    //            }
-    //        }
-    //    }
-    
     deinit {
     deinit {
         dePrint("RingEditViewController 销毁了")
         dePrint("RingEditViewController 销毁了")
     }
     }
     
     
-    func reloadTrackView() {
-    
-        tempMp3Path = editOriginalURL.path
-
-        startCropRate = 0
-        endCropRate = 1.0
-        dragLeftView.centerX = trackContentView.x
-        dragRightView.centerX = trackContentView.frame.maxX
-        
-        
-        timeLabel.text = ringModel.duration.mmss
-//        undoButton.isEna bled = operationCache.count > 1
-        cutButton.setBtnEnabled(isEnabled: false)
-    }
-
     override func navBarClickLeftAction() {
     override func navBarClickLeftAction() {
         TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
         TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
             message: "As you leave, the changes you have made will be lost.".localized,
             message: "As you leave, the changes you have made will be lost.".localized,
@@ -583,405 +188,18 @@ class TSEditAudioVideoBaseVC: TSBaseVC , ZHCroppedDelegate, ZHWaveformViewDelega
             }
             }
         ))
         ))
     }
     }
-    //#################################### UI 储存属性 ####################################//
-    lazy var fadeInDuration: Int = 0 {
-        didSet {
-            fadeinSliderView.rightLabel.text = "\(fadeInDuration)s"
-        }
-    }
-    lazy var fadeOutDuration: Int = 0 {
-        didSet {
-            fadeoutSliderView.rightLabel.text = "\(fadeOutDuration)s"
-        }
-    }
     
     
-    lazy var outputVolume: Float = 1.0 {
-        didSet {
-            outputVolumeSliderView.rightLabel.text = "\(Int(outputVolume*100.0))%"
-        }
-    }
-    lazy var previousLeftX: CGFloat = 0
-    lazy var startCropRate: CGFloat = 0 {
-        didSet {
-            let time = startDuration
-            cutButton.setBtnEnabled(isEnabled: true)
-            
-            //            print("---start: \(time)")
-            startTimeLabel.text = time.mmss
-            timeLabel.text = (endDuration - startDuration).mmss
-        }
-    }
-    // 拖拽时被暂停,拖拽结束后,继续播放
-    lazy var isSuspendByAction = false
-    lazy var endCropRate: CGFloat = 1.0 {
-        didSet {
-            cutButton.setBtnEnabled(isEnabled: true)
-            let time = endDuration
-            endTimeLabel.text = time.mmss
-            timeLabel.text = (endDuration - startDuration).mmss
-        }
-    }
-    lazy var previousRightX: CGFloat = 0
-}
-
-
-extension TSEditAudioVideoBaseVC {
     
     
-
-    
-    @objc func sliderBeginTap(_ slider: UISlider) {
-        suspendPlay()
-    }
-    
-    @objc func sliderEndTap(_ slider: UISlider) {
-        autoPlayAfterMove()
-    }
-    
-    @objc func sliderValueChanged(_ slider: UISlider) {
-        //        print("---\(slider.value)")
-        if player.isPlaying {
-            player.pause()
-        }
-        if slider == fadeinSlider {
-            fadeInDuration = Int(slider.value.rounded(.toNearestOrEven))
-        } else if slider == fadeoutSlider {
-            fadeOutDuration = Int(slider.value.rounded(.toNearestOrEven))
-        } else if slider == outputVolumeSlider {
-            outputVolume = slider.value
-        }
-    }
-
-    
-    // 裁剪起始时间
-    var startDuration: Double {
-        return startCropRate * CGFloat(ringModel.duration)
-    }
-    
-
-    
-    var startMinCenterX: CGFloat {
-        return trackContentView.x
-    }
-    
-    var startMaxCenterX: CGFloat {
-        let ratio = (endCropRate * CGFloat(ringModel.duration) - 10) / CGFloat(ringModel.duration)
-        return ratio * trackContentView.width + trackContentView.x
-    }
-    
-    var endMinCenterX: CGFloat {
-        let ratio = (startCropRate * CGFloat(ringModel.duration) + 10) / CGFloat(ringModel.duration)
-        return ratio * trackContentView.width + trackContentView.x
-    }
-    
-    var endMaxCenterX: CGFloat {
-        return trackContentView.frame.maxX
-    }
-
-    @objc private func leftPanRecognizer(sender: UIPanGestureRecognizer) {
-        
-        dePrint("TSEditAudioVideoBaseVC leftPanRecognizer=\(sender)")
-        let limitMinCenterX: CGFloat = startMinCenterX
-        let limitMaxCenterX: CGFloat = startMaxCenterX
-        guard limitMaxCenterX > limitMinCenterX else {
-            if sender.state == .began {
-                dePrint("TSEditAudioVideoBaseVC rightPanRecognizer No less than 10s")
-                TSToastShared.showToast(text:"No less than 10s".localized)
-            }
-            return
-        }
-        
-        if sender.state == .began {
-            suspendPlay()
-        } else if sender.state == .changed {
-            // 修改位置
-            let newPoint = sender.translation(in: trackBgView)
-            var center = dragLeftView.center
-            center.x = previousLeftX + newPoint.x
-            guard center.x > limitMinCenterX,
-                  center.x < limitMaxCenterX else {
-                // 越界,拖不动了, 最少10s
-                if endDuration - startDuration < 11 {
-                    TSToastShared.showToast(text:"No less than 10s".localized)
-                }
-                return
-            }
-            dragLeftView.center = center
-            
-        } else if sender.state == .ended || sender.state == .failed {
-            previousLeftX = dragLeftView.center.x
-            autoPlayAfterMove()
-        }
-        
-        // 边界校验
-        if dragLeftView.centerX < limitMinCenterX {
-            dragLeftView.centerX = limitMinCenterX
-        }
-        if dragLeftView.centerX > limitMaxCenterX {
-            dragLeftView.centerX = limitMaxCenterX
-        }
-        
-        let position = dragLeftView.centerX - trackContentView.x
-        trackView.updateLeftCroppedPosition(position)
-        startCropRate = position / trackContentView.width
-        progressLine.centerX = dragLeftView.centerX
-    }
-    
-
-    var endDuration: Double {
-        return endCropRate * CGFloat(CGFloat(ringModel.duration))
-    }
-    
-
-    @objc private func rightPanRecognizer(sender: UIPanGestureRecognizer) {
-        dePrint("TSEditAudioVideoBaseVC rightPanRecognizer=\(sender)")
-        let limitMinCenterX: CGFloat = endMinCenterX
-        let limitMaxCenterX: CGFloat = endMaxCenterX
-        guard limitMaxCenterX > limitMinCenterX else {
-            if sender.state == .began {
-                dePrint("TSEditAudioVideoBaseVC rightPanRecognizer No less than 10s")
-                // 越界,拖不动了
-                TSToastShared.showToast(text:"No less than 10s".localized)
-            }
-            return
-        }
-        
-        if sender.state == .began {
-            suspendPlay()
-        } else if sender.state == .changed {
-            let newPoint = sender.translation(in: trackBgView)
-            var center = dragRightView.center
-            center.x = previousRightX + newPoint.x
-            guard center.x > limitMinCenterX, center.x < limitMaxCenterX else {
-                // 越界,拖不动了, 最少10s
-                if endDuration - startDuration < 11 {
-                    TSToastShared.showToast(text:"No less than 10s".localized)
-                }
-                return
-            }
-            dragRightView.center = center
-        } else if sender.state == .ended || sender.state == .failed {
-            previousRightX = dragRightView.centerX
-            autoPlayAfterMove()
-        }
-        
-        // 边界校验
-        if dragRightView.centerX > limitMaxCenterX {
-            dragRightView.centerX = limitMaxCenterX
-        }
-        if dragRightView.centerX < limitMinCenterX {
-            dragRightView.centerX = limitMinCenterX
-        }
-        
-        let position = dragRightView.centerX - trackContentView.x
-        trackView.updateRightCroppedPosition(position)
-        endCropRate = position / trackContentView.width
-    }
-    
-    @IBAction func buttonClick(_ sender: UIButton) {
-        let model = ringModel
-        
-        //        switch sender {
-        //        case playButton:
-        //            startPlay()
-        //        case undoButton:
-        //            player.pause()
-        //            operationCache.removeLast()
-        //            ringModel = operationCache.last
-        //            reloadTrackView()
-        //        case cutButton:
-        //            startCutAudio { [weak self] newModel, errMsg in
-        //                DispatchQueue.main.async {
-        //                    if let newModel = newModel {
-        //                        self?.operationCache.append(newModel)
-        //                        self?.ringModel = newModel
-        //                        self?.reloadTrackView()
-        //                    } else {
-        //                        TSToastShared.showToast(text:errMsg ?? "Sorry, Edit Failure".localized)
-        //                    }
-        //                }
-        //            }
-        //        case doneButton:
-        //            player.pause()
-        //            startCutAudio { [weak self] result, errMsg in
-        //                guard let self = self else { return }
-        //                DispatchQueue.main.async {
-        //                    if let ringModel = result {
-        //                        TSToastShared.showLoading(containerView: self.view)
-        ////                        RingDownloadManager.shared.shareBand(with: ringModel) { _ in
-        ////                            DispatchQueue.main.async {
-        ////                                TSToastShared.hideLoading()
-        ////                            }
-        ////                        }
-        //                    } else {
-        //                        TSToastShared.showToast(text:errMsg ?? "Sorry, Edit Failure".localized)
-        //                    }
-        //                }
-        //            }
-        
-        //        default:
-        //            break
-        //        }
-    }
-    
-    // 拖拽,暂停
-    func suspendPlay() {
-        if player.isPlaying {
-            isSuspendByAction = true
-            player.pause()
-        }
-    }
-    
-    // 停止拖拽,继续播放
-    func autoPlayAfterMove() {
-        startPlay()
-        isSuspendByAction = false
-    }
     
     
     func startPlay() {
     func startPlay() {
-        let model = ringModel
         
         
-        playButton.isSelected = !playButton.isSelected
-        if player.isPlaying {
-            player.pause()
-        } else {
-            
-            player.playUrlString(model.audioUrl,localURL: editOriginalURL)
-//            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
-                self.player.seek(to:self.startDuration)
-//            }
-            player.setVolume(volume: fadeInDuration > 0 ? 0 : maxVolume)
-
-            if UIApplication.getSystemVolume() < 0.1 {
-                TSToastShared.showToast(text:"Please turn up the volume".localized)
-            }
-            
-        }
     }
     }
     
     
     func saveButtonClick() {
     func saveButtonClick() {
-        handleSaveCutAudio()
-    }
-    
-    
-    func handleSaveCutAudio(completion:((TSRingModel?)->Void)? = nil){
-        player.pause()
-        // 保存音频
-        startCutAudio { result, errMsg,savePath in
-            if let ringModel = result {
-                // 裁剪的音频,使用本地文件播放,清空网络url
-                dePrint("TSEditAudioVideoBaseVC saveModel ringModel = \(ringModel.toJSONString())")
-                TSMineRintoneHistory.shared.saveModel(model: ringModel)
-                
-                completion?(ringModel)
-                DispatchQueue.main.async {
-                    self.pop()
-                    if let window = WindowHelper.getKeyWindow() {
-                        kSaveSuccesswShared.show(atView:window,text: "Saved in “My Ringtone”".localized) { [weak self]  in
-                            guard let self = self else { return }
-                            if let vc = WindowHelper.getCurrentViewController(){
-                                kPushVC(target: vc, modelVC: TSRingDownVC())
-                            }
-                        }
-                    }
-                }
-            } else {
-                DispatchQueue.main.async {
-                    TSToastShared.showToast(text: errMsg ?? "Sorry, Save Failure".localized)
-                }
-                completion?(nil)
-            }
-        }
+        
     }
     }
     
     
     func setButtonClick() {
     func setButtonClick() {
-        handleSaveCutAudio { model in
-            if let ringModel = model {
-                let path = ringModel.documentPath.fillDocumentURL
-                _ = kPurchaseToolShared.kshareBand(needVip: false, vc: self, fileURL: path, fileName: ringModel.title)
-            }
-        }
-    }
-    
-    // 裁剪
-    func startCutAudio(completion: ((TSRingModel?, String?,URL?) -> Void)?) {
-        guard let copyModel = ringModel.copy() as? TSRingModel else {
-            completion?(nil, nil, nil)
-            return
-        }
-       
-    
-       let savePath = TSDownloadManager.generateRingSaveLocalURL(name: copyModel.title)
-        TSFileManagerTool.checkFolderAndCreate(from: savePath)
         
         
-        copyModel.duration = Int(endDuration - startDuration)
-        TSRingLoadingView.shared.showWindow()
-        audioTool.startTansformAudio(url:editOriginalURL.path, from: startDuration, to: endDuration, fadeIn: Double(fadeInDuration), fadeOut: Double(fadeOutDuration),addVolume: Double(outputVolume) ,savePath: savePath.path) { filePath, errMsg in
-            DispatchQueue.main.async {
-                TSRingLoadingView.shared.remove()
-            }
-            if let filePath = filePath {
-                let url = URL(fileURLWithPath: filePath)
-                copyModel.documentPath = filePath.documentLastURLString
-                
-                if let fileInfo = TSBusinessAudioPlayer.getAudioFileInfo(path: url.path) {
-                    if let size = fileInfo.sizeInBytes {
-                        copyModel.size = Int(size)
-                    }
-                    if let duration = fileInfo.durationInSeconds {
-                        copyModel.duration = Int(duration)
-                    }
-                }
-    
-                completion?(copyModel, errMsg, savePath)
-            } else {
-                completion?(nil, errMsg, nil)
-            }
-        }
-    }
-    
-}
-extension TSEditAudioVideoBaseVC {
-    func handlePlayer(state: TSBusinessAudioPlayer.PlayerState) {
-        playButton.isSelected = player.isPlaying
-        progressLine.isHidden = !playButton.isSelected
-        if player.currentPlayerState == .play {
-            progressLine.centerX = dragLeftView.centerX
-        }
-    }
-
-    func handlePlayer(progressChanged current: Double, total: Double) {
-        let range = endDuration - startDuration
-        let rangeWidth = trackContentView.width * range / total
-        let progress = max(0, current - startDuration) / range
-
-        if player.isPlaying {
-            progressLine.centerX = dragLeftView.centerX + progress * rangeWidth
-        }
-
-        if current >= endDuration {
-            player.pause()
-        }
-
-        // 淡入
-        if fadeInDuration > 0, current - startDuration < Double(fadeInDuration) {
-            let fadeProgress = Float(current - startDuration) / Float(fadeInDuration)
-            let newVolume = min(fadeProgress * maxVolume * 100, 100.0)
-            print("---volume: \(newVolume)")
-            player.setVolume(volume:newVolume / 100)
-        }
-
-        // 淡出
-        if fadeOutDuration > 0, current > (endDuration - Double(fadeOutDuration)) {
-            let fadeProgress = Float(endDuration - current) / Float(fadeOutDuration)
-            let newVolume = max(fadeProgress * maxVolume * 100, 0.0)
-            print("---volume: \(newVolume)")
-            player.setVolume(volume: newVolume / 100)
-        }
-    }
-
-    func sanitizeFilePath(_ path: String) -> String {
-        let illegalFileNameCharacters = CharacterSet(charactersIn: "/\\?%*|\"<>: ")
-        let sanitizedPath = path.components(separatedBy: illegalFileNameCharacters).joined(separator: "_")
-        return sanitizedPath
     }
     }
 }
 }

+ 1 - 42
AIRingtone/Common/Tool/TSAudioPlayer/TSBusinessAudioPlayer.swift

@@ -110,11 +110,6 @@ class TSBusinessAudioPlayer {
         self.stop()
         self.stop()
         if let urlString = urlString {
         if let urlString = urlString {
             
             
-//            if self.currentURLString == urlStrin {
-//                self.play()
-//                return
-//            }
-            
             self.currentURLString = urlString
             self.currentURLString = urlString
             self.currentLocalURL = localURL
             self.currentLocalURL = localURL
             self.currentIndexPath = indexPath
             self.currentIndexPath = indexPath
@@ -153,7 +148,6 @@ class TSBusinessAudioPlayer {
                 palyFile(path) //播放
                 palyFile(path) //播放
                 
                 
             }else if let path = TSDownloadManager.getRingLocalURL(urlString: urlString) {
             }else if let path = TSDownloadManager.getRingLocalURL(urlString: urlString) {
-//            if let path = TSCommonTool.getCachedURLString(from: urlString,missingEx: "mp3") {
                 palyFile(path) //播放
                 palyFile(path) //播放
             }else{
             }else{
                 self.changePlayerState(.loading(0.0))
                 self.changePlayerState(.loading(0.0))
@@ -175,23 +169,6 @@ class TSBusinessAudioPlayer {
                         self.stop()
                         self.stop()
                     }
                     }
                 }
                 }
-                
-//                TSCommonTool.downloadAndCacheFile(from: urlString,missingEx: "mp3") { [weak self] path, error in
-//                    guard let self = self else { return }
-//                    self.changePlayerState(.loading(1.0))
-//                
-//                    if isStopPlayingAfterLoading == true || currentURLString != urlString{
-//                        isStopPlayingAfterLoading = false
-//                        return
-//                    }
-//                    
-//                    if let path = path {
-//                        palyFile(URL(fileURLWithPath: path)) //播放
-//                    }else{
-//                        //暂停
-//                        self.stop()
-//                    }
-//                }
             }
             }
         }
         }
     }
     }
@@ -217,8 +194,7 @@ class TSBusinessAudioPlayer {
     }
     }
     
     
     func setVolume(volume:Float){
     func setVolume(volume:Float){
-        self.audioPlayer?.volume = volume 
-//        self.audioPlayer?.setVolume(volume)
+        self.audioPlayer?.volume = volume
         changePlayerState(.volume(volume))
         changePlayerState(.volume(volume))
     }
     }
     
     
@@ -251,23 +227,6 @@ extension TSBusinessAudioPlayer{
     struct AudioFileInfo {
     struct AudioFileInfo {
         let sizeInBytes: UInt64?    // 文件大小(字节)
         let sizeInBytes: UInt64?    // 文件大小(字节)
         let durationInSeconds: Double?  // 音频时长(秒)
         let durationInSeconds: Double?  // 音频时长(秒)
-        
-//        // 计算属性:格式化显示
-//        var formattedSize: String {
-//            guard let size = sizeInBytes else { return "未知大小" }
-//            let formatter = ByteCountFormatter()
-//            formatter.allowedUnits = [.useBytes, .useKB, .useMB, .useGB]
-//            return formatter.string(fromByteCount: Int64(size))
-//        }
-//        
-//        var formattedDuration: String {
-//            guard let duration = durationInSeconds else { return "未知时长" }
-//            let formatter = DateComponentsFormatter()
-//            formatter.unitsStyle = .positional
-//            formatter.allowedUnits = [.hour, .minute, .second]
-//            formatter.zeroFormattingBehavior = .pad
-//            return formatter.string(from: duration) ?? "00:00"
-//        }
     }
     }
 
 
     static func getAudioFileInfo(path: String) -> AudioFileInfo? {
     static func getAudioFileInfo(path: String) -> AudioFileInfo? {

+ 3 - 1
AIRingtone/Common/Tool/TSBandRingTool/TSBandRingTool.swift

@@ -139,6 +139,8 @@ class TSBandRingTool:NSObject {
     
     
     func shareRing(fileUrl: URL) {
     func shareRing(fileUrl: URL) {
         DispatchQueue.main.async {
         DispatchQueue.main.async {
+            guard let targetVC = self.targetVC else { return }
+            
             self.showTutorialVideo()
             self.showTutorialVideo()
             
             
             let vc = UIActivityViewController(activityItems: [fileUrl], applicationActivities: nil)
             let vc = UIActivityViewController(activityItems: [fileUrl], applicationActivities: nil)
@@ -160,7 +162,7 @@ class TSBandRingTool:NSObject {
 //                .airDrop,
 //                .airDrop,
 //                .openInIBooks
 //                .openInIBooks
 //            ]
 //            ]
-            self.targetVC?.present(vc, animated: true, completion: {
+            targetVC.present(vc, animated: true, completion: {
                 self.tryStartPictureInPicture()
                 self.tryStartPictureInPicture()
             })
             })