kln 2 долоо хоног өмнө
parent
commit
461e18eb73
71 өөрчлөгдсөн 1681 нэмэгдсэн , 528 устгасан
  1. 26 2
      AIPlayRingtones.xcodeproj/project.pbxproj
  2. 78 0
      AIPlayRingtones.xcodeproj/xcshareddata/xcschemes/AIPlayRingtones.xcscheme
  3. 31 27
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift
  4. 28 19
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift
  5. 3 0
      AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift
  6. 66 10
      AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift
  7. 33 10
      AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift
  8. 29 19
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC.swift
  9. 2 2
      AIPlayRingtones/AppPage/APSettingVC/APSettingVC.swift
  10. 42 44
      AIPlayRingtones/AppPage/ASCommonView/ASBtnView/ASAppBtnView.swift
  11. 332 231
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorBaseVC.swift
  12. 4 36
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC+load.swift
  13. 14 28
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC.swift
  14. 3 3
      AIPlayRingtones/AppPage/Common/ Notification+Ex.swift
  15. 10 0
      AIPlayRingtones/AppPage/Common/Ex/UIFont+TSEx.swift
  16. 1 1
      AIPlayRingtones/AppPage/Common/TSNetWork/TSNetWork+Business.swift
  17. BIN
      AIPlayRingtones/Assets.xcassets/App-Icon.imageset/App-Icon.png
  18. 21 0
      AIPlayRingtones/Assets.xcassets/App-Icon.imageset/Contents.json
  19. 99 14
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/Contents.json
  20. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-1024.png
  21. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
  22. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
  23. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
  24. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
  25. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png
  26. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png
  27. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
  28. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
  29. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
  30. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
  31. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png
  32. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png
  33. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png
  34. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
  35. BIN
      AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
  36. 22 0
      AIPlayRingtones/Assets.xcassets/CellPlay/refresh_purple.imageset/Contents.json
  37. BIN
      AIPlayRingtones/Assets.xcassets/CellPlay/refresh_purple.imageset/refresh_purple@2x.png
  38. BIN
      AIPlayRingtones/Assets.xcassets/CellPlay/refresh_purple.imageset/refresh_purple@3x.png
  39. BIN
      AIPlayRingtones/Assets.xcassets/Common/failed_big.imageset/failed_big@2x.png
  40. BIN
      AIPlayRingtones/Assets.xcassets/Common/failed_big.imageset/failed_big@3x.png
  41. 22 0
      AIPlayRingtones/Assets.xcassets/Common/generated_loading.imageset/Contents.json
  42. BIN
      AIPlayRingtones/Assets.xcassets/Common/generated_loading.imageset/generated_loading@2x.png
  43. BIN
      AIPlayRingtones/Assets.xcassets/Common/generated_loading.imageset/generated_loading@3x.png
  44. BIN
      AIPlayRingtones/Assets.xcassets/Common/network_error.imageset/network_error@2x.png
  45. BIN
      AIPlayRingtones/Assets.xcassets/Common/network_error.imageset/network_error@3x.png
  46. BIN
      AIPlayRingtones/Assets.xcassets/Common/pageNull.imageset/pageNull@2x.png
  47. BIN
      AIPlayRingtones/Assets.xcassets/Common/pageNull.imageset/pageNull@3x.png
  48. 22 0
      AIPlayRingtones/Assets.xcassets/Common/page_x.imageset/Contents.json
  49. BIN
      AIPlayRingtones/Assets.xcassets/Common/page_x.imageset/page_x@2x.png
  50. BIN
      AIPlayRingtones/Assets.xcassets/Common/page_x.imageset/page_x@3x.png
  51. 22 0
      AIPlayRingtones/Assets.xcassets/Common/setAs_bg.imageset/Contents.json
  52. BIN
      AIPlayRingtones/Assets.xcassets/Common/setAs_bg.imageset/setAs_bg@2x.png
  53. BIN
      AIPlayRingtones/Assets.xcassets/Common/setAs_bg.imageset/setAs_bg@3x.png
  54. 22 0
      AIPlayRingtones/Assets.xcassets/Common/x.imageset/Contents.json
  55. BIN
      AIPlayRingtones/Assets.xcassets/Common/x.imageset/x@2x.png
  56. BIN
      AIPlayRingtones/Assets.xcassets/Common/x.imageset/x@3x.png
  57. 13 15
      AIPlayRingtones/Base.lproj/LaunchScreen.storyboard
  58. 3 1
      AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorErrorView.swift
  59. 15 2
      AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorLoadingView.swift
  60. 7 7
      AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorView.swift
  61. 3 4
      AIPlayRingtones/CommonView/ASPageNullView.swift
  62. 101 35
      AIPlayRingtones/CommonView/ASRingToneCellView.swift
  63. 488 0
      AIPlayRingtones/CommonView/FakeBlurView.swift
  64. 0 0
      AIPlayRingtones/CommonView/Untitled.swift
  65. 8 0
      AIPlayRingtones/Info.plist
  66. 4 1
      AIPlayRingtones/OperationQueue/ASBaseOperationQueue.swift
  67. 1 1
      AIPlayRingtones/OperationQueue/ASProgressState.swift
  68. 32 12
      AIPlayRingtones/OperationQueue/Generate/ASGenerateBaseOperation.swift
  69. 74 4
      AIPlayRingtones/OperationQueue/Generate/ASGenerateTextToRingOperation.swift
  70. BIN
      AIPlayRingtones/Resources/Poppins-BoldItalic.otf
  71. BIN
      AIPlayRingtones/Resources/rotatingAnimation.gif

+ 26 - 2
AIPlayRingtones.xcodeproj/project.pbxproj

@@ -17,6 +17,9 @@
 		3DB4D4A32DDC34100082596A /* ASRTRFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A22DDC34020082596A /* ASRTRFileView.swift */; };
 		3DB4D4A52DDC8E830082596A /* APSettingVC+Col.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A42DDC8E7B0082596A /* APSettingVC+Col.swift */; };
 		3DB4D4A82DDC92560082596A /* ASBusinessWebVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A72DDC92530082596A /* ASBusinessWebVC.swift */; };
+		3DB4D4AA2DDDCEA50082596A /* Poppins-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A92DDDCEA50082596A /* Poppins-BoldItalic.otf */; };
+		3DB4D4AE2DDDCED00082596A /* UIFont+TSEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4AB2DDDCED00082596A /* UIFont+TSEx.swift */; };
+		3DB4D4B22DDF0B960082596A /* FakeBlurView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4B12DDF0B940082596A /* FakeBlurView.swift */; };
 		3DCD56F32DDAE3E3004AAB5B /* ASRingToneCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F22DDAE3DF004AAB5B /* ASRingToneCellView.swift */; };
 		3DCD56F52DDAE42A004AAB5B /* ASViewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F42DDAE421004AAB5B /* ASViewTool.swift */; };
 		3DCD56F92DDAE481004AAB5B /* TSBusinessAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F62DDAE481004AAB5B /* TSBusinessAudioPlayer.swift */; };
@@ -106,6 +109,10 @@
 		3DB4D4A22DDC34020082596A /* ASRTRFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRTRFileView.swift; sourceTree = "<group>"; };
 		3DB4D4A42DDC8E7B0082596A /* APSettingVC+Col.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APSettingVC+Col.swift"; sourceTree = "<group>"; };
 		3DB4D4A72DDC92530082596A /* ASBusinessWebVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASBusinessWebVC.swift; sourceTree = "<group>"; };
+		3DB4D4A92DDDCEA50082596A /* Poppins-BoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-BoldItalic.otf"; sourceTree = "<group>"; };
+		3DB4D4AB2DDDCED00082596A /* UIFont+TSEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+TSEx.swift"; sourceTree = "<group>"; };
+		3DB4D4B02DDF0B880082596A /* Untitled.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Untitled.swift; sourceTree = "<group>"; };
+		3DB4D4B12DDF0B940082596A /* FakeBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeBlurView.swift; sourceTree = "<group>"; };
 		3DCD56F22DDAE3DF004AAB5B /* ASRingToneCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRingToneCellView.swift; sourceTree = "<group>"; };
 		3DCD56F42DDAE421004AAB5B /* ASViewTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASViewTool.swift; sourceTree = "<group>"; };
 		3DCD56F62DDAE481004AAB5B /* TSBusinessAudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBusinessAudioPlayer.swift; sourceTree = "<group>"; };
@@ -230,6 +237,14 @@
 			path = ASBusinessWebVC;
 			sourceTree = "<group>";
 		};
+		3DB4D4AD2DDDCED00082596A /* Ex */ = {
+			isa = PBXGroup;
+			children = (
+				3DB4D4AB2DDDCED00082596A /* UIFont+TSEx.swift */,
+			);
+			path = Ex;
+			sourceTree = "<group>";
+		};
 		3DCD56F82DDAE481004AAB5B /* TSAudioPlayer */ = {
 			isa = PBXGroup;
 			children = (
@@ -304,6 +319,8 @@
 		A800FEAF2DDAC0E9009DABDC /* CommonView */ = {
 			isa = PBXGroup;
 			children = (
+				3DB4D4B02DDF0B880082596A /* Untitled.swift */,
+				3DB4D4B12DDF0B940082596A /* FakeBlurView.swift */,
 				3DCD573A2DDB4E5E004AAB5B /* ASPageNullView.swift */,
 				3DCD572E2DDB1D87004AAB5B /* ASRingLoadingView.swift */,
 				3DCD56F42DDAE421004AAB5B /* ASViewTool.swift */,
@@ -397,6 +414,7 @@
 		A848F88F2DD6D4E800B746EC /* Common */ = {
 			isa = PBXGroup;
 			children = (
+				3DB4D4AD2DDDCED00082596A /* Ex */,
 				3DCD57172DDB1158004AAB5B /* TSBandRingTool */,
 				3DCD57032DDB1118004AAB5B /* TSPurchaseTool */,
 				3DCD57002DDB1008004AAB5B /* CpuMapManager.swift */,
@@ -534,6 +552,7 @@
 			children = (
 				3DCD57362DDB3FFA004AAB5B /* DanceRingtoneExample.mp3 */,
 				3DCD57372DDB3FFA004AAB5B /* GentleRingtoneExample.mp3 */,
+				3DB4D4A92DDDCEA50082596A /* Poppins-BoldItalic.otf */,
 				3DCD57322DDB38E7004AAB5B /* ringAnimation.gif */,
 				3DCD57332DDB38E7004AAB5B /* rotatingAnimation.gif */,
 				A848F8E02DD7271400B746EC /* ring_ttr_style.json */,
@@ -665,6 +684,7 @@
 			files = (
 				3DCD57342DDB38E7004AAB5B /* ringAnimation.gif in Resources */,
 				3DCD57352DDB38E7004AAB5B /* rotatingAnimation.gif in Resources */,
+				3DB4D4AA2DDDCEA50082596A /* Poppins-BoldItalic.otf in Resources */,
 				A848F8822DD6D1AF00B746EC /* Assets.xcassets in Resources */,
 				A848F8D52DD719B600B746EC /* ring_duration.json in Resources */,
 				3DCD57222DDB1158004AAB5B /* tutorial-ring.mp4 in Resources */,
@@ -756,6 +776,7 @@
 				A848F8C02DD6E6FA00B746EC /* APRingTonesVC+TextView.swift in Sources */,
 				3DCD572F2DDB1D8A004AAB5B /* ASRingLoadingView.swift in Sources */,
 				3DB4D49D2DDC29AC0082596A /* ASRTRStyleView.swift in Sources */,
+				3DB4D4AE2DDDCED00082596A /* UIFont+TSEx.swift in Sources */,
 				3DCD57312DDB2A66004AAB5B /* ASGenerateRingToRingOperation.swift in Sources */,
 				A848F8EA2DD74E3A00B746EC /* ASDBActionInfoModel.swift in Sources */,
 				3DCD573D2DDB5A3C004AAB5B /* ASMyRingCell.swift in Sources */,
@@ -781,6 +802,7 @@
 				A848F8F32DD7528D00B746EC /* ASBaseOperation.swift in Sources */,
 				A848F8BB2DD6E30600B746EC /* APRingTonesVM.swift in Sources */,
 				3DB4D49B2DDC28F20082596A /* APAudioToRingVC+Upload.swift in Sources */,
+				3DB4D4B22DDF0B960082596A /* FakeBlurView.swift in Sources */,
 				3DCD56F32DDAE3E3004AAB5B /* ASRingToneCellView.swift in Sources */,
 				3DCD56FF2DDAFC1B004AAB5B /* ASBusinessFileManager.swift in Sources */,
 				A848F8C42DD6E70500B746EC /* APRingTonesVC+Style.swift in Sources */,
@@ -828,6 +850,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = HR2R5NZ2MG;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIPlayRingtones/Info.plist;
 				INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
@@ -843,7 +866,7 @@
 					"$(PROJECT_DIR)/AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3",
 				);
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.tsts..AIPlayRingtones;
+				PRODUCT_BUNDLE_IDENTIFIER = com.musicdownloader.ringtones;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
 				SUPPORTS_MACCATALYST = NO;
@@ -864,6 +887,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = HR2R5NZ2MG;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIPlayRingtones/Info.plist;
 				INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
@@ -879,7 +903,7 @@
 					"$(PROJECT_DIR)/AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3",
 				);
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.tsts..AIPlayRingtones;
+				PRODUCT_BUNDLE_IDENTIFIER = com.musicdownloader.ringtones;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
 				SUPPORTS_MACCATALYST = NO;

+ 78 - 0
AIPlayRingtones.xcodeproj/xcshareddata/xcschemes/AIPlayRingtones.xcscheme

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1630"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "A848F85F2DD6D19100B746EC"
+               BuildableName = "AIPlayRingtones.app"
+               BlueprintName = "AIPlayRingtones"
+               ReferencedContainer = "container:AIPlayRingtones.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A848F85F2DD6D19100B746EC"
+            BuildableName = "AIPlayRingtones.app"
+            BlueprintName = "AIPlayRingtones"
+            ReferencedContainer = "container:AIPlayRingtones.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "A848F85F2DD6D19100B746EC"
+            BuildableName = "AIPlayRingtones.app"
+            BlueprintName = "AIPlayRingtones"
+            ReferencedContainer = "container:AIPlayRingtones.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 31 - 27
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift

@@ -35,17 +35,17 @@ extension APAudioToRingVC {
 extension APAudioToRingVC : UIDocumentPickerDelegate {
 
   @objc func selectAudioFile() {
-      if viewModel.ringFilePath == nil {
-          if let url = Bundle.main.url(forResource: "DanceRingtoneExample", withExtension: "mp3") {
-              viewModel.ringFilePath = url
-              fileView.filePath = url
-          }
-      }else{
-          viewModel.ringFilePath = nil
-          fileView.filePath = nil
-      }
-      
-      return
+//      if viewModel.ringFilePath == nil {
+//          if let url = Bundle.main.url(forResource: "DanceRingtoneExample", withExtension: "mp3") {
+//              viewModel.ringFilePath = url
+//              fileView.filePath = url
+//          }
+//      }else{
+//          viewModel.ringFilePath = nil
+//          fileView.filePath = nil
+//      }
+//      
+//      return
       let documentTypes = ["public.mp3"]
       // 音频 mp3,wav,m4a
       // .MP3; .AAC; .WAV; .WMA; .CDA; .FLAC; .M4A; .MID; .MKA; .MP2; .MPA; .MPC; .APE; .OFR; .OGG; .RA; .WV; .TTA; .AC3; .DTS
@@ -70,23 +70,27 @@ extension APAudioToRingVC : UIDocumentPickerDelegate {
         
         // 3. 处理选中的音频文件
         print("选中的音频文件路径:", selectedFileURL.path)
-        
+        let cacheDirectory = TSFileManagerTool.cacheDirectory.appendingPathComponent(selectedFileURL.lastPathComponent)
+        TSFileManagerTool.copyFileWithOverwrite(from: selectedFileURL, to: cacheDirectory)
+        viewModel.ringFilePath = cacheDirectory
+        fileView.filePath = cacheDirectory
         // 示例:读取文件数据(需处理权限)
-        if selectedFileURL.startAccessingSecurityScopedResource() {
-            defer { selectedFileURL.stopAccessingSecurityScopedResource() }
-            
-            do {
-                dePrint("selectedFileURL=\(selectedFileURL)")
-                let fileData = try Data(contentsOf: selectedFileURL)
-                print("文件大小:", fileData.count, "字节")
-                let cacheDirectory = TSFileManagerTool.cacheDirectory.appendingPathComponent(selectedFileURL.lastPathComponent)
-                TSFileManagerTool.copyFileWithOverwrite(from: selectedFileURL, to: cacheDirectory)
-                
-                viewModel.ringFilePath = cacheDirectory
-            } catch {
-                print("读取文件失败:", error.localizedDescription)
-            }
-        }
+//        if selectedFileURL.startAccessingSecurityScopedResource() {
+//            defer { selectedFileURL.stopAccessingSecurityScopedResource() }
+//            
+//            do {
+//                dePrint("selectedFileURL=\(selectedFileURL)")
+//                let fileData = try Data(contentsOf: selectedFileURL)
+//                print("文件大小:", fileData.count, "字节")
+//                let cacheDirectory = TSFileManagerTool.cacheDirectory.appendingPathComponent(selectedFileURL.lastPathComponent)
+//                TSFileManagerTool.copyFileWithOverwrite(from: selectedFileURL, to: cacheDirectory)
+//                
+//                viewModel.ringFilePath = cacheDirectory
+//                fileView.filePath = cacheDirectory
+//            } catch {
+//                print("读取文件失败:", error.localizedDescription)
+//            }
+//        }
     }
 
     // 用户取消选择时回调

+ 28 - 19
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift

@@ -64,6 +64,22 @@ class APAudioToRingVC: TSBaseVC {
             guard let self = self else { return }
             creatBtnView.setBtnEnabled(isEnabled: enble)
         }.store(in: &cancellable)
+        
+        NotificationCenter.default.addObserver(forName: .kBaseOperationQueueCountChanged, object: nil, queue: .main) { [weak self] notification in
+            guard let self = self else { return }
+            if let userInfo = notification.userInfo as? [String: Any], let _ = userInfo["ASBaseOperationQueue"] as? ASGenerateRingToRingOperationQueue {
+                setCreatBtnEnabled()
+            }
+        }
+        
+        NotificationCenter.default.addObserver(forName: .kGenerateRTROperationChanged, object: nil, queue: .main) { [weak self] notification in
+            guard let self = self else { return }
+            if let userInfo = notification.userInfo as? [String: Any], let state = userInfo["state"] as? ASProgressState {
+                if case let .progress(progress,progressString) = state {
+                    creatBtnView.setLoadingText(text: progressString)
+                }
+            }
+        }
     }
 }
 
@@ -72,29 +88,22 @@ extension APAudioToRingVC {
         view.endEditing(true)
     }
     
+    func setCreatBtnEnabled() {
+        let isAvailability = ASGenerateRingToRingOperationQueue.shared.isAvailability
+        if viewModel.isCanGennerate, isAvailability {
+            creatBtnView.setBtnEnabled(isEnabled: true)
+            creatBtnView.loading = false
+        } else {
+            creatBtnView.setBtnEnabled(isEnabled: false)
+            creatBtnView.loading = !isAvailability
+        }
+
+    }
     
     func generateAI() {
         view.endEditing(true)
-        
-        let gennerateVC = ASRingGeneratorVC(generateStyleModel: viewModel.generateStyleModel) { [weak self] _ in
-            guard let self = self else { return }
-//            updateVipView()
-        }
-
-        gennerateVC.reloadViewBlock = { [weak self] in
-            guard let self = self else { return }
-//            updataCollectionView()
-        }
-        
-        gennerateVC.closePageComplete = {
-            [weak self] in
-            guard let self = self else { return }
-//            updataCollectionView()
-        }
-
+        let gennerateVC = ASRingGeneratorVC(generateStyleModel: viewModel.generateStyleModel)
         kPresentModalVC(target: self, modelVC: gennerateVC, transitionStyle: .crossDissolve)
-
-      
     }
     
 }

+ 3 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift

@@ -83,6 +83,9 @@ class ASRTRFileplayView: TSBaseView {
             make.bottom.equalTo(-20)
         }
         
+        ringToneView.progressView.snp.updateConstraints { make in
+            make.trailing.equalTo(-60)
+        }
         return ringToneView
     }()
     

+ 66 - 10
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift

@@ -52,8 +52,27 @@ class ASMyRingCell: SwipeCollectionViewCell  {
         generateView.refreshHandel = { [weak self]  in
             guard let self = self else { return }
             guard let oldModel = model else { return }
-//            if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones){ return }//判断 vip
-//            TSGenerateRintoneOperationQueue.shared.creatOperation(uuid: oldModel.uuid).creatRintone(oldModel: oldModel, prompt: oldModel.request.prompt, promptSort: oldModel.request.promptSort)
+
+            if oldModel.modelType == .ttr {
+                //            if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones){ return }//判断 vip
+                if ASGenerateTextToRingOperationQueue.shared.isAvailability {
+                    generateView.setProgress(progress: 0)
+                    let gennerateOperation = ASGenerateTextToRingOperationQueue.shared.creatOperation(uuid: oldModel.uuid)
+                    gennerateOperation.isSaveProcessToDB = true
+                    gennerateOperation.creatRing(oldModel: oldModel) { success in }
+//                    dePrint("\(self.indexPath.item),刷新进度发self.operation=\(gennerateOperation)")
+                    modelDidSet()
+                }
+            }else if oldModel.modelType == .rtr {
+                //            if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones){ return }//判断 vip
+                if ASGenerateRingToRingOperationQueue.shared.isAvailability {
+                    generateView.setProgress(progress: 0)
+                    let gennerateOperation = ASGenerateRingToRingOperationQueue.shared.creatOperation(uuid: oldModel.uuid)
+                    gennerateOperation.isSaveProcessToDB = true
+                    gennerateOperation.creatRing(oldModel: oldModel) { success in }
+                    modelDidSet()
+                }
+            }
         }
         return generateView
     }()
@@ -134,25 +153,62 @@ class ASMyRingCell: SwipeCollectionViewCell  {
     func dealThings(){
         
     }
-    
+    var operation:ASGenerateBaseOperation?
 }
 
 
 extension ASMyRingCell {
     
+    var currentOperation:ASGenerateBaseOperation?{
+        guard let model = model else { return nil }
+//        dePrint("\(self.indexPath.item),刷新进度真self.uuid=\(model.uuid)")
+        if model.modelType == .ttr {
+            return ASGenerateTextToRingOperationQueue.shared.findOperation(uuid: model.uuid)
+        }else if model.modelType == .rtr {
+            return ASGenerateRingToRingOperationQueue.shared.findOperation(uuid: model.uuid)
+        }
+        return nil
+    }
     func modelDidSet(){
         guard let model = model else { return }
-        if let rintoneOperation = ASGenerateTextToRingOperationQueue.shared.findOperation(uuid: model.uuid) as? ASGenerateTextToRingOperation {
-            rintoneOperation.currentActionInfoModelChanged = { [weak self] actionInfoModel in
+        
+        if let rintoneOperation = currentOperation {
+//            rintoneOperation.currentActionInfoModelChanged = { [weak self] actionInfoModel in
+//                guard let self = self else { return }
+//                DispatchQueue.main.async {
+//                    self.updataActionInfoModelView(model: actionInfoModel)
+//                }
+//            }
+            
+            rintoneOperation.stateDataPblishedChanged = { [weak self] state, actionInfoModel in
                 guard let self = self else { return }
-                DispatchQueue.main.async {
-                    self.updataActionInfoModelView(model: actionInfoModel)
+                switch state {
+                    case .failed(let errorStr,let code):
+                    generateView.isHidden = false
+                    generateView.setFail()
+                    case .success:
+                    if let model = actionInfoModel {
+                        updataActionInfoModelView(model: model)
+                    }
+                    case .progress(let progress, let string):
+                    generateView.isHidden = false
+                    generateView.setProgress(progress: progress)
+                    default:
+                    generateView.isHidden = false
+                    generateView.setProgress(progress: 0)
                 }
             }
+            
+            self.operation = rintoneOperation
+//            dePrint("\(self.indexPath.item),刷新进度真self.operation=\(self.operation)")
+        }
+        else{
+//            dePrint("\(self.indexPath.item),刷新进度空self.operation=\(self.operation)")
+            self.operation = nil
         }
 
         updataActionInfoModelView(model: model)
-        dePrint("model actionStatus 收到=\(model.actionStatus)")
+        dePrint("\(self.indexPath.item),model actionStatus 收到=\(model.actionStatus)")
         
         if playSelf{
             setPlayerStateChangedHandle()
@@ -206,11 +262,11 @@ extension ASMyRingCell {
         if model.modelType == .example {
             model.actionStatus = .success
         }
-        
+
         switch model.actionStatus {
         case .pending,.running:
             generateView.isHidden = false
-            generateView.setProgress(progress: model.percent)
+            generateView.setProgress(progress: model.percent*kPercentScale)
         case .success:
             generateView.isHidden = true
             

+ 33 - 10
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift

@@ -18,6 +18,25 @@ class APMyRingVC: TSBaseVC {
         titleImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()
         }
+        
+//        let vipBtn = UIButton.createButton(image: .aiRintoneIcon) { [weak self] in
+//            guard let self = self else { return }
+//      
+//            if let model = dbHistory.listModels.first,model.modelType != 1 {
+//                ASRMShared.writeThread {
+//                    model.status = "failed"
+//                }
+//            }
+//
+//            updateListView()
+//        }
+//        navBarView.barView.addSubview(vipBtn)
+//        vipBtn.snp.makeConstraints { make in
+//            make.centerY.equalToSuperview()
+//            make.trailing.equalTo(-16) // (-60)
+//            make.width.height.equalTo(24)
+//        }
+
         return navBarView
     }()
     
@@ -69,29 +88,33 @@ class APMyRingVC: TSBaseVC {
     
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
+        debugPrint("viewWillAppear listModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
     }
     
     override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
         TSBusinessAudioPlayer.shared.stop()
     }
-    
+
     override func dealThings() {
         updateListView()
         
-        NotificationCenter.default.addObserver(forName: .kGenerateRingOperationChanged, object: nil, queue: nil) {[weak self] notification in
-            guard let self = self else { return }
-            if let userInfo = notification.userInfo as? [String: Any],let state = userInfo["state"] as? ASProgressState {
-                switch state {
-                case .start, .success(_),.failed(_),.none:
-                    self.updateListView()
-                default:break
-                }
+        NotificationCenter.default.addObserver(self, selector: #selector(operationChanged(_:)), name: .kGenerateRingOperationChanged, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(operationChanged(_:)), name: .kGenerateRTROperationChanged, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(operationChanged(_:)), name: .kGenerateTTROperationChanged, object: nil)
+        NotificationCenter.default.addObserver(self, selector: #selector(updateListView), name: .kRingDataChanged, object: nil)
+    }
+    
+    
+    @objc func operationChanged(_ notification: Notification) {
+        if let userInfo = notification.userInfo as? [String: Any],let state = userInfo["state"] as? ASProgressState {
+            if state.reloadNewData {
+                self.updateListView()
             }
         }
     }
     
-    func updateListView(){
+    @objc func updateListView(){
         dbHistory.getModelList { [weak self] array in
             guard let self = self else { return }
             listModelArray = array

+ 29 - 19
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC.swift

@@ -53,6 +53,22 @@ class APRingTonesVC: TSBaseVC {
             guard let self = self else { return }
             creatBtnView.setBtnEnabled(isEnabled: enble)
         }.store(in: &cancellable)
+        
+        NotificationCenter.default.addObserver(forName: .kBaseOperationQueueCountChanged, object: nil, queue: .main) { [weak self] notification in
+            guard let self = self else { return }
+            if let userInfo = notification.userInfo as? [String: Any], let _ = userInfo["ASBaseOperationQueue"] as? ASGenerateTextToRingOperationQueue {
+                setCreatBtnEnabled()
+            }
+        }
+    
+        NotificationCenter.default.addObserver(forName: .kGenerateTTROperationChanged, object: nil, queue: .main) { [weak self] notification in
+            guard let self = self else { return }
+            if let userInfo = notification.userInfo as? [String: Any], let state = userInfo["state"] as? ASProgressState {
+                if case let .progress(_,progressString) = state {
+                    creatBtnView.setLoadingText(text: progressString)
+                }
+            }
+        }
     }
 }
 
@@ -62,29 +78,23 @@ extension APRingTonesVC {
         view.endEditing(true)
     }
     
+    func setCreatBtnEnabled() {
+        let isAvailability = ASGenerateTextToRingOperationQueue.shared.isAvailability
+        if viewModel.isCanGennerate, isAvailability {
+            creatBtnView.setBtnEnabled(isEnabled: true)
+            creatBtnView.loading = false
+        } else {
+            creatBtnView.setBtnEnabled(isEnabled: false)
+            creatBtnView.loading = !isAvailability
+        }
+
+    }
+    
     
     func generateAI() {
         view.endEditing(true)
-        
-        let gennerateVC = ASRingGeneratorVC(generateStyleModel: viewModel.generateStyleModel) { [weak self] _ in
-            guard let self = self else { return }
-//            updateVipView()
-        }
-
-        gennerateVC.reloadViewBlock = { [weak self] in
-            guard let self = self else { return }
-//            updataCollectionView()
-        }
-        
-        gennerateVC.closePageComplete = {
-            [weak self] in
-            guard let self = self else { return }
-//            updataCollectionView()
-        }
-
+        let gennerateVC = ASRingGeneratorVC(generateStyleModel: viewModel.generateStyleModel)
         kPresentModalVC(target: self, modelVC: gennerateVC, transitionStyle: .crossDissolve)
-
-      
     }
     
 }

+ 2 - 2
AIPlayRingtones/AppPage/APSettingVC/APSettingVC.swift

@@ -29,7 +29,7 @@ class APSettingVC: TSBaseVC {
     lazy var collectionView = creatCollectionView()
     
     
-    let appid = "6740220736"
+    let appid = "6746234900"
     lazy var dataArray: [TSBasicSectionModel] = {
         var dataArray = [TSBasicSectionModel]()
         let sectionModel = TSBasicSectionModel()
@@ -128,7 +128,7 @@ class APSettingVC: TSBaseVC {
         sectionModel.addSubItemModel(
             createItemModel(
                 leftTitle: "About us".localized,
-                rightIsHave: true,
+                rightIsHave: false,
                 tapBlock: { [weak self] model, _, _ in
                    guard let self = self else { return }
       

+ 42 - 44
AIPlayRingtones/AppPage/ASCommonView/ASBtnView/ASAppBtnView.swift

@@ -22,17 +22,15 @@ class ASAppBtnView: TSBaseView {
     var isIconVipBlock:(()->Bool)? //vip 图片显示
     var isClickVipBlock:(()->Bool)?  //点击是,是否需要弹出 vip
     
-//    var loading:Bool = false{
-//        willSet {
-//            if loading != newValue {
-//                loadingAnimation(loading: newValue)
-//                
-//                if loading == false {
-//                    self.resetBtnText()
-//                }
-//            }
-//        }
-//    }
+    var loading:Bool = false{
+        didSet{
+            loadingAnimation(loading: loading)
+            
+            if loading == false {
+                self.resetBtnText()
+            }
+        }
+    }
     
     //###################################### Button ######################################
     var button:UIButton = UIButton()
@@ -55,7 +53,7 @@ class ASAppBtnView: TSBaseView {
         
         switch style {
         case .generate:
-            title = "Generate".localized
+            title = "Generate Now".localized
             setUpGenerate()
             launchVipLogic()
         }
@@ -63,13 +61,13 @@ class ASAppBtnView: TSBaseView {
     }
     
     
-//    func setLoadingText(text:String?){
-//        if loading {
-//            button.setTitle(text, for: .normal)
-//        }else{
-//            resetBtnText()
-//        }
-//    }
+    func setLoadingText(text:String?){
+        if loading {
+            button.setTitle(text, for: .normal)
+        }else{
+            resetBtnText()
+        }
+    }
     
     func resetBtnText(){
         button.setTitle(title, for:.normal)
@@ -98,10 +96,10 @@ extension ASAppBtnView{
     }
 
     func updateVipView() {
-//        switch style {
-//        case .generate:
-//            setVip(vip: isIconVipBlock?() ?? false)
-//        }
+        switch style {
+        case .generate:
+            setVip(vip: isIconVipBlock?() ?? false)
+        }
     }
     
     func setBtnEnabled(isEnabled:Bool) {
@@ -113,18 +111,18 @@ extension ASAppBtnView{
         return button.isEnabled
     }
     
-//    func setVip(vip:Bool) {
-//        
-//        if loading { //loading,正在显示转圈动画
-//            return
-//        }
-//        
-//        if vip {
-//            button.setImage(UIImage(named: "btnImage_vip"), for: .normal)
-//        }else{
-//            button.setImage(nil, for: .normal)
-//        }
-//    }
+    func setVip(vip:Bool) {
+        
+        if loading { //loading,正在显示转圈动画
+            return
+        }
+        
+        if vip {
+            button.setImage(UIImage(named: "btnImage_vip"), for: .normal)
+        }else{
+            button.setImage(nil, for: .normal)
+        }
+    }
     
 }
 //创造按钮
@@ -161,15 +159,15 @@ extension ASAppBtnView{
 //创造按钮
 extension ASAppBtnView{
     
-//    private func loadingAnimation(loading:Bool) {
-//        if loading {
-//            button.setImage(UIImage(named: "generated_loading"), for: .normal)
-//            self.button.imageView?.startRotating()
-//        }else {
-//            button.imageView?.stopRotating()
-//            updateVipView()
-//        }
-//    }
+    private func loadingAnimation(loading:Bool) {
+        if loading {
+            button.setImage(UIImage(named: "generated_loading"), for: .normal)
+            self.button.imageView?.startRotating()
+        }else {
+            button.imageView?.stopRotating()
+            updateVipView()
+        }
+    }
     
 }
 //常用提交按钮

+ 332 - 231
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorBaseVC.swift

@@ -5,295 +5,396 @@
 //  Created by 100Years on 2025/5/18.
 //
 
-
 class ASRingGeneratorBaseVC: TSBaseVC {
     
-    lazy var topBgView: UIView = {
-        let topBgView = UIView(frame: CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight))
-        topBgView.backgroundColor = .black.withAlphaComponent(0.5)
-        topBgView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
-        return topBgView
-    }()
-    
-    var bottomViewH:CGFloat = 340{
+
+    var bottomViewH:CGFloat = 304{
         didSet{
             bottomView.frame = CGRectMake(0, k_ScreenHeight-bottomViewH, k_ScreenWidth, bottomViewH)
         }
     }
     
-    lazy var bgImageView: UIImageView = {
-        let bgImageView = UIImageView()
-        bgImageView.image = UIImage(named: "bottom_alert_bg")?.resizableImage(capInsets:UIEdgeInsets(top:40, left: 30, bottom: 30, right: 170))
-        bgImageView.contentMode = .scaleToFill
-        return bgImageView
-    }()
-    
     lazy var bottomView: UIView = {
         let bottomView = UIView(frame: CGRectMake(0, k_ScreenHeight-bottomViewH, k_ScreenWidth, bottomViewH))
-        bottomView.addSubview(bgImageView)
-        bgImageView.snp.makeConstraints { make in
-            make.bottom.top.leading.right.equalTo(0)
-        }
+        bottomView.backgroundColor = .mainBg
         return bottomView
     }()
-    
 
-    lazy var xBtn: UIButton = {
-        let xBtn = TSUIExpandedTouchButton()
-        xBtn.setUpButton(image: UIImage(named: "x")) { [weak self]  in
-//        let xBtn = UIButton.createButton(image: UIImage(named: "x")) { [weak self]  in
+    lazy var titleLabel: UILabel = {
+        let titleLabel = UILabel.createLabel(text: "Successfully Generated".localized,font: .font(name: .PoppinsBoldItalic,size: 18.0),textColor: .white,textAlignment: .left)
+        return titleLabel
+    }()
+    
+    lazy var closePageBtn: UIButton = {
+        let xBtn = UIButton.createButton(image: .pageX) { [weak self]  in
             guard let self = self else { return }
-            clickXBtn()
+            closePage()
         }
         return xBtn
     }()
     
-    lazy var againBtn: UIButton = {
-        let againBtn = UIButton.createButton(title:"Try Again".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
-        { [weak self]  in
+    lazy var xBtn: UIButton = {
+        let xBtn = TSUIExpandedTouchButton()
+        xBtn.setUpButton(image: UIImage(named: "x")) { [weak self]  in
             guard let self = self else { return }
-            clickAgainBtn()
+            clickXBtn()
         }
-        return againBtn
+        return xBtn
     }()
     
+
     lazy var saveBtn: UIButton = {
-        let saveBtn = UIButton.createButton(title:"Save".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+        let saveBtn = UIButton.createButton(title:"Save".localized,backgroundImage:.setAsBg,font: UIFont.font(size: 14,weight: .medium),titleColor:.white)
         { [weak self]  in
             guard let self = self else { return }
             clickSubmitBtn()
         }
-        kDelayMainShort {
-            saveBtn.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
-        }
         return saveBtn
     }()
-    
-    
-    lazy var leftBtn: UIButton = {
-        let leftBtn = UIButton.createButton(title:"Copy".localized,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
-        { [weak self]  in
-            guard let self = self else { return }
-            clickLeftBtn()
-        }
-        leftBtn.isHidden = true
-        return leftBtn
-    }()
-    
-    lazy var rightBtn: UIButton = {
-        
-        let rightBtn = UIButton.createButton(title:"Save".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
-        { [weak self]  in
-            guard let self = self else { return }
-            clickRightBtn()
-        }
-        
-        kDelayMainShort {
-            rightBtn.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
-        }
-        rightBtn.isHidden = true
-        return rightBtn
-    }()
-    
-
-    lazy var regenerateBtn: UIButton = {
-        let regenerateBtn = UIButton.createButton(
-            title: "regenerate",
-            image: UIImage(named: "refresh_gary"),
-            backgroundColor:.white.withAlphaComponent(0.1),
-            font: .font(size: 12),
-            titleColor: .white.withAlphaComponent(0.6),
-            corner: 8.0)
-        { [weak self]  in
-            guard let self = self else { return }
-            clickAgainBtn()
-        }
-        regenerateBtn.contentEdgeInsets = UIEdgeInsets(top: 4, left: 7, bottom: 4, right: 7)
-        regenerateBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0)
-        regenerateBtn.isHidden = true
-        return regenerateBtn
-    }()
-    
-    //############################## 失败 View ##############################
-    
-    lazy var failLabel: UILabel = {
-        let failLabel = UILabel.createLabel(text: "Generation Failed".localized,font: .font(size: 14.0),textColor: .white.withAlphaComponent(0.6),textAlignment: .center)
-        return failLabel
-    }()
-    
-    lazy var failView: UIView = {
-        let failView = UIView()
-        let failImageView = UIImageView.createImageView(imageName: "generation_failed")
-    
-        failView.addSubview(failImageView)
-        failImageView.snp.makeConstraints { make in
-            make.top.equalTo(0)
-            make.centerX.equalToSuperview()
-            make.width.equalTo(88)
-            make.height.equalTo(88)
-        }
-        
-        failView.addSubview(failLabel)
-        failLabel.snp.makeConstraints { make in
-            make.top.equalTo(failImageView.snp.bottom).offset(16)
-            make.leading.equalTo(10)
-            make.trailing.equalTo(-10)
-            make.width.greaterThanOrEqualTo(88)
-            make.height.equalTo(14)
-            make.bottom.equalTo(0)
-        }
-        failView.isHidden = true
-        return failView
-    }()
-    
-    //############################## 结果 View ##############################
-    lazy var resultIconImageView: UIImageView = {
-        let resultIconImageView = UIImageView.createImageView(imageName: "")
-        return resultIconImageView
-    }()
-    
-    lazy var successTopView: UIView = {
-        let resultView = UIView()
-
-        resultView.addSubview(resultIconImageView)
-        resultIconImageView.snp.makeConstraints { make in
-            make.top.equalTo(-15)
-            make.trailing.equalTo(-28)
-            make.width.equalTo(88)
-            make.height.equalTo(88)
-        }
-        
-        let successLabel = UILabel.createLabel(text: "Successfully Generated".localized,font: .font(size: 18.0),textColor: .themeColor,textAlignment: .left)
-        resultView.addSubview(successLabel)
-        successLabel.snp.makeConstraints { make in
-            make.top.equalTo(30)
-            make.leading.equalTo(20)
-            make.trailing.equalTo(resultIconImageView.snp.leading).offset(-20)
-            make.height.equalTo(18)
-        }
-        kDelayMainShort {
-            successLabel.applyGradient(colors: [UIColor.white,"#D999FF".uiColor])
-        }
-        resultView.isHidden = true
-        return resultView
-    }()
-    
-    //############################## 自定义 View ##############################
-    lazy var diyView: UIView = {
-        let diyView = UIView()
- 
-        diyView.addSubview(failView)
-        failView.snp.makeConstraints { make in
-            make.centerY.equalToSuperview().offset(-40)
-            make.centerX.equalToSuperview()
-        }
-        
-        diyView.addSubview(successTopView)
-        successTopView.snp.makeConstraints { make in
-            make.leading.top.trailing.equalTo(0)
-            make.height.equalTo(73)
-        }
-        
 
-        return diyView
-    }()
-    
     //点击空白,关闭页面
-    var isClickTheBlankClosePage = true
-    
     override func createView() {
-        view.backgroundColor = .clear
+
+        view.backgroundColor = TSColorConfigShared.mainBg.withAlphaComponent(0.6)
         setNavBarViewHidden(true)
 
-        contentView.addSubview(topBgView)
         contentView.addSubview(bottomView)
     
         let safeBottom = k_Height_safeAreaInsetsBottom()
-        //重试
-        bottomView.addSubview(againBtn)
-        againBtn.snp.makeConstraints { make in
-            make.bottom.equalTo(-16-safeBottom)
-            make.centerX.equalToSuperview()
-            make.width.equalTo(228)
-            make.height.equalTo(48)
-        }
-        
+
         //保存
         bottomView.addSubview(saveBtn)
         saveBtn.snp.makeConstraints { make in
-            make.bottom.equalTo(-16-safeBottom)
+            make.bottom.equalTo(-44-safeBottom)
             make.centerX.equalToSuperview()
-            make.width.equalTo(228)
-            make.height.equalTo(48)
-        }
-        
-        
-        //中心点
-        let centerView = UIView()
-        bottomView.addSubview(centerView)
-        centerView.snp.makeConstraints { make in
-            make.center.equalToSuperview()
-        }
-        bottomView.addSubview(leftBtn)
-        leftBtn.snp.makeConstraints { make in
-            make.bottom.equalTo(-16-safeBottom)
-            make.trailing.equalTo(centerView.snp.leading).offset(-8)
-            make.width.equalTo(163)
+            make.width.equalTo(290)
             make.height.equalTo(48)
         }
-        
-        bottomView.addSubview(rightBtn)
-        rightBtn.snp.makeConstraints { make in
-            make.bottom.equalTo(-16-safeBottom)
-            make.leading.equalTo(centerView.snp.trailing).offset(8)
-            make.width.equalTo(163)
-            make.height.equalTo(48)
-        }
-        
-        bottomView.addSubview(diyView)
-        diyView.snp.makeConstraints { make in
-            make.bottom.equalTo(saveBtn.snp.top).offset(-10)
-            make.top.left.right.equalTo(0)
+
+        bottomView.addSubview(titleLabel)
+        titleLabel.snp.makeConstraints { make in
+            make.top.equalTo(24)
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-30)
         }
         
         bottomView.addSubview(xBtn)
         xBtn.snp.makeConstraints { make in
-            make.top.equalTo(0)
+            make.top.equalTo(8)
             make.trailing.equalTo(-6)
-            make.width.equalTo(24)
-            make.height.equalTo(24)
+            make.width.equalTo(20)
+            make.height.equalTo(20)
+        }
+    
+        contentView.addSubview(closePageBtn)
+        closePageBtn.snp.makeConstraints { make in
+            make.top.equalTo(4.0+k_Height_StatusBar)
+            make.leading.equalTo(16.0)
+            make.width.height.equalTo(36)
         }
-        
-
     }
     
     func closePage() {
         self.dismiss(animated: true, completion: nil)
     }
 
-    @objc func clickAgainBtn(){
-        
-    }
-    
     @objc func clickSubmitBtn(){
         
     }
-    
-    @objc func clickLeftBtn(){
-        
-    }
-    
-    @objc func clickRightBtn(){
-        
-    }
-    
+
     @objc func clickXBtn(){
         closePage()
     }
-    
-    @objc private func dismissKeyboard() {
-        if isClickTheBlankClosePage {
-            closePage()
-        }
-    }
 }
+
+//class ASRingGeneratorBaseVC: TSBaseVC {
+//    
+//    lazy var topBgView: UIView = {
+//        let topBgView = UIView(frame: CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight))
+//        topBgView.backgroundColor = .black.withAlphaComponent(0.5)
+//        topBgView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
+//        return topBgView
+//    }()
+//    
+//    var bottomViewH:CGFloat = 340{
+//        didSet{
+//            bottomView.frame = CGRectMake(0, k_ScreenHeight-bottomViewH, k_ScreenWidth, bottomViewH)
+//        }
+//    }
+//    
+//    lazy var bgImageView: UIImageView = {
+//        let bgImageView = UIImageView()
+//        bgImageView.image = UIImage(named: "bottom_alert_bg")?.resizableImage(capInsets:UIEdgeInsets(top:40, left: 30, bottom: 30, right: 170))
+//        bgImageView.contentMode = .scaleToFill
+//        return bgImageView
+//    }()
+//    
+//    lazy var bottomView: UIView = {
+//        let bottomView = UIView(frame: CGRectMake(0, k_ScreenHeight-bottomViewH, k_ScreenWidth, bottomViewH))
+//        bottomView.addSubview(bgImageView)
+//        bgImageView.snp.makeConstraints { make in
+//            make.bottom.top.leading.right.equalTo(0)
+//        }
+//        return bottomView
+//    }()
+//    
+//
+//    lazy var xBtn: UIButton = {
+//        let xBtn = TSUIExpandedTouchButton()
+//        xBtn.setUpButton(image: UIImage(named: "x")) { [weak self]  in
+////        let xBtn = UIButton.createButton(image: UIImage(named: "x")) { [weak self]  in
+//            guard let self = self else { return }
+//            clickXBtn()
+//        }
+//        return xBtn
+//    }()
+//    
+//    lazy var againBtn: UIButton = {
+//        let againBtn = UIButton.createButton(title:"Try Again".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+//        { [weak self]  in
+//            guard let self = self else { return }
+//            clickAgainBtn()
+//        }
+//        return againBtn
+//    }()
+//    
+//    lazy var saveBtn: UIButton = {
+//        let saveBtn = UIButton.createButton(title:"Save".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+//        { [weak self]  in
+//            guard let self = self else { return }
+//            clickSubmitBtn()
+//        }
+//        kDelayMainShort {
+//            saveBtn.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
+//        }
+//        return saveBtn
+//    }()
+//    
+//    
+//    lazy var leftBtn: UIButton = {
+//        let leftBtn = UIButton.createButton(title:"Copy".localized,backgroundColor: .fromHex("#FFFFFF", alpha: 0.4),font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+//        { [weak self]  in
+//            guard let self = self else { return }
+//            clickLeftBtn()
+//        }
+//        leftBtn.isHidden = true
+//        return leftBtn
+//    }()
+//    
+//    lazy var rightBtn: UIButton = {
+//        
+//        let rightBtn = UIButton.createButton(title:"Save".localized,backgroundColor:.themeColor,font: UIFont.font(size: 14,weight: .medium),titleColor:.white,corner: 24)
+//        { [weak self]  in
+//            guard let self = self else { return }
+//            clickRightBtn()
+//        }
+//        
+//        kDelayMainShort {
+//            rightBtn.addGradientBg(colors: ["#E961F6".uiColor.cgColor,"#7E57F4".uiColor.cgColor])
+//        }
+//        rightBtn.isHidden = true
+//        return rightBtn
+//    }()
+//    
+//
+//    lazy var regenerateBtn: UIButton = {
+//        let regenerateBtn = UIButton.createButton(
+//            title: "regenerate",
+//            image: UIImage(named: "refresh_gary"),
+//            backgroundColor:.white.withAlphaComponent(0.1),
+//            font: .font(size: 12),
+//            titleColor: .white.withAlphaComponent(0.6),
+//            corner: 8.0)
+//        { [weak self]  in
+//            guard let self = self else { return }
+//            clickAgainBtn()
+//        }
+//        regenerateBtn.contentEdgeInsets = UIEdgeInsets(top: 4, left: 7, bottom: 4, right: 7)
+//        regenerateBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -4, bottom: 0, right: 0)
+//        regenerateBtn.isHidden = true
+//        return regenerateBtn
+//    }()
+//    
+//    //############################## 失败 View ##############################
+//    
+//    lazy var failLabel: UILabel = {
+//        let failLabel = UILabel.createLabel(text: "Generation Failed".localized,font: .font(size: 14.0),textColor: .white.withAlphaComponent(0.6),textAlignment: .center)
+//        return failLabel
+//    }()
+//    
+//    lazy var failView: UIView = {
+//        let failView = UIView()
+//        let failImageView = UIImageView.createImageView(imageName: "generation_failed")
+//    
+//        failView.addSubview(failImageView)
+//        failImageView.snp.makeConstraints { make in
+//            make.top.equalTo(0)
+//            make.centerX.equalToSuperview()
+//            make.width.equalTo(88)
+//            make.height.equalTo(88)
+//        }
+//        
+//        failView.addSubview(failLabel)
+//        failLabel.snp.makeConstraints { make in
+//            make.top.equalTo(failImageView.snp.bottom).offset(16)
+//            make.leading.equalTo(10)
+//            make.trailing.equalTo(-10)
+//            make.width.greaterThanOrEqualTo(88)
+//            make.height.equalTo(14)
+//            make.bottom.equalTo(0)
+//        }
+//        failView.isHidden = true
+//        return failView
+//    }()
+//    
+//    //############################## 结果 View ##############################
+//    lazy var resultIconImageView: UIImageView = {
+//        let resultIconImageView = UIImageView.createImageView(imageName: "")
+//        return resultIconImageView
+//    }()
+//    
+//    lazy var successTopView: UIView = {
+//        let resultView = UIView()
+//
+//        resultView.addSubview(resultIconImageView)
+//        resultIconImageView.snp.makeConstraints { make in
+//            make.top.equalTo(-15)
+//            make.trailing.equalTo(-28)
+//            make.width.equalTo(88)
+//            make.height.equalTo(88)
+//        }
+//        
+//        let successLabel = UILabel.createLabel(text: "Successfully Generated".localized,font: .font(size: 18.0),textColor: .themeColor,textAlignment: .left)
+//        resultView.addSubview(successLabel)
+//        successLabel.snp.makeConstraints { make in
+//            make.top.equalTo(30)
+//            make.leading.equalTo(20)
+//            make.trailing.equalTo(resultIconImageView.snp.leading).offset(-20)
+//            make.height.equalTo(18)
+//        }
+//        kDelayMainShort {
+//            successLabel.applyGradient(colors: [UIColor.white,"#D999FF".uiColor])
+//        }
+//        resultView.isHidden = true
+//        return resultView
+//    }()
+//    
+//    //############################## 自定义 View ##############################
+//    lazy var diyView: UIView = {
+//        let diyView = UIView()
+// 
+//        diyView.addSubview(failView)
+//        failView.snp.makeConstraints { make in
+//            make.centerY.equalToSuperview().offset(-40)
+//            make.centerX.equalToSuperview()
+//        }
+//        
+//        diyView.addSubview(successTopView)
+//        successTopView.snp.makeConstraints { make in
+//            make.leading.top.trailing.equalTo(0)
+//            make.height.equalTo(73)
+//        }
+//        
+//
+//        return diyView
+//    }()
+//    
+//    //点击空白,关闭页面
+//    var isClickTheBlankClosePage = true
+//    
+//    override func createView() {
+//        view.backgroundColor = .clear
+//        setNavBarViewHidden(true)
+//
+//        contentView.addSubview(topBgView)
+//        contentView.addSubview(bottomView)
+//    
+//        let safeBottom = k_Height_safeAreaInsetsBottom()
+//        //重试
+//        bottomView.addSubview(againBtn)
+//        againBtn.snp.makeConstraints { make in
+//            make.bottom.equalTo(-16-safeBottom)
+//            make.centerX.equalToSuperview()
+//            make.width.equalTo(228)
+//            make.height.equalTo(48)
+//        }
+//        
+//        //保存
+//        bottomView.addSubview(saveBtn)
+//        saveBtn.snp.makeConstraints { make in
+//            make.bottom.equalTo(-16-safeBottom)
+//            make.centerX.equalToSuperview()
+//            make.width.equalTo(228)
+//            make.height.equalTo(48)
+//        }
+//        
+//        
+//        //中心点
+//        let centerView = UIView()
+//        bottomView.addSubview(centerView)
+//        centerView.snp.makeConstraints { make in
+//            make.center.equalToSuperview()
+//        }
+//        bottomView.addSubview(leftBtn)
+//        leftBtn.snp.makeConstraints { make in
+//            make.bottom.equalTo(-16-safeBottom)
+//            make.trailing.equalTo(centerView.snp.leading).offset(-8)
+//            make.width.equalTo(163)
+//            make.height.equalTo(48)
+//        }
+//        
+//        bottomView.addSubview(rightBtn)
+//        rightBtn.snp.makeConstraints { make in
+//            make.bottom.equalTo(-16-safeBottom)
+//            make.leading.equalTo(centerView.snp.trailing).offset(8)
+//            make.width.equalTo(163)
+//            make.height.equalTo(48)
+//        }
+//        
+//        bottomView.addSubview(diyView)
+//        diyView.snp.makeConstraints { make in
+//            make.bottom.equalTo(saveBtn.snp.top).offset(-10)
+//            make.top.left.right.equalTo(0)
+//        }
+//        
+//        bottomView.addSubview(xBtn)
+//        xBtn.snp.makeConstraints { make in
+//            make.top.equalTo(0)
+//            make.trailing.equalTo(-6)
+//            make.width.equalTo(24)
+//            make.height.equalTo(24)
+//        }
+//        
+//
+//    }
+//    
+//    func closePage() {
+//        self.dismiss(animated: true, completion: nil)
+//    }
+//
+//    @objc func clickAgainBtn(){
+//        
+//    }
+//    
+//    @objc func clickSubmitBtn(){
+//        
+//    }
+//    
+//    @objc func clickLeftBtn(){
+//        
+//    }
+//    
+//    @objc func clickRightBtn(){
+//        
+//    }
+//    
+//    @objc func clickXBtn(){
+//        closePage()
+//    }
+//    
+//    @objc private func dismissKeyboard() {
+//        if isClickTheBlankClosePage {
+//            closePage()
+//        }
+//    }
+//}

+ 4 - 36
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC+load.swift

@@ -50,62 +50,30 @@ extension ASRingGeneratorVC {
                     showError(text: "")
                 }
             case .progress(let progress, let string):
-                showProgress(text: string)
+            showProgress(progress:progress,text: string)
             default:
                 showLoading()
         }
     }
     
-    func showProgress(text:String) {
-        generateInView.updateShowProgress(text: text)
-        
+    func showProgress(progress:Float, text:String) {
+        generateInView.updateShowProgress(progress: progress,text: text)
         bottomView.isHidden = true
-        isClickTheBlankClosePage = false
     }
     
     func showLoading(){
-        generateInView.updateShowLoading(text: "Generating".localized + " ...")
-        
+        generateInView.updateShowLoading(progress: 0.0,text: "Generating".localized + " ...")
         bottomView.isHidden = true
-        isClickTheBlankClosePage = false
-        
-        xBtn.isHidden = true
     }
     
     func showError(text:String,code:Int = 0){
         generateInView.updateShowError(text: text,code: code)
-    
         bottomView.isHidden = true
-        isClickTheBlankClosePage = false
-        xBtn.isHidden = false
-//        againBtn.isHidden = false//重试
-//        failView.isHidden = false
-////        failLabel.text = msg
-//        saveBtn.isHidden = true
-//        successTopView.isHidden = true
-//
-//        ringView.isHidden = true
-//        regenerateBtn.isHidden = true
-//
-//        isClickTheBlankClosePage = true
     }
     
     func showSuccess(model:ASActionInfoModel){
         generateInView.updateShowSuccess()
-        
         bottomView.isHidden = false
-        
-        xBtn.isHidden = false
-        againBtn.isHidden = true//重试
-        failView.isHidden = true
-        saveBtn.isHidden = false
-        successTopView.isHidden = false
-
         infoModel = model
-        isClickTheBlankClosePage = true
-        
-        ringView.isHidden = false
-        regenerateBtn.isHidden = false
-        
     }
 }

+ 14 - 28
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC.swift

@@ -7,13 +7,13 @@
 
 class ASRingGeneratorVC: ASRingGeneratorBaseVC {
     var infoModel:ASActionInfoModel?
-    var complete:((ASActionInfoModel)->Void)
+    var complete:((ASActionInfoModel)->Void)?
     var reloadViewBlock:(()->Void)?
     var progressState = ASProgressState.none
 
 
     var generateStyleModel:ASGenerateStyleModel
-    init(generateStyleModel:ASGenerateStyleModel,infoModel:ASActionInfoModel? = nil,complete:@escaping ((ASActionInfoModel)->Void)) {
+    init(generateStyleModel:ASGenerateStyleModel,infoModel:ASActionInfoModel? = nil,complete: ((ASActionInfoModel)->Void)? = nil) {
         self.generateStyleModel = generateStyleModel
         self.infoModel = infoModel
         self.complete = complete
@@ -38,7 +38,7 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
         return ringToneView
     }()
     
-    var operation:ASBaseOperation?
+    var operation:ASGenerateBaseOperation?
     override func createView() {
         super.createView()
         
@@ -47,31 +47,17 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
             make.top.bottom.leading.trailing.equalTo(0)
         }
 
-        diyView.addSubview(ringView)
+        bottomView.addSubview(ringView)
         ringView.snp.makeConstraints { make in
-            make.top.equalTo(98)
+            make.top.equalTo(82)
             make.centerX.equalToSuperview()
-            make.width.equalTo(k_ScreenWidth - 40)
+            make.width.equalTo(k_ScreenWidth - 32)
             make.height.equalTo(72)
         }
-        
-        diyView.addSubview(regenerateBtn)
-        regenerateBtn.snp.makeConstraints { make in
-            make.top.equalTo(ringView.snp.bottom).offset(16)
-            make.centerX.equalToSuperview()
-        }
-        saveBtn.setTitle("Set As Ringtone".localized, for: .normal)
-        resultIconImageView.image = resultIcon
-        bottomViewH = 340.0
-        bgImageView.addShadow(shadowColor: "#E6E229".uiColor.cgColor, shadowOffset: .zero, shadowRadius: 20, shadowOpacity: 0.8)
-        
-        diyView.addSubview(failView)
-        failView.snp.updateConstraints { make in
-            make.centerY.equalToSuperview().offset(0)
-        }
     }
     
     @objc func clickBackstageBtn() {
+        self.operation?.isSaveProcessToDB = true
         NotificationCenter.default.post(name: .kRingDataChanged, object: nil)
         self.dismiss(animated: true, completion: nil)
     }
@@ -108,12 +94,7 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
         }
     }
     
-    override func clickAgainBtn() {
-        audioPlayer.stop()
-//        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones, vc: self){ return }//判断 vip
-        creatRintone()
-    }
-    
+
     @objc override func clickSubmitBtn(){
         
         guard let model = infoModel else {
@@ -203,12 +184,14 @@ extension ASRingGeneratorVC{
     
     func generatorNewTTR() {
         let operation:ASGenerateTextToRingOperation = ASGenerateTextToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        self.operation = operation
         let oldModel = operation.createActionInfoModel(generateStyleModel: generateStyleModel)
         generatorTTRCreatRing(oldModel: oldModel)
     }
     
     func generatorTTRCreatRing(oldModel:ASActionInfoModel) {
         let operation:ASGenerateTextToRingOperation = ASGenerateTextToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        self.operation = operation
         operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
             guard let self = self else { return }
             self.upDateView(state: state, model: model)
@@ -227,6 +210,7 @@ extension ASRingGeneratorVC{
 extension ASRingGeneratorVC{
     func generatorNewRTR() {
         let operation:ASGenerateRingToRingOperation = ASGenerateRingToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        self.operation = operation
         operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
             guard let self = self else { return }
             self.upDateView(state: state, model: model)
@@ -237,10 +221,12 @@ extension ASRingGeneratorVC{
             guard let oldModel = actionInfoModel else {return}
             generatorRTRCreatRing(oldModel: oldModel)
         }
+
     }
     
     func generatorRTRCreatRing(oldModel:ASActionInfoModel) {
         let operation:ASGenerateRingToRingOperation = ASGenerateRingToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        self.operation = operation
         operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
             guard let self = self else { return }
             self.upDateView(state: state, model: model)
@@ -266,7 +252,7 @@ extension ASRingGeneratorVC{
     func updateInfoModel(model:ASActionInfoModel?){
         infoModel = model
         if let model = model {
-            complete(model)
+            complete?(model)
             setRingViewData(model: model)
         }
     }

+ 3 - 3
AIPlayRingtones/AppPage/Common/ Notification+Ex.swift

@@ -14,9 +14,9 @@ extension Notification.Name {
     
     static let kBaseOperationQueueCountChanged = Notification.Name("kBaseOperationQueueCountChanged") //任务数量放生变化
     
-    static let kGenerateRingOperationChanged = Notification.Name("kGeneratePTPOperationChanged") //生成铃声任务发生变化
-    static let kGenerateTTROperationChanged = Notification.Name("kGeneratePTPOperationChanged") //生成文生铃声任务发生变化
-    static let kGenerateRTROperationChanged = Notification.Name("kGeneratePTPOperationChanged") //生成铃声生铃声任务发生变化
+    static let kGenerateRingOperationChanged = Notification.Name("kGenerateRingOperationChanged") //生成铃声任务发生变化
+    static let kGenerateTTROperationChanged = Notification.Name("kGenerateTTROperationChanged") //生成文生铃声任务发生变化
+    static let kGenerateRTROperationChanged = Notification.Name("kGenerateRTROperationChanged") //生成铃声生铃声任务发生变化
     
     static let kRingDataChanged = Notification.Name("kGeneratePTPOperationChanged") //铃声数据发生变化
     static let kTextToRingDataChanged = Notification.Name("kTextToRingDataChanged") //文生铃声数据改变

+ 10 - 0
AIPlayRingtones/AppPage/Common/Ex/UIFont+TSEx.swift

@@ -0,0 +1,10 @@
+//
+//  Untitled.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/4/1.
+//
+
+public extension FontName {
+    static let PoppinsBoldItalic   = "Poppins-BoldItalic"
+}

+ 1 - 1
AIPlayRingtones/AppPage/Common/TSNetWork/TSNetWork+Business.swift

@@ -50,7 +50,7 @@ func getUserInfoJsonString()->[String:Any] {
 //        "subscriptionStatus":kPurchaseDefault.isVip ? "active" : "fallow",
     ]
 
-    return [String:Any]()
+    return dic
 }
 
 

BIN
AIPlayRingtones/Assets.xcassets/App-Icon.imageset/App-Icon.png


+ 21 - 0
AIPlayRingtones/Assets.xcassets/App-Icon.imageset/Contents.json

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

+ 99 - 14
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/Contents.json

@@ -1,30 +1,115 @@
 {
   "images" : [
     {
+      "filename" : "icon-20@2x.png",
       "idiom" : "universal",
       "platform" : "ios",
-      "size" : "1024x1024"
+      "scale" : "2x",
+      "size" : "20x20"
     },
     {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
+      "filename" : "icon-20@3x.png",
       "idiom" : "universal",
       "platform" : "ios",
-      "size" : "1024x1024"
+      "scale" : "3x",
+      "size" : "20x20"
+    },
+    {
+      "filename" : "icon-29@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "icon-29@3x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "3x",
+      "size" : "29x29"
+    },
+    {
+      "filename" : "icon-38@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "38x38"
+    },
+    {
+      "filename" : "icon-38@3x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "3x",
+      "size" : "38x38"
+    },
+    {
+      "filename" : "icon-40@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "icon-40@3x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "3x",
+      "size" : "40x40"
+    },
+    {
+      "filename" : "icon-60@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "icon-60@3x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "3x",
+      "size" : "60x60"
+    },
+    {
+      "filename" : "icon-64@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "64x64"
+    },
+    {
+      "filename" : "icon-64@3x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "3x",
+      "size" : "64x64"
+    },
+    {
+      "filename" : "icon-68@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "68x68"
+    },
+    {
+      "filename" : "icon-76@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "76x76"
+    },
+    {
+      "filename" : "icon-83.5@2x.png",
+      "idiom" : "universal",
+      "platform" : "ios",
+      "scale" : "2x",
+      "size" : "83.5x83.5"
     },
     {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "tinted"
-        }
-      ],
+      "filename" : "icon-1024.png",
       "idiom" : "universal",
       "platform" : "ios",
+      "scale" : "1x",
       "size" : "1024x1024"
     }
   ],

BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-1024.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/CellPlay/refresh_purple.imageset/Contents.json

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

BIN
AIPlayRingtones/Assets.xcassets/CellPlay/refresh_purple.imageset/refresh_purple@2x.png


BIN
AIPlayRingtones/Assets.xcassets/CellPlay/refresh_purple.imageset/refresh_purple@3x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/failed_big.imageset/failed_big@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/failed_big.imageset/failed_big@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/Common/generated_loading.imageset/Contents.json

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

BIN
AIPlayRingtones/Assets.xcassets/Common/generated_loading.imageset/generated_loading@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/generated_loading.imageset/generated_loading@3x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/network_error.imageset/network_error@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/network_error.imageset/network_error@3x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/pageNull.imageset/pageNull@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/pageNull.imageset/pageNull@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/Common/page_x.imageset/Contents.json

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

BIN
AIPlayRingtones/Assets.xcassets/Common/page_x.imageset/page_x@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/page_x.imageset/page_x@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/Common/setAs_bg.imageset/Contents.json

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

BIN
AIPlayRingtones/Assets.xcassets/Common/setAs_bg.imageset/setAs_bg@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/setAs_bg.imageset/setAs_bg@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/Common/x.imageset/Contents.json

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

BIN
AIPlayRingtones/Assets.xcassets/Common/x.imageset/x@2x.png


BIN
AIPlayRingtones/Assets.xcassets/Common/x.imageset/x@3x.png


+ 13 - 15
AIPlayRingtones/Base.lproj/LaunchScreen.storyboard

@@ -1,10 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
     <device id="retina6_12" orientation="portrait" appearance="light"/>
     <dependencies>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
@@ -16,18 +15,19 @@
                         <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="我是启动页" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Utq-NQ-ipo">
-                                <rect key="frame" x="69" y="393.66666666666669" width="255" height="64.666666666666686"/>
-                                <fontDescription key="fontDescription" type="system" pointSize="54"/>
-                                <nil key="textColor"/>
-                                <nil key="highlightedColor"/>
-                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="App-Icon" translatesAutoresizingMaskIntoConstraints="NO" id="BHi-fz-vwn">
+                                <rect key="frame" x="146.66666666666666" y="326" width="100" height="100"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="100" id="T2o-X2-J5M"/>
+                                    <constraint firstAttribute="width" constant="100" id="w70-0w-wSZ"/>
+                                </constraints>
+                            </imageView>
                         </subviews>
                         <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
-                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                         <constraints>
-                            <constraint firstItem="Utq-NQ-ipo" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="dc8-BR-Rlx"/>
-                            <constraint firstItem="Utq-NQ-ipo" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="drs-SC-nJf"/>
+                            <constraint firstItem="BHi-fz-vwn" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="iyQ-Kw-JOp"/>
+                            <constraint firstItem="BHi-fz-vwn" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" constant="-50" id="nGb-GY-J86"/>
                         </constraints>
                     </view>
                 </viewController>
@@ -37,8 +37,6 @@
         </scene>
     </scenes>
     <resources>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
+        <image name="App-Icon" width="512" height="512"/>
     </resources>
 </document>

+ 3 - 1
AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorErrorView.swift

@@ -40,7 +40,9 @@ class ASGeneratorErrorView: TSBaseView {
     }()
     
     lazy var submitBtn: UIButton = {
-        let btn = UIButton.createButton(title: "Generate in the background".localized,backgroundColor: .white.withAlphaComponent(0.4),font: .font(size: 16),titleColor: "#111111".uiColor,corner: 24)
+        let btn = UIButton.createButton(title: "",font: .font(size: 16),titleColor: .themeColor,corner: 24)
+        btn.layer.borderColor = UIColor.themeColor.cgColor
+        btn.layer.borderWidth = 1.0
         btn.titleLabel?.adjustsFontSizeToFitWidth = true
         return btn
     }()

+ 15 - 2
AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorLoadingView.swift

@@ -47,6 +47,11 @@ class ASGeneratorLoadingView : TSBaseView {
         return textLabel
     }()
     
+    lazy var progressView: TSRingProgressView = {
+        let progressView = TSRingProgressView()
+        return progressView
+    }()
+    
     lazy var textLabel: UILabel = {
         let textLabel = UILabel.createLabel(font: .font(size: 18),textColor: .white,textAlignment: .center,numberOfLines: 0)
         textLabel.isHidden = true
@@ -95,8 +100,15 @@ class ASGeneratorLoadingView : TSBaseView {
             make.trailing.equalTo(-kTextLeading)
         }
         
-        cusStackView.addSpacing(length: 16.0)
+        cusStackView.addSpacing(length: 12.0)
+        
+        cusStackView.addArrangedSubview(progressView)
+        progressView.snp.makeConstraints { make in
+            make.leading.equalTo(40)
+            make.trailing.equalTo(-40)
+        }
         
+        cusStackView.addSpacing(length: 8.0)
         cusStackView.addArrangedSubview(textLabel)
         textLabel.snp.makeConstraints { make in
             make.leading.equalTo(kTextLeading)
@@ -146,9 +158,10 @@ extension ASGeneratorLoadingView {
         infoLabel.isHidden = info.isEmpty
     }
     
-    func setProgressText(text:String) {
+    func setProgressText(progress:Float, text:String) {
         textLabel.text = text
         textLabel.isHidden = text.isEmpty
+        progressView.setProgress(progress: progress)
     }
 
 }

+ 7 - 7
AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorView.swift

@@ -45,7 +45,7 @@ class ASGeneratorView: TSBaseView {
         let blurEffect = UIBlurEffect(style: .dark)
         let blurEffectView = UIVisualEffectView(effect: blurEffect)
         blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-        blurEffectView.alpha = 0.95
+        blurEffectView.alpha = 0.9
         return blurEffectView
     }()
     
@@ -124,12 +124,12 @@ class ASGeneratorView: TSBaseView {
     
 
     
-    func showLoading(text:String){
+    func showLoading(progress:Float, text:String) {
         isRotating = true
         animationView.isHidden = false
         errorView.isHidden = true
         
-        animationView.setProgressText(text: text)
+        animationView.setProgressText(progress:progress,text: text)
     }
     
     func showError(text:String){
@@ -160,15 +160,15 @@ class ASGeneratorView: TSBaseView {
 
 extension ASGeneratorView{
     
-    func updateShowProgress(text:String) {
+    func updateShowProgress(progress:Float, text:String) {
         isHidden = false
-        showLoading(text: text)
+        showLoading(progress:progress,text: text)
         isRotating = true
     }
     
-    func updateShowLoading(text:String){
+    func updateShowLoading(progress:Float, text:String) {
         isHidden = false
-        showLoading(text: text)
+        showLoading(progress:progress,text: text)
         isRotating = true
     }
     

+ 3 - 4
AIPlayRingtones/CommonView/ASPageNullView.swift

@@ -12,7 +12,7 @@ class ASPageNullView: TSBaseView {
     }()
     
     lazy var titleLabel: UILabel = {
-        let titleLabel = UILabel.createLabel(text:"No record".localized ,font:.font(size: 14.0),textColor: .white,textAlignment: .center,numberOfLines: 0)
+        let titleLabel = UILabel.createLabel(text:"No record".localized ,font:.font(size: 14.0,weight: .medium),textColor: .white,textAlignment: .center,numberOfLines: 0)
         return titleLabel
     }()
     
@@ -24,17 +24,16 @@ class ASPageNullView: TSBaseView {
         
         contentView.addSubview(imageView)
         imageView.snp.makeConstraints { make in
-            make.top.equalTo(151)
+            make.top.equalTo(176)
             make.centerX.equalToSuperview()
             make.width.height.equalTo(120)
         }
 
         contentView.addSubview(titleLabel)
         titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(imageView.snp.bottom)
+            make.top.equalTo(imageView.snp.bottom).offset(16.0)
             make.leading.equalTo(16)
             make.trailing.equalTo(-16)
-            make.height.equalTo(20)
         }
 
     }

+ 101 - 35
AIPlayRingtones/CommonView/ASRingToneCellView.swift

@@ -30,14 +30,10 @@ class ASRingToneCellView: TSBaseView {
         return coverImageView
     }()
     
-//    let selectedColor:UIColor = "#3C213F".uiColor
-    lazy var progressView: TSCircularProgressView = {
-        let progressView = TSCircularProgressView(frame: CGRect(x: 0, y: 0, width: 49, height: 49))
-        progressView.trackColor = .clear
-        progressView.progressColor = .white
-        progressView.lineWidth = 2.0 // 设置线条粗细
-        progressView.isClockwise = true // 设置为逆时针
-        progressView.progress = 0.0
+    lazy var progressView: TSRingProgressView = {
+        let progressView = TSRingProgressView()
+        progressView.isHidden = true
+        progressView.generateProgressView.image = nil
         return progressView
     }()
     
@@ -132,12 +128,6 @@ class ASRingToneCellView: TSBaseView {
             make.centerY.equalToSuperview()
             make.width.height.equalTo(48)
         }
-
-        progressView.snp.makeConstraints { make in
-            make.leading.equalTo(11)
-            make.centerY.equalToSuperview()
-            make.width.height.equalTo(progressView.width)
-        }
         
         playBtn.snp.makeConstraints { make in
             make.center.equalToSuperview()
@@ -156,6 +146,12 @@ class ASRingToneCellView: TSBaseView {
             make.height.equalTo(12)
         }
         
+        progressView.snp.makeConstraints { make in
+            make.leading.equalTo(timeLab.snp.trailing).offset(8)
+            make.centerY.equalTo(timeLab.snp.centerY)
+            make.trailing.equalTo(-52)
+        }
+        
         contentView.addSubview(rightShade)
         rightShade.snp.makeConstraints { make in
             make.trailing.top.bottom.equalToSuperview()
@@ -222,7 +218,7 @@ extension ASRingToneCellView {
         case .currentTime(_):
             self.isPlay = true
             self.progressView.isHidden = false
-            self.progressView.progress = CGFloat(TSBusinessAudioPlayer.shared.playProgress)
+            self.progressView.progress = Float(TSBusinessAudioPlayer.shared.playProgress)
         default:
             break
         }
@@ -236,9 +232,19 @@ class TSRingToneGenerateView:TSBaseView {
     
     var refreshHandel:(()->Void)?
 
-    lazy var generateProgressView: UIImageView = {
-        let generateProgressView = UIImageView.createImageView(imageName: "cell_ring_progress",contentMode: .scaleToFill)
-        return generateProgressView
+    lazy var bgImageView: UIImageView = {
+        let bgImageView = UIImageView.createImageView(image: .cellRingBg,contentMode: .scaleToFill)
+        return bgImageView
+    }()
+    
+    lazy var progressLabel: UILabel = {
+        let progressLabel = UILabel.createLabel(text:"Working On Your Ringtone...".localized,font: .font(size: 14),textColor: .white,numberOfLines: 1)
+        return progressLabel
+    }()
+    
+    lazy var progressView: TSRingProgressView = {
+        let progressView = TSRingProgressView()
+        return progressView
     }()
     
     lazy var iconImageView: UIImageView = {
@@ -254,7 +260,7 @@ class TSRingToneGenerateView:TSBaseView {
     
     lazy var refreshBtn: TSUIExpandedTouchButton = {
         let refreshBtn = TSUIExpandedTouchButton()
-        refreshBtn.setUpButton(image: UIImage(named: "refresh_white")){[weak self]  in
+        refreshBtn.setUpButton(image: .refreshPurple){[weak self]  in
             guard let self = self else { return }
             refreshHandel?()
         }
@@ -268,12 +274,11 @@ class TSRingToneGenerateView:TSBaseView {
         
         contentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(clickContentView)))
         
-        contentView.addSubview(generateProgressView)
-        generateProgressView.snp.makeConstraints { make in
-            make.leading.top.bottom.equalTo(0)
-            make.width.equalToSuperview().multipliedBy(1.0)
+        contentView.addSubview(bgImageView)
+        bgImageView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
         }
-        
+ 
         contentView.addSubview(iconImageView)
         iconImageView.snp.makeConstraints { make in
             make.centerY.equalToSuperview()
@@ -281,11 +286,26 @@ class TSRingToneGenerateView:TSBaseView {
             make.leading.equalTo(12.0)
         }
         
+        contentView.addSubview(progressLabel)
+        progressLabel.snp.makeConstraints { make in
+            make.leading.equalTo(iconImageView.snp.trailing).offset(20)
+            make.top.equalTo(22)
+            make.trailing.equalTo(-16)
+        }
+        
+        contentView.addSubview(progressView)
+        progressView.snp.makeConstraints { make in
+            make.leading.equalTo(iconImageView.snp.trailing).offset(20)
+            make.bottom.equalTo(-22)
+            make.trailing.equalTo(-16)
+        }
+        
+        
         contentView.addSubview(infoLabel)
         infoLabel.snp.makeConstraints { make in
             make.centerY.equalToSuperview()
-            make.leading.equalTo(iconImageView.snp.trailing).offset(16)
-            make.trailing.equalTo(-50)
+            make.leading.equalTo(iconImageView.snp.trailing).offset(20)
+            make.trailing.equalTo(-40)
         }
         
         contentView.addSubview(refreshBtn)
@@ -304,20 +324,66 @@ class TSRingToneGenerateView:TSBaseView {
     }
     
     func setProgress(progress:Float) {
-        generateProgressView.snp.remakeConstraints{ make in
-            make.leading.top.bottom.equalTo(0)
-            make.width.equalToSuperview().multipliedBy(progress)
-        }
-        generateProgressView.isHidden = false
+        progressLabel.isHidden = false
+        progressView.isHidden = false
+        progressView.setProgress(progress: progress)
+        
+        infoLabel.isHidden = true
         refreshBtn.isHidden = true
-        let progressInt = Int(progress*100)
-        infoLabel.text = "Working on your ringtone \(progressInt)%..."
     }
     
     func setFail(){
-        setProgress(progress: 0.0)
+        progressLabel.isHidden = true
+        progressView.isHidden = true
+        progressView.setProgress(progress: 0)
+        
         infoLabel.text = "Generation Failed".localized
+        infoLabel.isHidden = false
         refreshBtn.isHidden = false
-        generateProgressView.isHidden = true
     }
 }
+
+
+class TSRingProgressView:TSBaseView {
+    
+    lazy var generateProgressView: UIImageView = {
+        let generateProgressView = UIImageView.createImageView(imageName: "cell_ring_progress",contentMode: .scaleToFill)
+        generateProgressView.backgroundColor = .white
+        generateProgressView.cornerRadius = 1.0
+        return generateProgressView
+    }()
+    
+    override func creatUI() {
+   
+        contentView.backgroundColor = .white.withAlphaComponent(0.2)
+        contentView.cornerRadius = 1.0
+        contentView.addSubview(generateProgressView)
+        
+        contentView.snp.remakeConstraints { make in
+            make.edges.equalToSuperview()
+            make.height.equalTo(2)
+        }
+        
+        generateProgressView.snp.makeConstraints { make in
+            make.leading.top.bottom.equalTo(0)
+            make.width.equalToSuperview().multipliedBy(0.0)
+        }
+    
+        
+    }
+
+    func setProgress(progress:Float) {
+        generateProgressView.snp.remakeConstraints{ make in
+            make.leading.top.bottom.equalTo(0)
+            make.width.equalToSuperview().multipliedBy(progress)
+        }
+    }
+    
+    
+    var progress:Float = 0.0{
+        didSet{
+            setProgress(progress: progress)
+        }
+    }
+    
+}

+ 488 - 0
AIPlayRingtones/CommonView/FakeBlurView.swift

@@ -0,0 +1,488 @@
+//
+//  FakeBlurView.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/22.
+//
+
+import UIKit
+
+
+import MetalKit
+import MetalPerformanceShaders
+
+final class HybridBlurView: MTKView {
+    
+    // MARK: - 可配置属性
+    
+    /// 模糊半径 (0-30pt)
+    var blurRadius: Float = 10 {
+        didSet {
+            metalBlurRadius = max(0, blurRadius - systemBlurRadius)
+            rebuildPipeline()
+        }
+    }
+    
+    /// 原生模糊的基础半径 (0-8pt)
+    var systemBlurRadius: Float = 8 {
+        didSet {
+            rebuildPipeline()
+        }
+    }
+    
+    // MARK: - 私有属性
+    
+    private var metalBlurRadius: Float = 2
+    private let deviceDefault = MTLCreateSystemDefaultDevice()!
+    private var commandQueue: MTLCommandQueue!
+    private var textureCache: CVMetalTextureCache!
+    private var blurPipeline: MPSImageGaussianBlur?
+    private var sourceTexture: MTLTexture?
+    private var destinationTexture: MTLTexture?
+    
+    private lazy var systemBlurView: UIVisualEffectView = {
+        let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
+        view.frame = bounds
+        view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+        return view
+    }()
+    
+    // MARK: - 初始化
+    
+    override init(frame frameRect: CGRect, device: MTLDevice?) {
+        super.init(frame: frameRect, device: device ?? MTLCreateSystemDefaultDevice()!)
+        commonInit()
+    }
+    
+    required init(coder: NSCoder) {
+        super.init(coder: coder)
+        commonInit()
+    }
+    
+    private func commonInit() {
+        // Metal基础配置
+        self.device = device
+        self.framebufferOnly = false
+        self.isPaused = true
+        self.enableSetNeedsDisplay = true
+        self.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
+        
+        // 创建命令队列
+        commandQueue = deviceDefault.makeCommandQueue()
+        
+        // 设置纹理缓存
+        CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, deviceDefault, nil, &textureCache)
+        
+        // 添加系统模糊视图
+        addSubview(systemBlurView)
+        sendSubviewToBack(systemBlurView)
+        
+        // 初始管道
+        rebuildPipeline()
+    }
+    
+    // MARK: - 管道重建
+    
+    private func rebuildPipeline() {
+        // 系统模糊视图效果调整
+        let effect = UIBlurEffect(style: .light)
+        systemBlurView.effect = effect
+        
+        // Metal模糊管道 (只处理超出系统模糊的部分)
+        if metalBlurRadius > 0 {
+            blurPipeline = MPSImageGaussianBlur(device: deviceDefault, sigma: metalBlurRadius)
+        } else {
+            blurPipeline = nil
+        }
+    }
+    
+    // MARK: - 纹理处理
+    
+    private func prepareTextures() {
+        // 获取系统模糊视图的截图(修正cgImage访问方式)
+        guard let snapshot = systemBlurView.snapshotView(afterScreenUpdates: false) else { return }
+
+        UIGraphicsBeginImageContextWithOptions(snapshot.bounds.size, false, 0)
+        defer { UIGraphicsEndImageContext() }
+
+        guard let context = UIGraphicsGetCurrentContext() else { return }
+        snapshot.layer.render(in: context)
+        guard let image = UIGraphicsGetImageFromCurrentImageContext(),
+              let cgImage = image.cgImage else { return }
+        
+        // 创建源纹理
+        let textureLoader = MTKTextureLoader(device: deviceDefault)
+        sourceTexture = try? textureLoader.newTexture(cgImage: cgImage, options: [
+            .SRGB: false,
+            .generateMipmaps: false
+        ])
+        
+        // 创建目标纹理
+        let descriptor = MTLTextureDescriptor.texture2DDescriptor(
+            pixelFormat: .bgra8Unorm,
+            width: Int(drawableSize.width),
+            height: Int(drawableSize.height),
+            mipmapped: false
+        )
+        descriptor.usage = [.shaderRead, .shaderWrite, .renderTarget]
+        destinationTexture = deviceDefault.makeTexture(descriptor: descriptor)
+    }
+    
+    // MARK: - 渲染
+    
+    override func draw(_ rect: CGRect) {
+        super.draw(rect)
+        
+        guard let drawable = currentDrawable,
+              let commandBuffer = commandQueue.makeCommandBuffer() else { return }
+        
+        // 确保先准备好纹理
+        prepareTextures()
+        
+        // 如果没有额外的Metal模糊需求
+        guard metalBlurRadius > 0,
+              let blurPipeline = blurPipeline,
+              let sourceTexture = sourceTexture,
+              let destinationTexture = destinationTexture else {
+            
+            // 直接显示系统模糊效果(确保有源纹理)
+            if let sourceTexture = sourceTexture {
+                if let blitEncoder = commandBuffer.makeBlitCommandEncoder() {
+                    blitEncoder.copy(from: sourceTexture, to: drawable.texture)
+                    blitEncoder.endEncoding()
+                }
+            } else {
+                // 如果连系统模糊纹理都没有,清空绘制
+                let renderPassDescriptor = currentRenderPassDescriptor
+                renderPassDescriptor?.colorAttachments[0].loadAction = .clear
+                renderPassDescriptor?.colorAttachments[0].clearColor = clearColor
+                
+                if let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor!) {
+                    renderEncoder.endEncoding()
+                }
+            }
+            
+            commandBuffer.present(drawable)
+            commandBuffer.commit()
+            return
+        }
+        
+        // 执行Metal模糊
+        blurPipeline.encode(
+            commandBuffer: commandBuffer,
+            sourceTexture: sourceTexture,
+            destinationTexture: destinationTexture
+        )
+        
+        // 将结果复制到drawable
+        if let blitEncoder = commandBuffer.makeBlitCommandEncoder() {
+            blitEncoder.copy(from: destinationTexture, to: drawable.texture)
+            blitEncoder.endEncoding()
+        }
+        
+        commandBuffer.present(drawable)
+        commandBuffer.commit()
+    }
+    
+    // MARK: - 布局更新
+    
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        systemBlurView.frame = bounds
+        setNeedsDisplay()
+    }
+}
+
+/// 仿毛玻璃效果视图(视觉欺骗方案)
+final class FakeBlurView: UIView {
+    
+    // MARK: - 可配置属性
+    
+    /// 模糊强度 (0.0 ~ 1.0)
+    @IBInspectable var intensity: CGFloat = 0.7 {
+        didSet { updateAllLayers() }
+    }
+    
+    /// 基础模糊色调 (默认白色)
+    @IBInspectable var baseColor: UIColor = .white {
+        didSet { baseLayer.backgroundColor = baseColor.withAlphaComponent(baseAlpha).cgColor }
+    }
+    
+    /// 噪点颗粒密度 (0.1 ~ 2.0)
+    @IBInspectable var noiseDensity: CGFloat = 1.0 {
+        didSet { generateNoiseTexture() }
+    }
+    
+    /// 是否启用动态光晕
+    @IBInspectable var enableHighlight: Bool = true {
+        didSet { highlightLayer.isHidden = !enableHighlight }
+    }
+    
+    // MARK: - 私有属性
+    
+    private let baseLayer = CALayer()
+    private let noiseLayer = CALayer()
+    private let highlightLayer = CALayer()
+    private let gradientMask = CAGradientLayer()
+    private var baseAlpha: CGFloat { intensity * 0.8 }
+    
+    // MARK: - 初始化
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        commonInit()
+    }
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+        commonInit()
+    }
+    
+    private func commonInit() {
+        layer.masksToBounds = true
+        setupBaseLayer()
+        setupNoiseLayer()
+        setupHighlightLayer()
+        setupGradientMask()
+        
+        // 监听设备旋转
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(handleDeviceOrientation),
+            name: UIDevice.orientationDidChangeNotification,
+            object: nil
+        )
+    }
+    
+    // MARK: - 图层设置
+    
+    private func setupBaseLayer() {
+        baseLayer.frame = bounds
+        baseLayer.backgroundColor = baseColor.withAlphaComponent(baseAlpha).cgColor
+        layer.addSublayer(baseLayer)
+    }
+    
+    private func setupNoiseLayer() {
+        noiseLayer.frame = bounds
+        noiseLayer.contentsGravity = .center
+        generateNoiseTexture()
+        layer.addSublayer(noiseLayer)
+    }
+    
+    private func setupHighlightLayer() {
+        highlightLayer.frame = bounds
+        highlightLayer.isHidden = !enableHighlight
+        updateHighlight()
+        layer.addSublayer(highlightLayer)
+    }
+    
+    private func setupGradientMask() {
+        gradientMask.frame = bounds
+        layer.mask = gradientMask
+        updateGradientMask()
+    }
+    
+    // MARK: - 核心算法
+    
+    /// 生成可平铺的噪点纹理
+    private func generateNoiseTexture() {
+        let size = CGSize(width: 100, height: 100)
+        let pointCount = Int(500 * noiseDensity)
+        
+        let renderer = UIGraphicsImageRenderer(size: size)
+        let image = renderer.image { ctx in
+            UIColor.clear.setFill()
+            ctx.fill(CGRect(origin: .zero, size: size))
+            
+            for _ in 0..<pointCount {
+                let alpha = CGFloat.random(in: 0.02...0.1)
+                let point = CGPoint(
+                    x: CGFloat.random(in: 0..<size.width),
+                    y: CGFloat.random(in: 0..<size.height)
+                )
+                let radius = CGFloat.random(in: 0.5...2.0)
+                
+                UIColor.white.withAlphaComponent(alpha).setFill()
+                UIBezierPath(ovalIn: CGRect(
+                    x: point.x, y: point.y,
+                    width: radius, height: radius
+                )).fill()
+            }
+        }
+        
+        noiseLayer.contents = image.cgImage
+        noiseLayer.contentsScale = UIScreen.main.scale
+    }
+    
+    /// 更新径向渐变遮罩
+    private func updateGradientMask() {
+        gradientMask.type = .radial
+        gradientMask.colors = [
+            UIColor.white.cgColor,
+            UIColor.clear.cgColor
+        ]
+        gradientMask.locations = [0, NSNumber(value: Double(intensity * 1.5))]
+        
+        let center = CGPoint(x: bounds.midX, y: bounds.midY)
+        gradientMask.startPoint = center
+        gradientMask.endPoint = CGPoint(
+            x: center.x + bounds.width * 0.5,
+            y: center.y + bounds.height * 0.5
+        )
+    }
+    
+    /// 更新高光效果
+    private func updateHighlight() {
+        let gradient = CAGradientLayer()
+        gradient.frame = highlightLayer.bounds
+        
+        let highlightColor = UIColor.white.withAlphaComponent(0.3 * intensity)
+        gradient.colors = [
+            UIColor.clear.cgColor,
+            highlightColor.cgColor,
+            UIColor.clear.cgColor
+        ]
+        
+        if bounds.width > bounds.height {
+            gradient.startPoint = CGPoint(x: 0, y: 0.5)
+            gradient.endPoint = CGPoint(x: 1, y: 0.5)
+        } else {
+            gradient.startPoint = CGPoint(x: 0.5, y: 0)
+            gradient.endPoint = CGPoint(x: 0.5, y: 1)
+        }
+        
+        highlightLayer.mask = gradient
+    }
+    
+    /// 统一更新所有图层
+    private func updateAllLayers() {
+        baseLayer.backgroundColor = baseColor.withAlphaComponent(baseAlpha).cgColor
+        updateGradientMask()
+        updateHighlight()
+    }
+    
+    // MARK: - 布局更新
+    
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        baseLayer.frame = bounds
+        noiseLayer.frame = bounds
+        highlightLayer.frame = bounds
+        gradientMask.frame = bounds
+        updateAllLayers()
+    }
+    
+    // MARK: - 设备方向处理
+    
+    @objc private func handleDeviceOrientation() {
+        UIView.animate(withDuration: 0.3) {
+            self.updateHighlight()
+        }
+    }
+    
+    // MARK: - 动态效果
+    
+    /// 根据滚动速度调整模糊效果
+    /// - Parameter velocity: 滚动速度(来自UIScrollView)
+    func adjustForScrollVelocity(_ velocity: CGPoint) {
+        let velocityFactor = min(max(abs(velocity.x) + abs(velocity.y), 0), 2000) / 2000
+        
+        CATransaction.begin()
+        CATransaction.setAnimationDuration(0.3)
+        
+        let scale = 1.0 + 0.3 * velocityFactor
+        noiseLayer.transform = CATransform3DMakeScale(scale, scale, 1)
+        highlightLayer.opacity = Float(1 - velocityFactor)
+        
+        CATransaction.commit()
+    }
+    
+    // MARK: - 内存管理
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+}
+
+////示例1:基础使用(代码方式)
+//class ViewController: UIViewController {
+//    private let fakeBlurView = FakeBlurView()
+//
+//    override func viewDidLoad() {
+//        super.viewDidLoad()
+//        
+//        // 添加到视图层级
+//        view.addSubview(fakeBlurView)
+//        fakeBlurView.frame = CGRect(x: 20, y: 100, width: 300, height: 100)
+//        
+//        // 基础配置
+//        fakeBlurView.tintColor = .systemBlue
+//        fakeBlurView.intensity = 0.8
+//        fakeBlurView.noiseDensity = 1.2
+//        fakeBlurView.layer.cornerRadius = 12
+//        
+//        // 添加测试内容
+//        let label = UILabel(frame: fakeBlurView.bounds)
+//        label.text = "仿毛玻璃效果测试"
+//        label.textAlignment = .center
+//        label.font = .boldSystemFont(ofSize: 18)
+//        fakeBlurView.addSubview(label)
+//    }
+//}
+
+//示例3:结合UIScrollView动态效果
+//class ScrollViewController: UIViewController, UIScrollViewDelegate {
+//    @IBOutlet weak var scrollView: UIScrollView!
+//    @IBOutlet weak var headerBlurView: FakeBlurView!
+//    
+//    override func viewDidLoad() {
+//        super.viewDidLoad()
+//        scrollView.delegate = self
+//        headerBlurView.intensity = 0.5
+//    }
+//    
+//    func scrollViewDidScroll(_ scrollView: UIScrollView) {
+//        // 根据滚动位置调整强度
+//        let offsetY = scrollView.contentOffset.y
+//        let maxOffset: CGFloat = 100
+//        let newIntensity = min(max(0, offsetY / maxOffset), 1)
+//        headerBlurView.intensity = newIntensity
+//        
+//        // 根据速度添加动态效果
+//        let velocity = scrollView.panGestureRecognizer.velocity(in: scrollView)
+//        headerBlurView.adjustForScrollVelocity(velocity)
+//    }
+//}
+
+//示例4:状态栏模糊背景
+//extension UIViewController {
+//    func addStatusBarBlur() {
+//        let statusBarView = FakeBlurView(frame: UIApplication.shared.statusBarFrame)
+//        statusBarView.tag = 10086
+//        statusBarView.intensity = 0.9
+//        statusBarView.tintColor = .systemBackground
+//        view.addSubview(statusBarView)
+//    }
+//    
+//    func updateStatusBarBlur(alpha: CGFloat) {
+//        view.viewWithTag(10086)?.alpha = alpha
+//    }
+//}
+//
+
+//// 在viewDidLoad中调用
+//addStatusBarBlur()
+
+
+
+// 在需要极致性能时调用
+//fakeBlurView.layer.shouldRasterize = true
+//fakeBlurView.layer.rasterizationScale = UIScreen.main.scale
+
+////动态色调切换​​:
+//UIView.animate(withDuration: 0.3) {
+//    self.fakeBlurView.tintColor = isDarkMode ? .darkGray : .white
+//}
+
+//// 降低纹理分辨率(内存减少75%)
+//fakeBlurView.noiseDensity = 0.5

+ 0 - 0
AIPlayRingtones/CommonView/Untitled.swift


+ 8 - 0
AIPlayRingtones/Info.plist

@@ -7,5 +7,13 @@
 		<key>NSAllowsArbitraryLoads</key>
 		<true/>
 	</dict>
+	<key>UIAppFonts</key>
+	<array>
+		<string>Poppins-BoldItalic.otf</string>
+	</array>
+	<key>UIBackgroundModes</key>
+	<array>
+		<string>audio</string>
+	</array>
 </dict>
 </plist>

+ 4 - 1
AIPlayRingtones/OperationQueue/ASBaseOperationQueue.swift

@@ -29,6 +29,8 @@ class ASBaseOperationQueue {
         return false
     }
     
+    weak var latestOperation:ASBaseOperation? //最新的任务
+    
     init(maxConcurrentOperationCount: Int = 1) {
         queue.maxConcurrentOperationCount = maxConcurrentOperationCount
         dePrint("ASBaseOperationQueue operationCountObservation")
@@ -36,7 +38,7 @@ class ASBaseOperationQueue {
            operationCountObservation = queue.observe(\.operationCount, options: [.new]) { [weak self] (queue, change) in
                guard let _ = self else { return }
                if let _ = change.newValue {
-                   NotificationCenter.default.post(name: .kBaseOperationQueueCountChanged, object: nil, userInfo: nil)
+                   NotificationCenter.default.post(name: .kBaseOperationQueueCountChanged, object: nil, userInfo: ["ASBaseOperationQueue":self])
                }
            }
     }
@@ -67,6 +69,7 @@ class ASBaseOperationQueue {
                 
                 dePrint("ASBaseOperationQueue $operationStatePblished =\(state)")
             }
+            latestOperation = operation
             return operation
         }
     }

+ 1 - 1
AIPlayRingtones/OperationQueue/ASProgressState.swift

@@ -48,7 +48,7 @@ enum ASProgressState  {
     
     var reloadNewData:Bool{
         switch self {
-        case .pending,.success(_),.failed(_,_):
+        case .start,.pending,.success(_),.failed(_,_):
             return true
         default:
             return false

+ 32 - 12
AIPlayRingtones/OperationQueue/Generate/ASGenerateBaseOperation.swift

@@ -53,7 +53,18 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
     
     @Published var stateDatauPblished:(ASProgressState,ASActionInfoModel?) = (ASProgressState.none,nil){
         didSet{
-            dePrint("ASBaseOperation stateDatauPblished didSet = \(stateDatauPblished)")
+//            dePrint("ASBaseOperation stateDatauPblished didSet = \(stateDatauPblished)")
+//                if let block = self.stateDataPblishedChanged{
+//                    debugPrint("刷新进度block 真=\(self.stateDatauPblished)")
+//                    self.stateDataPblishedChanged?(self.stateDatauPblished.0,self.stateDatauPblished.1)
+//                }else{
+//                    debugPrint("刷新进度block 空=\(self.stateDatauPblished)")
+//                }
+            
+            DispatchQueue.main.async {
+                self.stateDataPblishedChanged?(self.stateDatauPblished.0,self.stateDatauPblished.1)
+            }
+            
             if case .start = stateDatauPblished.0 {
                 start()
             }else if stateDatauPblished.0.isResult {
@@ -68,8 +79,16 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
     var stopNetwork = false
     var generatingProgress = 0
     var action_id:Int = 0
-    var isSaveDB:Bool = true //是否保存到数据库
+    var isSaveProcessToDB:Bool = false //是否保存过程到数据库
+    {
+        didSet{
+            if isSaveProcessToDB == true {
+                saveDataDB()
+            }
+        }
+    }
     var currentActionInfoModelChanged:((ASActionInfoModel)->Void)?
+    var stateDataPblishedChanged:((ASProgressState,ASActionInfoModel?)->Void)?
     @Published var currentActionInfoModel: ASActionInfoModel = ASActionInfoModel()
     
     func initializeActionInfoModel(oldModel:ASActionInfoModel) {
@@ -80,9 +99,8 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
     
     func replaceSaveInfoModel(model:ASActionInfoModel){ }
     
-    func handleGenerateSuccess(){
-        
-    }
+    func handleGenerateSuccess(){}
+    func saveDataDB(){}
 
     func handleFailInfoModel(errorString:String?,code:Int = 0){
         self.currentActionInfoModel.actionStatus = .failed
@@ -135,7 +153,7 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                                     guard let self = self else { return }
                                     let progressInt = Int(progress*10.0)
                                     let progressString = "Generating".localized + " \(90 + progressInt)%"
-                                stateDatauPblished = (.progress(Float(progress),progressString),currentActionInfoModel)
+                                stateDatauPblished = (.progress(kPercentScale+Float(progress)*0.1,progressString),currentActionInfoModel)
                                     dePrint("生成后下载进度 \(progress)")
                             } complete: { [weak self] url, success in
                                 guard let self = self else { return }
@@ -151,10 +169,6 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                                             genmojiModel.response.size = Int(size)
                                         }
                                     }
-                               
-                                
-                                    self.stateDatauPblished = (.success(nil),genmojiModel)
-                                    self.generatingProgress = 0
                                     successBlock()
                                 }else{
                                     self.handleFailInfoModel(errorString: nil)
@@ -168,7 +182,8 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                         debugPrint("getActionInfo error failed")
                         handleFailInfoModel(errorString:genmojiModel.response.codeErrorMsg,code: genmojiModel.response.code)
                     default:
-                        stateDatauPblished = (.progress(genmojiModel.percent,generating(progress: genmojiModel.percent)),currentActionInfoModel)
+                        let progressText = generating(progress: genmojiModel.percent)
+                        stateDatauPblished = (.progress(genmojiModel.percent*kPercentScale,progressText),currentActionInfoModel)
                         if stopNetwork == false {
                             kDelayOnMainThread(2.0) {
                                 self.getActionInfo(action_id: action_id)
@@ -184,6 +199,7 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
             
         }
     }
+    
      func generating(progress:Float) -> String {
 
          //Generating 0%-100%
@@ -213,7 +229,11 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
         queryRequest?.cancel()
     }
 }
- var kRandomBoolLastResult:Bool = true
+
+let kPercentScale:Float = 0.9 //下载进度的缩减比例
+
+
+var kRandomBoolLastResult:Bool = true
 func kRandomBool() -> Bool {
     if !kRandomBoolLastResult {
         // 如果上一次是 false,这次必须返回 true

+ 74 - 4
AIPlayRingtones/OperationQueue/Generate/ASGenerateTextToRingOperation.swift

@@ -50,15 +50,29 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
     override func replaceSaveInfoModel(model:ASActionInfoModel){
         model.uuid = uuid
         model.request.uploadTimestamp = currentActionInfoModel.request.uploadTimestamp
+        model.modelType = currentActionInfoModel.modelType
+        model.id = currentActionInfoModel.id
+        if isSaveProcessToDB {
+            saveDataDB()
+        }
 
-        ASRMShared.ringDBHistory.updateData(model,id: currentActionInfoModel.id)
         currentActionInfoModel = model
         dePrint("model actionStatus 发出=\(model.actionStatus)")
         currentActionInfoModelChanged?(currentActionInfoModel)
     }
 
+    override func saveDataDB() {
+        if currentActionInfoModel.id == 0 {
+            return
+        }
+        debugPrint("saveDataDB ASRMShared.ringDBHistory.listModels.count = \(ASRMShared.ringDBHistory.listModels.count),currentActionInfoModel.id = \(currentActionInfoModel.id)")
+        ASRMShared.ringDBHistory.updateData(currentActionInfoModel,id: currentActionInfoModel.id)
+        debugPrint("saveDataDB ASRMShared.ringDBHistory.listModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
+    }
     override func handleGenerateSuccess() {
+        //只要是生成成功,就一定保存数据,且消耗次数
 //        kPurchaseDefault.useOnceForFree(type: .picToPic)
+        saveDataDB()
         
         if isShowSuccessView == false {
             return
@@ -116,14 +130,69 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
         return infoModel
     }
     
-
+//    //测试接口
+//    func creatRing(oldModel:ASActionInfoModel,complete:@escaping (Bool)->Void) {
+//        
+//        initializeActionInfoModel(oldModel: oldModel)
+//        
+//        generatingProgress = 0
+//        stopNetwork = false
+//        
+//        currentActionInfoModel.status = "running"
+//        currentActionInfoModel.actionStatus = .running
+//        currentActionInfoModel.percent = 0
+//        replaceSaveInfoModel(model: currentActionInfoModel)
+//        
+//        stateDatauPblished = (.progress(0.0,generating(progress: 0.0)),currentActionInfoModel)
+// 
+//        let infoModel = ASActionInfoModel(JSONString: "{\"id\":54914,\"actionType\":\"music_create\",\"request\":\"{\\\"prompt\\\": \\\"Dynamic ringtone, memorable hook, balanced highs and lows, versatile for any phone, Generate a Folk ringtone with a fingerpicked acoustic guitar melody and light percussion. Use a BPM of 80-90 for a warm, earthy feel.\\\", \\\"duration\\\": 5, \\\"audioUrl\\\": null, \\\"countryCode\\\": \\\"CN\\\"}\",\"response\":\"{\\\"title\\\": \\\"Whispering Pines Melody\\\", \\\"musicUrl\\\": \\\"https://be-aigc.s3-accelerate.amazonaws.com/b6651963-c501-4c91-a424-fc2bec0e60ad.wav\\\"}\",\"createdTimestamp\":1747660794,\"status\":\"success\",\"costTime\":7,\"estimateCost\":60,\"percent\":1.0}")
+//        
+//        let sendProgress:(Float,ASActionInfoModel)->Void = { [weak self] progress,infoModel in
+//            guard let self = self else { return }
+//            infoModel.percent = progress
+//            infoModel.actionStatus = .running
+//            infoModel.status = "running"
+//            self.replaceSaveInfoModel(model: infoModel)
+//            self.stateDatauPblished = (.progress(progress,"Generating".localized + " \(Int(progress*100))%"),infoModel)
+//        }
+//        
+//        var currentSec:Double = 0.0
+//        guard let infoModel = infoModel else { return  }
+//        infoModel.id = oldModel.id
+//        currentSec+=1.0
+//        kDelayOnMainThread(currentSec) {
+//            self.stateDatauPblished = (.pending,nil) //通知首页进行更新
+//        }
+//        complete(true)
+//        for index in 1...10 {
+//            kDelayOnMainThread(currentSec+Double(index)*3) {
+//                sendProgress(Float(index)/10.0,infoModel)
+//            }
+//        }
+//
+//        currentSec+=10.0*3.0+2.0
+//        kDelayOnMainThread(currentSec) {
+//            if kRandomBool() {
+//                infoModel.actionStatus = .success
+//                infoModel.status = "success"
+//                self.replaceSaveInfoModel(model: infoModel)
+//                self.stateDatauPblished = (.success(nil),infoModel)
+//                self.handleGenerateSuccess()
+//            }else{
+//                infoModel.actionStatus = .failed
+//                infoModel.status = "failed"
+//                self.replaceSaveInfoModel(model: infoModel)
+//                self.stateDatauPblished = (.failed("模拟失败", 0),infoModel)
+//            }
+//        }
+//    }
+    
     func creatRing(oldModel:ASActionInfoModel,complete:@escaping (Bool)->Void) {
         
         initializeActionInfoModel(oldModel: oldModel)
         
         generatingProgress = 0
         stopNetwork = false
-        stateDatauPblished = (.start,nil)
         
         
         currentActionInfoModel.status = "running"
@@ -165,9 +234,9 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
                 if let dataDict = kNetWorkCodeSuccess(data: data),
                    let actionId = dataDict["actionId"] as? Int{
                     if stopNetwork == false {
+                        complete(true)
                         self.stateDatauPblished = (.pending,nil) //通知首页进行更新
                         self.getActionInfo(action_id:actionId)
-                        complete(true)
                     }
                 }else{
                     handleFailInfoModel(errorString: "",code: 0)
@@ -176,6 +245,7 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
             }
         }
     }
+    
     override func generating(progress: Float) -> String {
         let progress = Float(progress)*(0.9) // 预留 10% 进度给图片下载
         //Generating 0%-100%

BIN
AIPlayRingtones/Resources/Poppins-BoldItalic.otf


BIN
AIPlayRingtones/Resources/rotatingAnimation.gif