Переглянути джерело

4.3a改造:所有的扩展全部更换

kln 1 тиждень тому
батько
коміт
31fbd07219
94 змінених файлів з 1418 додано та 2026 видалено
  1. 77 145
      AIPlayRingtones.xcodeproj/project.pbxproj
  2. 7 0
      AIPlayRingtones/AIPlayRingtones-Bridging-Header.h
  3. 4 10
      AIPlayRingtones/APConfig/APConfig+Color.swift
  4. 1 1
      AIPlayRingtones/AppDelegate.swift
  5. 2 2
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift
  6. 3 3
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+View.swift
  7. 1 1
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift
  8. 4 4
      AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift
  9. 4 4
      AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRStyleView.swift
  10. 5 5
      AIPlayRingtones/AppPage/APLaunchVC/APLaunchVC.swift
  11. 9 9
      AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift
  12. 8 6
      AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift
  13. 5 5
      AIPlayRingtones/AppPage/APRingTonesVC/APRingStyleVC/APRingStyleVC.swift
  14. 3 3
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC+View.swift
  15. 2 2
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/View/ASDurationColView.swift
  16. 15 16
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/View/ASPromptTextView.swift
  17. 1 1
      AIPlayRingtones/AppPage/APSettingVC/APSettingVC+Col.swift
  18. 4 4
      AIPlayRingtones/AppPage/APSettingVC/APSettingVC.swift
  19. 1 1
      AIPlayRingtones/AppPage/APSettingVC/ASTutorialsVC/ASTutorialsVC.swift
  20. 1 1
      AIPlayRingtones/AppPage/ASBusinessWebVC/ASBusinessWebVC.swift
  21. 6 4
      AIPlayRingtones/AppPage/ASCommonView/ASBtnView/ASAppBtnView.swift
  22. 1 1
      AIPlayRingtones/AppPage/ASCommonView/ASBtnView/ASLeftHeaderView.swift
  23. 5 5
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorBaseVC.swift
  24. 2 2
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC.swift
  25. 4 4
      AIPlayRingtones/AppPage/CustomTabBarController/CustomTabBarController.m
  26. 0 15
      AIPlayRingtones/Classes/Ex/Array+Ex.swift
  27. 0 24
      AIPlayRingtones/Classes/Ex/CGFloat+Ex.swift
  28. 0 19
      AIPlayRingtones/Classes/Ex/Date+Ex.swift
  29. 0 36
      AIPlayRingtones/Classes/Ex/NSString+Ex.swift
  30. 0 47
      AIPlayRingtones/Classes/Ex/SwiftUI/Color+Ex.swift
  31. 0 16
      AIPlayRingtones/Classes/Ex/SwiftUI/Font+Ex.swift
  32. 0 34
      AIPlayRingtones/Classes/Ex/SwiftUI/Text+Ex.swift
  33. 0 144
      AIPlayRingtones/Classes/Ex/UIButton+Ex.swift
  34. 0 49
      AIPlayRingtones/Classes/Ex/UIColor+Ex.swift
  35. 0 56
      AIPlayRingtones/Classes/Ex/UIFont+Ex.swift
  36. 0 45
      AIPlayRingtones/Classes/Ex/UIImage+Ex.swift
  37. 0 123
      AIPlayRingtones/Classes/Ex/UIView+Ex.swift
  38. 0 118
      AIPlayRingtones/Classes/Ex/UIView+Frame.swift
  39. 0 49
      AIPlayRingtones/Classes/Ex/UIView+Rotating.swift
  40. 0 58
      AIPlayRingtones/Classes/Ex/UIViewController+Ex.swift
  41. 0 149
      AIPlayRingtones/Classes/GlobalImports/GlobalImports.swift
  42. 0 151
      AIPlayRingtones/Classes/Tool/TSBusinessFileManager.swift
  43. 0 78
      AIPlayRingtones/Classes/Tool/TSCollectionViewObserver.swift
  44. 0 173
      AIPlayRingtones/Classes/Tool/TSFileManagerTool.swift
  45. 0 27
      AIPlayRingtones/Classes/Tool/TSRandomTextTool.swift
  46. 84 139
      AIPlayRingtones/Classes/View/TSPlaceholderTextView/TSPlaceholderTextView.swift
  47. 2 2
      AIPlayRingtones/Classes/View/TSSaveSuccessTool/TSSaveSuccessTool.swift
  48. 25 0
      AIPlayRingtones/Common/ASColObserver.h
  49. 87 0
      AIPlayRingtones/Common/ASColObserver.m
  50. 44 0
      AIPlayRingtones/Common/ASFileManager.h
  51. 124 0
      AIPlayRingtones/Common/ASFileManager.m
  52. 7 0
      AIPlayRingtones/Common/ASFileManager.swift
  53. 17 0
      AIPlayRingtones/Common/ASRandomTextTool.h
  54. 39 0
      AIPlayRingtones/Common/ASRandomTextTool.m
  55. 8 25
      AIPlayRingtones/Common/ASWindTool.swift
  56. 1 1
      AIPlayRingtones/Common/BaseClass/ASBaseNavContentBarView.m
  57. 130 0
      AIPlayRingtones/Common/Common.swift
  58. 0 0
      AIPlayRingtones/Common/Ex/NSString+AS.h
  59. 0 0
      AIPlayRingtones/Common/Ex/NSString+AS.m
  60. 105 0
      AIPlayRingtones/Common/Ex/UIButton+AS.swift
  61. 0 0
      AIPlayRingtones/Common/Ex/UIColor+AS.h
  62. 0 0
      AIPlayRingtones/Common/Ex/UIColor+AS.m
  63. 52 0
      AIPlayRingtones/Common/Ex/UIFont+AS.swift
  64. 14 22
      AIPlayRingtones/Common/Ex/UIImageView+AS.swift
  65. 9 37
      AIPlayRingtones/Common/Ex/UILabel+AS.swift
  66. 200 0
      AIPlayRingtones/Common/Ex/UIView+AS.swift
  67. 40 0
      AIPlayRingtones/Common/Ex/UIViewController+AS.swift
  68. 27 0
      AIPlayRingtones/Common/Ex/UIViewController+CustomAlert.h
  69. 84 0
      AIPlayRingtones/Common/Ex/UIViewController+CustomAlert.m
  70. 9 0
      AIPlayRingtones/Common/GlobalImports.swift
  71. 5 5
      AIPlayRingtones/Common/GlobalMacros.h
  72. 3 3
      AIPlayRingtones/Common/TSAudioPlayer/TSAudioPlayer.swift
  73. 8 8
      AIPlayRingtones/Common/TSAudioPlayer/TSBusinessAudioPlayer.swift
  74. 1 1
      AIPlayRingtones/Common/TSBandRingTool/AudioTool.swift
  75. 4 4
      AIPlayRingtones/Common/TSBandRingTool/TSBandRingTool.swift
  76. 4 4
      AIPlayRingtones/Common/TSNetWork/TSNetWork+Business.swift
  77. 17 17
      AIPlayRingtones/Common/TSNetWork/TSNetworkManager.swift
  78. 5 17
      AIPlayRingtones/CommonView/ASCustomAlert.swift
  79. 3 3
      AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorErrorView.swift
  80. 1 1
      AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorLoadingView.swift
  81. 2 2
      AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorView.swift
  82. 1 1
      AIPlayRingtones/CommonView/ASPageNullView.swift
  83. 2 1
      AIPlayRingtones/CommonView/ASRingLoadingView.swift
  84. 17 17
      AIPlayRingtones/CommonView/ASRingToneCellView.swift
  85. 16 32
      AIPlayRingtones/CommonView/ASTLLabel.swift
  86. 12 0
      AIPlayRingtones/CommonView/ASTouchBtn.swift
  87. 1 1
      AIPlayRingtones/CommonView/ASViewTool.swift
  88. 2 2
      AIPlayRingtones/Data/ASDBHistoryManager.swift
  89. 1 1
      AIPlayRingtones/Data/ASRealmManager.swift
  90. 2 2
      AIPlayRingtones/OperationQueue/ASBaseOperation.swift
  91. 7 7
      AIPlayRingtones/OperationQueue/ASBaseOperationQueue.swift
  92. 9 9
      AIPlayRingtones/OperationQueue/Generate/ASGenerateBaseOperation.swift
  93. 1 1
      AIPlayRingtones/OperationQueue/Generate/ASGenerateRingToRingOperation.swift
  94. 11 11
      AIPlayRingtones/OperationQueue/Generate/ASGenerateTextToRingOperation.swift

+ 77 - 145
AIPlayRingtones.xcodeproj/project.pbxproj

@@ -20,36 +20,11 @@
 		3DB4D4AA2DDDCEA50082596A /* Poppins-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A92DDDCEA50082596A /* Poppins-BoldItalic.otf */; };
 		3DB4D4B22DDF0B960082596A /* FakeBlurView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4B12DDF0B940082596A /* FakeBlurView.swift */; };
 		3DB4D4B52DE025920082596A /* ASTutorialsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4B42DE025910082596A /* ASTutorialsVC.swift */; };
-		3DBEA0CB2DE69B2E000C6859 /* UIImage+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0902DE69B2E000C6859 /* UIImage+Ex.swift */; };
-		3DBEA0CC2DE69B2E000C6859 /* TSBusinessFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0A62DE69B2E000C6859 /* TSBusinessFileManager.swift */; };
 		3DBEA0CD2DE69B2E000C6859 /* TSSaveSuccessTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0B72DE69B2E000C6859 /* TSSaveSuccessTool.swift */; };
 		3DBEA0CE2DE69B2E000C6859 /* TSSimpleCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0B52DE69B2E000C6859 /* TSSimpleCollectionView.swift */; };
-		3DBEA0CF2DE69B2E000C6859 /* WindowHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0AF2DE69B2E000C6859 /* WindowHelper.swift */; };
-		3DBEA0D22DE69B2E000C6859 /* Array+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0832DE69B2E000C6859 /* Array+Ex.swift */; };
-		3DBEA0D92DE69B2E000C6859 /* UIImageView+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0912DE69B2E000C6859 /* UIImageView+Ex.swift */; };
-		3DBEA0E12DE69B2E000C6859 /* Color+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA07F2DE69B2E000C6859 /* Color+Ex.swift */; };
-		3DBEA0E82DE69B2E000C6859 /* UIView+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0962DE69B2E000C6859 /* UIView+Ex.swift */; };
-		3DBEA0EA2DE69B2E000C6859 /* UIView+Rotating.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0982DE69B2E000C6859 /* UIView+Rotating.swift */; };
-		3DBEA0EB2DE69B2E000C6859 /* Text+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0812DE69B2E000C6859 /* Text+Ex.swift */; };
-		3DBEA0EC2DE69B2E000C6859 /* UILabel+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0922DE69B2E000C6859 /* UILabel+Ex.swift */; };
-		3DBEA0EF2DE69B2E000C6859 /* UIColor+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA08D2DE69B2E000C6859 /* UIColor+Ex.swift */; };
-		3DBEA0F02DE69B2E000C6859 /* Font+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0802DE69B2E000C6859 /* Font+Ex.swift */; };
-		3DBEA0F12DE69B2E000C6859 /* TSFileManagerTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0AA2DE69B2E000C6859 /* TSFileManagerTool.swift */; };
-		3DBEA0F32DE69B2E000C6859 /* TSRandomTextTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0A22DE69B2E000C6859 /* TSRandomTextTool.swift */; };
-		3DBEA0F62DE69B2E000C6859 /* TSCustomAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0A82DE69B2E000C6859 /* TSCustomAlertController.swift */; };
-		3DBEA0FC2DE69B2E000C6859 /* UIFont+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA08F2DE69B2E000C6859 /* UIFont+Ex.swift */; };
-		3DBEA0FE2DE69B2E000C6859 /* UIButton+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA08C2DE69B2E000C6859 /* UIButton+Ex.swift */; };
 		3DBEA0FF2DE69B2E000C6859 /* TSCustomStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0C02DE69B2E000C6859 /* TSCustomStackView.swift */; };
-		3DBEA1002DE69B2E000C6859 /* UIViewController+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0992DE69B2E000C6859 /* UIViewController+Ex.swift */; };
-		3DBEA1012DE69B2E000C6859 /* Date+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0872DE69B2E000C6859 /* Date+Ex.swift */; };
-		3DBEA1032DE69B2E000C6859 /* NSString+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA08A2DE69B2E000C6859 /* NSString+Ex.swift */; };
-		3DBEA1062DE69B2E000C6859 /* GlobalImports.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA09C2DE69B2E000C6859 /* GlobalImports.swift */; };
 		3DBEA1072DE69B2E000C6859 /* TSPlaceholderTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0B12DE69B2E000C6859 /* TSPlaceholderTextView.swift */; };
-		3DBEA1082DE69B2E000C6859 /* UIView+Frame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0972DE69B2E000C6859 /* UIView+Frame.swift */; };
-		3DBEA1092DE69B2E000C6859 /* CGFloat+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0862DE69B2E000C6859 /* CGFloat+Ex.swift */; };
-		3DBEA10B2DE69B2E000C6859 /* TSCollectionViewObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA0A72DE69B2E000C6859 /* TSCollectionViewObserver.swift */; };
 		3DBEA1102DE6A04B000C6859 /* SimpleWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA10F2DE6A04B000C6859 /* SimpleWebViewController.m */; };
-		3DBEA1122DE6A3AA000C6859 /* TopLeftLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1112DE6A3A6000C6859 /* TopLeftLabel.swift */; };
 		3DBEA11A2DE6B086000C6859 /* CustomTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1192DE6B086000C6859 /* CustomTabBarController.m */; };
 		3DBEA11E2DE6B229000C6859 /* NSString+AS.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA11D2DE6B229000C6859 /* NSString+AS.m */; };
 		3DBEA1252DE6B36D000C6859 /* UIColor+AS.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1242DE6B36D000C6859 /* UIColor+AS.m */; };
@@ -63,6 +38,22 @@
 		3DBEA1402DE6DD18000C6859 /* ASNormalNavigationBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA13F2DE6DD18000C6859 /* ASNormalNavigationBarView.m */; };
 		3DBEA1442DE6E018000C6859 /* ASBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1432DE6E018000C6859 /* ASBaseViewController.m */; };
 		3DBEA1462DE6E31C000C6859 /* APSettingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1452DE6E310000C6859 /* APSettingModel.swift */; };
+		3DBEA14B2DE6E731000C6859 /* UIViewController+CustomAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA14A2DE6E731000C6859 /* UIViewController+CustomAlert.m */; };
+		3DBEA14D2DE6E8AB000C6859 /* UILabel+AS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA14C2DE6E89B000C6859 /* UILabel+AS.swift */; };
+		3DBEA14F2DE6E926000C6859 /* ASTouchBtn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA14E2DE6E912000C6859 /* ASTouchBtn.swift */; };
+		3DBEA1562DE6EBAD000C6859 /* UIButton+AS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1502DE6EA87000C6859 /* UIButton+AS.swift */; };
+		3DBEA1582DE6ECA8000C6859 /* UIView+AS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1572DE6EC9A000C6859 /* UIView+AS.swift */; };
+		3DBEA15A2DE6EDF1000C6859 /* UIViewController+AS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1592DE6EDED000C6859 /* UIViewController+AS.swift */; };
+		3DBEA15C2DE6EEBC000C6859 /* UIImageView+AS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA15B2DE6EEB9000C6859 /* UIImageView+AS.swift */; };
+		3DBEA15E2DE6F008000C6859 /* UIFont+AS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA15D2DE6F004000C6859 /* UIFont+AS.swift */; };
+		3DBEA1602DE6F322000C6859 /* GlobalImports.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA15F2DE6F31B000C6859 /* GlobalImports.swift */; };
+		3DBEA1652DE6F390000C6859 /* ASRandomTextTool.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1642DE6F390000C6859 /* ASRandomTextTool.m */; };
+		3DBEA1672DE6F445000C6859 /* ASCustomAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1662DE6F439000C6859 /* ASCustomAlert.swift */; };
+		3DBEA16A2DE6F4F2000C6859 /* ASColObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1692DE6F4F2000C6859 /* ASColObserver.m */; };
+		3DBEA1712DE6F794000C6859 /* ASWindTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1702DE6F78D000C6859 /* ASWindTool.swift */; };
+		3DBEA1742DE6F8D3000C6859 /* ASFileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1732DE6F8D3000C6859 /* ASFileManager.m */; };
+		3DBEA1762DE6FB18000C6859 /* ASFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1752DE6FB0A000C6859 /* ASFileManager.swift */; };
+		3DBEA1782DE6FC66000C6859 /* ASTLLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DBEA1772DE6FC59000C6859 /* ASTLLabel.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 */; };
@@ -151,37 +142,12 @@
 		3DB4D4A92DDDCEA50082596A /* Poppins-BoldItalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Poppins-BoldItalic.otf"; sourceTree = "<group>"; };
 		3DB4D4B12DDF0B940082596A /* FakeBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeBlurView.swift; sourceTree = "<group>"; };
 		3DB4D4B42DE025910082596A /* ASTutorialsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASTutorialsVC.swift; sourceTree = "<group>"; };
-		3DBEA07F2DE69B2E000C6859 /* Color+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0802DE69B2E000C6859 /* Font+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Font+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0812DE69B2E000C6859 /* Text+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Text+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0832DE69B2E000C6859 /* Array+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0862DE69B2E000C6859 /* CGFloat+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGFloat+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0872DE69B2E000C6859 /* Date+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA08A2DE69B2E000C6859 /* NSString+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSString+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA08C2DE69B2E000C6859 /* UIButton+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA08D2DE69B2E000C6859 /* UIColor+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA08F2DE69B2E000C6859 /* UIFont+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0902DE69B2E000C6859 /* UIImage+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0912DE69B2E000C6859 /* UIImageView+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0922DE69B2E000C6859 /* UILabel+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0962DE69B2E000C6859 /* UIView+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA0972DE69B2E000C6859 /* UIView+Frame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Frame.swift"; sourceTree = "<group>"; };
-		3DBEA0982DE69B2E000C6859 /* UIView+Rotating.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Rotating.swift"; sourceTree = "<group>"; };
-		3DBEA0992DE69B2E000C6859 /* UIViewController+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Ex.swift"; sourceTree = "<group>"; };
-		3DBEA09C2DE69B2E000C6859 /* GlobalImports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalImports.swift; sourceTree = "<group>"; };
-		3DBEA0A22DE69B2E000C6859 /* TSRandomTextTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSRandomTextTool.swift; sourceTree = "<group>"; };
-		3DBEA0A62DE69B2E000C6859 /* TSBusinessFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBusinessFileManager.swift; sourceTree = "<group>"; };
-		3DBEA0A72DE69B2E000C6859 /* TSCollectionViewObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSCollectionViewObserver.swift; sourceTree = "<group>"; };
-		3DBEA0A82DE69B2E000C6859 /* TSCustomAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSCustomAlertController.swift; sourceTree = "<group>"; };
-		3DBEA0AA2DE69B2E000C6859 /* TSFileManagerTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSFileManagerTool.swift; sourceTree = "<group>"; };
-		3DBEA0AF2DE69B2E000C6859 /* WindowHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowHelper.swift; sourceTree = "<group>"; };
 		3DBEA0B12DE69B2E000C6859 /* TSPlaceholderTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPlaceholderTextView.swift; sourceTree = "<group>"; };
 		3DBEA0B52DE69B2E000C6859 /* TSSimpleCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSSimpleCollectionView.swift; sourceTree = "<group>"; };
 		3DBEA0B72DE69B2E000C6859 /* TSSaveSuccessTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSSaveSuccessTool.swift; sourceTree = "<group>"; };
 		3DBEA0C02DE69B2E000C6859 /* TSCustomStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSCustomStackView.swift; sourceTree = "<group>"; };
 		3DBEA10E2DE6A04B000C6859 /* SimpleWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SimpleWebViewController.h; sourceTree = "<group>"; };
 		3DBEA10F2DE6A04B000C6859 /* SimpleWebViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SimpleWebViewController.m; sourceTree = "<group>"; };
-		3DBEA1112DE6A3A6000C6859 /* TopLeftLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopLeftLabel.swift; sourceTree = "<group>"; };
 		3DBEA1182DE6B086000C6859 /* CustomTabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomTabBarController.h; sourceTree = "<group>"; };
 		3DBEA1192DE6B086000C6859 /* CustomTabBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomTabBarController.m; sourceTree = "<group>"; };
 		3DBEA11C2DE6B229000C6859 /* NSString+AS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+AS.h"; sourceTree = "<group>"; };
@@ -205,6 +171,26 @@
 		3DBEA1422DE6E018000C6859 /* ASBaseViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASBaseViewController.h; sourceTree = "<group>"; };
 		3DBEA1432DE6E018000C6859 /* ASBaseViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASBaseViewController.m; sourceTree = "<group>"; };
 		3DBEA1452DE6E310000C6859 /* APSettingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APSettingModel.swift; sourceTree = "<group>"; };
+		3DBEA1492DE6E731000C6859 /* UIViewController+CustomAlert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIViewController+CustomAlert.h"; sourceTree = "<group>"; };
+		3DBEA14A2DE6E731000C6859 /* UIViewController+CustomAlert.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+CustomAlert.m"; sourceTree = "<group>"; };
+		3DBEA14C2DE6E89B000C6859 /* UILabel+AS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UILabel+AS.swift"; sourceTree = "<group>"; };
+		3DBEA14E2DE6E912000C6859 /* ASTouchBtn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASTouchBtn.swift; sourceTree = "<group>"; };
+		3DBEA1502DE6EA87000C6859 /* UIButton+AS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+AS.swift"; sourceTree = "<group>"; };
+		3DBEA1572DE6EC9A000C6859 /* UIView+AS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+AS.swift"; sourceTree = "<group>"; };
+		3DBEA1592DE6EDED000C6859 /* UIViewController+AS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+AS.swift"; sourceTree = "<group>"; };
+		3DBEA15B2DE6EEB9000C6859 /* UIImageView+AS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageView+AS.swift"; sourceTree = "<group>"; };
+		3DBEA15D2DE6F004000C6859 /* UIFont+AS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+AS.swift"; sourceTree = "<group>"; };
+		3DBEA15F2DE6F31B000C6859 /* GlobalImports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalImports.swift; sourceTree = "<group>"; };
+		3DBEA1632DE6F390000C6859 /* ASRandomTextTool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASRandomTextTool.h; sourceTree = "<group>"; };
+		3DBEA1642DE6F390000C6859 /* ASRandomTextTool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASRandomTextTool.m; sourceTree = "<group>"; };
+		3DBEA1662DE6F439000C6859 /* ASCustomAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASCustomAlert.swift; sourceTree = "<group>"; };
+		3DBEA1682DE6F4F2000C6859 /* ASColObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASColObserver.h; sourceTree = "<group>"; };
+		3DBEA1692DE6F4F2000C6859 /* ASColObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASColObserver.m; sourceTree = "<group>"; };
+		3DBEA1702DE6F78D000C6859 /* ASWindTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASWindTool.swift; sourceTree = "<group>"; };
+		3DBEA1722DE6F8D3000C6859 /* ASFileManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ASFileManager.h; sourceTree = "<group>"; };
+		3DBEA1732DE6F8D3000C6859 /* ASFileManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ASFileManager.m; sourceTree = "<group>"; };
+		3DBEA1752DE6FB0A000C6859 /* ASFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASFileManager.swift; sourceTree = "<group>"; };
+		3DBEA1772DE6FC59000C6859 /* ASTLLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASTLLabel.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>"; };
@@ -328,6 +314,18 @@
 		3DB4D4AD2DDDCED00082596A /* Ex */ = {
 			isa = PBXGroup;
 			children = (
+				3DBEA11C2DE6B229000C6859 /* NSString+AS.h */,
+				3DBEA11D2DE6B229000C6859 /* NSString+AS.m */,
+				3DBEA1232DE6B36D000C6859 /* UIColor+AS.h */,
+				3DBEA1242DE6B36D000C6859 /* UIColor+AS.m */,
+				3DBEA1492DE6E731000C6859 /* UIViewController+CustomAlert.h */,
+				3DBEA14A2DE6E731000C6859 /* UIViewController+CustomAlert.m */,
+				3DBEA14C2DE6E89B000C6859 /* UILabel+AS.swift */,
+				3DBEA1502DE6EA87000C6859 /* UIButton+AS.swift */,
+				3DBEA1572DE6EC9A000C6859 /* UIView+AS.swift */,
+				3DBEA1592DE6EDED000C6859 /* UIViewController+AS.swift */,
+				3DBEA15B2DE6EEB9000C6859 /* UIImageView+AS.swift */,
+				3DBEA15D2DE6F004000C6859 /* UIFont+AS.swift */,
 			);
 			path = Ex;
 			sourceTree = "<group>";
@@ -340,61 +338,6 @@
 			path = ASTutorialsVC;
 			sourceTree = "<group>";
 		};
-		3DBEA0822DE69B2E000C6859 /* SwiftUI */ = {
-			isa = PBXGroup;
-			children = (
-				3DBEA07F2DE69B2E000C6859 /* Color+Ex.swift */,
-				3DBEA0802DE69B2E000C6859 /* Font+Ex.swift */,
-				3DBEA0812DE69B2E000C6859 /* Text+Ex.swift */,
-			);
-			path = SwiftUI;
-			sourceTree = "<group>";
-		};
-		3DBEA09B2DE69B2E000C6859 /* Ex */ = {
-			isa = PBXGroup;
-			children = (
-				3DBEA11B2DE6B1F3000C6859 /* OC */,
-				3DBEA0822DE69B2E000C6859 /* SwiftUI */,
-				3DBEA0832DE69B2E000C6859 /* Array+Ex.swift */,
-				3DBEA0862DE69B2E000C6859 /* CGFloat+Ex.swift */,
-				3DBEA0872DE69B2E000C6859 /* Date+Ex.swift */,
-				3DBEA08A2DE69B2E000C6859 /* NSString+Ex.swift */,
-				3DBEA08C2DE69B2E000C6859 /* UIButton+Ex.swift */,
-				3DBEA08D2DE69B2E000C6859 /* UIColor+Ex.swift */,
-				3DBEA08F2DE69B2E000C6859 /* UIFont+Ex.swift */,
-				3DBEA0902DE69B2E000C6859 /* UIImage+Ex.swift */,
-				3DBEA0912DE69B2E000C6859 /* UIImageView+Ex.swift */,
-				3DBEA0922DE69B2E000C6859 /* UILabel+Ex.swift */,
-				3DBEA0962DE69B2E000C6859 /* UIView+Ex.swift */,
-				3DBEA0972DE69B2E000C6859 /* UIView+Frame.swift */,
-				3DBEA0982DE69B2E000C6859 /* UIView+Rotating.swift */,
-				3DBEA0992DE69B2E000C6859 /* UIViewController+Ex.swift */,
-			);
-			path = Ex;
-			sourceTree = "<group>";
-		};
-		3DBEA09D2DE69B2E000C6859 /* GlobalImports */ = {
-			isa = PBXGroup;
-			children = (
-				3DBEA1262DE6BA96000C6859 /* GlobalMacros.h */,
-				3DBEA09C2DE69B2E000C6859 /* GlobalImports.swift */,
-			);
-			path = GlobalImports;
-			sourceTree = "<group>";
-		};
-		3DBEA0B02DE69B2E000C6859 /* Tool */ = {
-			isa = PBXGroup;
-			children = (
-				3DBEA0A22DE69B2E000C6859 /* TSRandomTextTool.swift */,
-				3DBEA0A62DE69B2E000C6859 /* TSBusinessFileManager.swift */,
-				3DBEA0A72DE69B2E000C6859 /* TSCollectionViewObserver.swift */,
-				3DBEA0A82DE69B2E000C6859 /* TSCustomAlertController.swift */,
-				3DBEA0AA2DE69B2E000C6859 /* TSFileManagerTool.swift */,
-				3DBEA0AF2DE69B2E000C6859 /* WindowHelper.swift */,
-			);
-			path = Tool;
-			sourceTree = "<group>";
-		};
 		3DBEA0B22DE69B2E000C6859 /* TSPlaceholderTextView */ = {
 			isa = PBXGroup;
 			children = (
@@ -430,7 +373,6 @@
 		3DBEA0C52DE69B2E000C6859 /* View */ = {
 			isa = PBXGroup;
 			children = (
-				3DBEA1112DE6A3A6000C6859 /* TopLeftLabel.swift */,
 				3DBEA0B22DE69B2E000C6859 /* TSPlaceholderTextView */,
 				3DBEA0B62DE69B2E000C6859 /* TSReusableCollectionView */,
 				3DBEA0B82DE69B2E000C6859 /* TSSaveSuccessTool */,
@@ -442,9 +384,6 @@
 		3DBEA0C72DE69B2E000C6859 /* Classes */ = {
 			isa = PBXGroup;
 			children = (
-				3DBEA09B2DE69B2E000C6859 /* Ex */,
-				3DBEA09D2DE69B2E000C6859 /* GlobalImports */,
-				3DBEA0B02DE69B2E000C6859 /* Tool */,
 				3DBEA0C52DE69B2E000C6859 /* View */,
 			);
 			path = Classes;
@@ -468,17 +407,6 @@
 			path = CustomTabBarController;
 			sourceTree = "<group>";
 		};
-		3DBEA11B2DE6B1F3000C6859 /* OC */ = {
-			isa = PBXGroup;
-			children = (
-				3DBEA11C2DE6B229000C6859 /* NSString+AS.h */,
-				3DBEA11D2DE6B229000C6859 /* NSString+AS.m */,
-				3DBEA1232DE6B36D000C6859 /* UIColor+AS.h */,
-				3DBEA1242DE6B36D000C6859 /* UIColor+AS.m */,
-			);
-			path = OC;
-			sourceTree = "<group>";
-		};
 		3DBEA1392DE6DBE6000C6859 /* BaseClass */ = {
 			isa = PBXGroup;
 			children = (
@@ -575,6 +503,9 @@
 		A800FEAF2DDAC0E9009DABDC /* CommonView */ = {
 			isa = PBXGroup;
 			children = (
+				3DBEA1772DE6FC59000C6859 /* ASTLLabel.swift */,
+				3DBEA1662DE6F439000C6859 /* ASCustomAlert.swift */,
+				3DBEA14E2DE6E912000C6859 /* ASTouchBtn.swift */,
 				3DB4D4B12DDF0B940082596A /* FakeBlurView.swift */,
 				3DCD573A2DDB4E5E004AAB5B /* ASPageNullView.swift */,
 				3DCD572E2DDB1D87004AAB5B /* ASRingLoadingView.swift */,
@@ -672,6 +603,8 @@
 		A848F88F2DD6D4E800B746EC /* Common */ = {
 			isa = PBXGroup;
 			children = (
+				3DBEA1262DE6BA96000C6859 /* GlobalMacros.h */,
+				3DBEA15F2DE6F31B000C6859 /* GlobalImports.swift */,
 				3DBEA1392DE6DBE6000C6859 /* BaseClass */,
 				3DB4D4AD2DDDCED00082596A /* Ex */,
 				3DCD57172DDB1158004AAB5B /* TSBandRingTool */,
@@ -682,6 +615,14 @@
 				A848F8F92DD7536300B746EC /*  Notification+Ex.swift */,
 				A848F89D2DD6D59C00B746EC /* TSNetWork */,
 				A848F8902DD6D4FD00B746EC /* Common.swift */,
+				3DBEA1632DE6F390000C6859 /* ASRandomTextTool.h */,
+				3DBEA1642DE6F390000C6859 /* ASRandomTextTool.m */,
+				3DBEA1682DE6F4F2000C6859 /* ASColObserver.h */,
+				3DBEA1692DE6F4F2000C6859 /* ASColObserver.m */,
+				3DBEA1702DE6F78D000C6859 /* ASWindTool.swift */,
+				3DBEA1722DE6F8D3000C6859 /* ASFileManager.h */,
+				3DBEA1732DE6F8D3000C6859 /* ASFileManager.m */,
+				3DBEA1752DE6FB0A000C6859 /* ASFileManager.swift */,
 			);
 			path = Common;
 			sourceTree = "<group>";
@@ -1012,17 +953,21 @@
 				A848F8CA2DD6E82B00B746EC /* APRingTonesVC+StackView.swift in Sources */,
 				A848F8C22DD6E70000B746EC /* APRingTonesVC+Duration.swift in Sources */,
 				A848F8A42DD6D67000B746EC /* APRingTonesVC.swift in Sources */,
+				3DBEA15C2DE6EEBC000C6859 /* UIImageView+AS.swift in Sources */,
 				A848F8BD2DD6E38900B746EC /* ASLeftHeaderView.swift in Sources */,
 				A848F8D82DD71A3A00B746EC /* ASRingGenerateSecModel.swift in Sources */,
 				3DB4D4A32DDC34100082596A /* ASRTRFileView.swift in Sources */,
+				3DBEA1652DE6F390000C6859 /* ASRandomTextTool.m in Sources */,
 				A848F8E82DD74DFD00B746EC /* ASDBHistoryManager.swift in Sources */,
 				A848F89E2DD6D59C00B746EC /* TSNetWork+Business.swift in Sources */,
 				3DB4D4B52DE025920082596A /* ASTutorialsVC.swift in Sources */,
 				A848F8AB2DD6D75300B746EC /* ASMyRingVC.swift in Sources */,
 				A848F89F2DD6D59C00B746EC /* TSNetworkManager.swift in Sources */,
 				A848F8E32DD7286A00B746EC /* ASGenerateStyleModel.swift in Sources */,
+				3DBEA1782DE6FC66000C6859 /* ASTLLabel.swift in Sources */,
 				3DCD57052DDB1120004AAB5B /* TSPurchaseTool.swift in Sources */,
 				3DB4D4992DDC28E70082596A /* APAudioToRingVC+StackView.swift in Sources */,
+				3DBEA15A2DE6EDF1000C6859 /* UIViewController+AS.swift in Sources */,
 				3DBEA11E2DE6B229000C6859 /* NSString+AS.m in Sources */,
 				3DCD56F52DDAE42A004AAB5B /* ASViewTool.swift in Sources */,
 				3DBEA1462DE6E31C000C6859 /* APSettingModel.swift in Sources */,
@@ -1030,6 +975,7 @@
 				A800FEBD2DDACCD4009DABDC /* ASRingGeneratorBaseVC.swift in Sources */,
 				A800FEB62DDAC764009DABDC /* ASGeneratorErrorView.swift in Sources */,
 				3DB4D4A82DDC92560082596A /* ASBusinessWebVC.swift in Sources */,
+				3DBEA1602DE6F322000C6859 /* GlobalImports.swift in Sources */,
 				A800FEB82DDAC826009DABDC /* TSNetWork+Error.swift in Sources */,
 				A848F8FA2DD7536700B746EC /*  Notification+Ex.swift in Sources */,
 				A848F8C02DD6E6FA00B746EC /* APRingTonesVC+TextView.swift in Sources */,
@@ -1038,10 +984,12 @@
 				3DCD57312DDB2A66004AAB5B /* ASGenerateRingToRingOperation.swift in Sources */,
 				A848F8EA2DD74E3A00B746EC /* ASDBActionInfoModel.swift in Sources */,
 				3DCD573D2DDB5A3C004AAB5B /* ASMyRingCell.swift in Sources */,
+				3DBEA1672DE6F445000C6859 /* ASCustomAlert.swift in Sources */,
 				3DBEA11A2DE6B086000C6859 /* CustomTabBarController.m in Sources */,
 				A848F8B32DD6D82300B746EC /* APConfig.swift in Sources */,
 				A848F8FC2DD753A000B746EC /* ASProgressState.swift in Sources */,
 				A848F8A92DD6D74A00B746EC /* APAudioToRingVC.swift in Sources */,
+				3DBEA16A2DE6F4F2000C6859 /* ASColObserver.m in Sources */,
 				A848F8AD2DD6D75900B746EC /* APSettingVC.swift in Sources */,
 				3DBEA1442DE6E018000C6859 /* ASBaseViewController.m in Sources */,
 				A848F8912DD6D50000B746EC /* Common.swift in Sources */,
@@ -1050,6 +998,8 @@
 				3DCD571A2DDB1158004AAB5B /* ExtAudioConverter.m in Sources */,
 				3DBEA1402DE6DD18000C6859 /* ASNormalNavigationBarView.m in Sources */,
 				3DCD571B2DDB1158004AAB5B /* AudioConverter.m in Sources */,
+				3DBEA1742DE6F8D3000C6859 /* ASFileManager.m in Sources */,
+				3DBEA14D2DE6E8AB000C6859 /* UILabel+AS.swift in Sources */,
 				3DB4D4932DDC25C10082596A /* APAudioToRingVM.swift in Sources */,
 				3DCD571C2DDB1158004AAB5B /* ZHCroppedDelegate.swift in Sources */,
 				3DCD571D2DDB1158004AAB5B /* ZHAudioProcessing.swift in Sources */,
@@ -1062,11 +1012,14 @@
 				A800FEBB2DDACAF3009DABDC /* ASRingGeneratorVC.swift in Sources */,
 				A848F8F32DD7528D00B746EC /* ASBaseOperation.swift in Sources */,
 				A848F8BB2DD6E30600B746EC /* APRingTonesVM.swift in Sources */,
+				3DBEA1712DE6F794000C6859 /* ASWindTool.swift in Sources */,
 				3DB4D49B2DDC28F20082596A /* APAudioToRingVC+Upload.swift in Sources */,
 				3DBEA1272DE6BA99000C6859 /* GlobalMacros.h in Sources */,
 				3DB4D4B22DDF0B960082596A /* FakeBlurView.swift in Sources */,
 				3DCD56F32DDAE3E3004AAB5B /* ASRingToneCellView.swift in Sources */,
+				3DBEA15E2DE6F008000C6859 /* UIFont+AS.swift in Sources */,
 				3DCD56FF2DDAFC1B004AAB5B /* ASBusinessFileManager.swift in Sources */,
+				3DBEA1762DE6FB18000C6859 /* ASFileManager.swift in Sources */,
 				A848F8C42DD6E70500B746EC /* APRingTonesVC+Style.swift in Sources */,
 				A848F8F82DD752E700B746EC /* ASGenerateTextToRingOperation.swift in Sources */,
 				3DBEA1102DE6A04B000C6859 /* SimpleWebViewController.m in Sources */,
@@ -1074,8 +1027,10 @@
 				A848F8EC2DD74EF800B746EC /* ASActionInfoModel.swift in Sources */,
 				A848F8F62DD752D700B746EC /* ASGenerateBaseOperation.swift in Sources */,
 				3DB4D4A52DDC8E830082596A /* APSettingVC+Col.swift in Sources */,
+				3DBEA1582DE6ECA8000C6859 /* UIView+AS.swift in Sources */,
 				A848F8EE2DD7508300B746EC /* ASRealmManager.swift in Sources */,
 				A848F8B52DD6D83E00B746EC /* APConfig+Color.swift in Sources */,
+				3DBEA14F2DE6E926000C6859 /* ASTouchBtn.swift in Sources */,
 				A848F8B92DD6DF7900B746EC /* ASAppBtnView.swift in Sources */,
 				3DBEA1342DE6D862000C6859 /* ASBaseCollectionReusableView.m in Sources */,
 				3DCD56FD2DDAFBE5004AAB5B /* ASDownloadManager.swift in Sources */,
@@ -1087,39 +1042,16 @@
 				A848F8D22DD7149D00B746EC /* ASDurationColView.swift in Sources */,
 				A848F8C62DD6E72D00B746EC /* APRingTonesVC+View.swift in Sources */,
 				A848F8862DD6D1AF00B746EC /* AppDelegate.swift in Sources */,
-				3DBEA0CB2DE69B2E000C6859 /* UIImage+Ex.swift in Sources */,
-				3DBEA0CC2DE69B2E000C6859 /* TSBusinessFileManager.swift in Sources */,
 				3DBEA0CD2DE69B2E000C6859 /* TSSaveSuccessTool.swift in Sources */,
 				3DBEA0CE2DE69B2E000C6859 /* TSSimpleCollectionView.swift in Sources */,
-				3DBEA0CF2DE69B2E000C6859 /* WindowHelper.swift in Sources */,
-				3DBEA0D22DE69B2E000C6859 /* Array+Ex.swift in Sources */,
 				3DBEA1312DE6D825000C6859 /* ASBaseCollectionCell.m in Sources */,
-				3DBEA0D92DE69B2E000C6859 /* UIImageView+Ex.swift in Sources */,
-				3DBEA0E12DE69B2E000C6859 /* Color+Ex.swift in Sources */,
-				3DBEA0E82DE69B2E000C6859 /* UIView+Ex.swift in Sources */,
-				3DBEA0EA2DE69B2E000C6859 /* UIView+Rotating.swift in Sources */,
 				3DBEA12B2DE6BCE3000C6859 /* ASBaseNavigationController.m in Sources */,
-				3DBEA0EB2DE69B2E000C6859 /* Text+Ex.swift in Sources */,
-				3DBEA0EC2DE69B2E000C6859 /* UILabel+Ex.swift in Sources */,
-				3DBEA0EF2DE69B2E000C6859 /* UIColor+Ex.swift in Sources */,
-				3DBEA0F02DE69B2E000C6859 /* Font+Ex.swift in Sources */,
-				3DBEA0F12DE69B2E000C6859 /* TSFileManagerTool.swift in Sources */,
-				3DBEA0F32DE69B2E000C6859 /* TSRandomTextTool.swift in Sources */,
-				3DBEA0F62DE69B2E000C6859 /* TSCustomAlertController.swift in Sources */,
-				3DBEA0FC2DE69B2E000C6859 /* UIFont+Ex.swift in Sources */,
-				3DBEA0FE2DE69B2E000C6859 /* UIButton+Ex.swift in Sources */,
+				3DBEA1562DE6EBAD000C6859 /* UIButton+AS.swift in Sources */,
 				3DBEA0FF2DE69B2E000C6859 /* TSCustomStackView.swift in Sources */,
 				3DBEA1362DE6D9A3000C6859 /* ASBaseModel.swift in Sources */,
-				3DBEA1002DE69B2E000C6859 /* UIViewController+Ex.swift in Sources */,
-				3DBEA1012DE69B2E000C6859 /* Date+Ex.swift in Sources */,
-				3DBEA1032DE69B2E000C6859 /* NSString+Ex.swift in Sources */,
+				3DBEA14B2DE6E731000C6859 /* UIViewController+CustomAlert.m in Sources */,
 				3DBEA1252DE6B36D000C6859 /* UIColor+AS.m in Sources */,
-				3DBEA1062DE69B2E000C6859 /* GlobalImports.swift in Sources */,
 				3DBEA1072DE69B2E000C6859 /* TSPlaceholderTextView.swift in Sources */,
-				3DBEA1082DE69B2E000C6859 /* UIView+Frame.swift in Sources */,
-				3DBEA1122DE6A3AA000C6859 /* TopLeftLabel.swift in Sources */,
-				3DBEA1092DE69B2E000C6859 /* CGFloat+Ex.swift in Sources */,
-				3DBEA10B2DE69B2E000C6859 /* TSCollectionViewObserver.swift in Sources */,
 				3DB4D4912DDC1F100082596A /* ASRingGeneratorVC+load.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 7 - 0
AIPlayRingtones/AIPlayRingtones-Bridging-Header.h

@@ -15,3 +15,10 @@
 #import "ASBaseNavContentBarView.h"
 #import "ASNormalNavigationBarView.h"
 #import "ASBaseViewController.h"
+#import "UIViewController+CustomAlert.h"
+#import "NSString+AS.h"
+#import "UIColor+AS.h"
+#import "GlobalMacros.h"
+#import "ASRandomTextTool.h"
+#import "ASColObserver.h"
+#import "ASFileManager.h"

+ 4 - 10
AIPlayRingtones/APConfig/APConfig+Color.swift

@@ -6,22 +6,16 @@
 //
 
 extension UIColor {
-    /// 背景色
-    static let mainBg = "#111018".uiColor
-    
     /// 主色调
     static let themeColor = "#B48EFF".uiColor
-    
+    /// 背景色
+    static let mainBg = "#111018".uiColor
     /// 弹窗色
     static let popupColor = "#222222".uiColor
-    
     /// 主要文字
     static let mainText = UIColor.white
-    
-    /// 辅助文字
-    static let textAssist = UIColor.fromHex("#FFFFFF", alpha: 0.4)
-    
     /// 卡片色
     static let cardColor = "#202030".uiColor
-
+    /// 辅助文字
+    static let textAssist = UIColor.white.withAlphaComponent(0.4)
 }

+ 1 - 1
AIPlayRingtones/AppDelegate.swift

@@ -52,7 +52,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
 
     func initPlatform() {
         DispatchQueue.main.async {//先提前调用,启动下数据库.
-            debugPrint("ASRMShared.ringDBHistory.istModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
+            logPrint("ASRMShared.ringDBHistory.istModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
         }
 
     }

+ 2 - 2
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift

@@ -71,8 +71,8 @@ extension APAudioToRingVC : UIDocumentPickerDelegate {
         
         // 3. 处理选中的音频文件
         print("选中的音频文件路径:", selectedFileURL.path)
-        let cacheDirectory = TSFileManagerTool.cacheDirectory.appendingPathComponent(selectedFileURL.lastPathComponent)
-        TSFileManagerTool.copyFileWithOverwrite(from: selectedFileURL, to: cacheDirectory)
+        let cacheDirectory = ASFileManager.cacheDirectory().appendingPathComponent(selectedFileURL.lastPathComponent)
+        ASFileManager.copyFileWithOverwrite(from: selectedFileURL, to: cacheDirectory)
         viewModel.ringFilePath = cacheDirectory
         fileView.filePath = cacheDirectory
     }

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

@@ -8,7 +8,7 @@
 extension APAudioToRingVC {
     
 //    func creatVipBtn()->UIButton{
-//        let vipBtn = UIButton.createButton(image: UIImage(named: "nav_vip")) { [weak self] in
+//        let vipBtn = UIButton.createBtn(image: UIImage(named: "nav_vip")) { [weak self] in
 //            guard let self = self else { return }
 //            TSPurchaseVC.show(target: self) {}
 //        }
@@ -18,7 +18,7 @@ extension APAudioToRingVC {
     func creatNavBarView()->ASBaseNavContentBarView{
         let navBarView = ASBaseNavContentBarView()
 
-        let titleImageView = UIImageView.createImageView(imageName: "nav_title_aiRingtone", contentMode: .scaleToFill)
+        let titleImageView = UIImageView.createImageV(imageName: "nav_title_aiRingtone", contentMode: .scaleToFill)
         navBarView.barView.addSubview(titleImageView)
         titleImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()
@@ -51,7 +51,7 @@ extension APAudioToRingVC {
     
     func creatCreatBtnView() -> ASAppBtnView{
         let creatBtnView = ASAppBtnView()
-        creatBtnView.setUpButton(style: .generate) { [weak self] in
+        creatBtnView.setUpBtn(style: .generate) { [weak self] in
             guard let self = self else { return }
             generateAI()
         }

+ 1 - 1
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift

@@ -13,7 +13,7 @@ class APAudioToRingVC: ASBaseViewController {
     lazy var navBarView: ASBaseNavContentBarView = {
         let navBarView = ASBaseNavContentBarView()
         
-        let titleImageView = UIImageView.createImageView(imageName: "nav_title_audioRingtone", contentMode: .scaleToFill)
+        let titleImageView = UIImageView.createImageV(imageName: "nav_title_audioRingtone", contentMode: .scaleToFill)
         navBarView.barView.addSubview(titleImageView)
         titleImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()

+ 4 - 4
AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift

@@ -13,7 +13,7 @@ class ASRTRFileUploadView: ASBaseView {
     var clickComplete:(()->Void)?
     var clickPlayComplete:(()->Void)?
     lazy var imageView: UIImageView = {
-        let imageView = UIImageView.createImageView(image: .uploadFileIcon)
+        let imageView = UIImageView.createImageV(image: .uploadFileIcon)
         return imageView
     }()
     
@@ -23,7 +23,7 @@ class ASRTRFileUploadView: ASBaseView {
     }()
     
     lazy var btn: UIButton = {
-        let imageView = UIButton.createButton(image: .uploadFileAdd)
+        let imageView = UIButton.createBtn(image: .uploadFileAdd)
         { [weak self]  in
             guard let self = self else { return }
             clickComplete?()
@@ -97,7 +97,7 @@ class ASRTRFileplayView: ASBaseView {
     }()
     
     lazy var btn: UIButton = {
-        let imageView = UIButton.createButton(image: .uploadFileChange){ [weak self]  in
+        let imageView = UIButton.createBtn(image: .uploadFileChange){ [weak self]  in
             guard let self = self else { return }
             clickComplete?()
         }
@@ -152,7 +152,7 @@ class ASRTRFileView: ASBaseView {
             if let filePath = filePath {
                 if let info = TSBusinessAudioPlayer.getAudioFileInfo(path: filePath.path()){
                     playView.ringView.nameLab.text = info.songName
-                    playView.ringView.timeLab.text = Float(info.durationInSeconds ?? 0).floatToMinuteSecond()
+                    playView.ringView.timeLab.text = Float(info.durationInSeconds ?? 0).timeMMSS
                 }
             }
         }

+ 4 - 4
AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRStyleView.swift

@@ -34,7 +34,7 @@ class ASRTRStyleView: ASBaseView {
         }
     }
 
-    private var collectionViewObserver: TSCollectionViewObserver!
+    private var collectionViewObserver: ASColObserver!
     lazy var colView: TSSimpleCollectionView = {
         let identifier = "ASRTRStyleViewCell"
 
@@ -67,7 +67,7 @@ class ASRTRStyleView: ASBaseView {
     override func dealThings() {
 
         // 监听collectionView 的 contentSize
-        collectionViewObserver = TSCollectionViewObserver(collectionView: colView.collectionView)
+        collectionViewObserver = ASColObserver(collectionView: colView.collectionView)
         collectionViewObserver.onContentSizeChange = { [weak self] size in
             guard let self = self else { return }
             print("collectionViewObserver 内容大小变化: \(size)")
@@ -117,7 +117,7 @@ class ASRTRStyleViewCell: ASBaseCollectionCell ,TSSimpleConfigurableView {
     }
 
     lazy var boardImageView: UIImageView = {
-        let boardImageView = UIImageView()//.createImageView(image: .ringTextSelectedBoard)
+        let boardImageView = UIImageView()//.createImageV(image: .ringTextSelectedBoard)
         boardImageView.isHidden = true
         
         DispatchQueue.main.async {
@@ -134,7 +134,7 @@ class ASRTRStyleViewCell: ASBaseCollectionCell ,TSSimpleConfigurableView {
     }()
     
     lazy var proImageView:UIImageView = {
-        let proImageView = UIImageView.createImageView(image: .PRO)
+        let proImageView = UIImageView.createImageV(image: .PRO)
         return proImageView
     }()
     

+ 5 - 5
AIPlayRingtones/AppPage/APLaunchVC/APLaunchVC.swift

@@ -71,10 +71,10 @@ class ASLaunchVC: UIViewController {
                     
                     guard UIApplication.shared.applicationState == .active
                     else {
-                        dePrint("倒计时:!= active")
+                        logPrint("倒计时:!= active")
                         maxTime += 1
                         if maxTime > 30 {
-                            dePrint("超过最大倒计时进入 app")
+                            logPrint("超过最大倒计时进入 app")
                             self.timer?.cancel()
                             self.timer = nil
                             self.enterApp()
@@ -84,7 +84,7 @@ class ASLaunchVC: UIViewController {
                     }
                     
                     self.remindTimeInterval -= 0.2
-                    dePrint("倒计时:\(self.remindTimeInterval)")
+                    logPrint("倒计时:\(self.remindTimeInterval)")
                     if self.remindTimeInterval <= 0 {
                         self.timer?.cancel()
                         self.timer = nil
@@ -105,13 +105,13 @@ class ASLaunchVC: UIViewController {
         // 获取 LaunchScreen.storyboard 的视图控制器
         let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
         guard let launchVC = storyboard.instantiateInitialViewController() else {
-            debugPrint("无法加载 LaunchScreen 的初始视图控制器")
+            logPrint("无法加载 LaunchScreen 的初始视图控制器")
             return
         }
 
         // 获取 LaunchScreen 的视图
         guard let launchView = launchVC.view else {
-            debugPrint("无法获取 LaunchScreen 的视图")
+            logPrint("无法获取 LaunchScreen 的视图")
             return
         }
 

+ 9 - 9
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift

@@ -60,7 +60,7 @@ class ASMyRingCell: SwipeCollectionViewCell  {
                     let gennerateOperation = ASGenerateTextToRingOperationQueue.shared.creatOperation(uuid: oldModel.uuid)
                     gennerateOperation.isSaveProcessToDB = true
                     gennerateOperation.creatRing(oldModel: oldModel) { success in }
-//                    dePrint("\(self.indexPath.item),刷新进度发self.operation=\(gennerateOperation)")
+//                    logPrint("\(self.indexPath.item),刷新进度发self.operation=\(gennerateOperation)")
                     modelDidSet()
                 }
             }else if oldModel.modelType == .rtr {
@@ -94,14 +94,14 @@ class ASMyRingCell: SwipeCollectionViewCell  {
         }
         
         kDelayMainShort {
-            exampleView.makeCorner([.topLeft,.bottomLeft], radius: 10)
+            exampleView.maskCorner([.topLeft,.bottomLeft], radius: 10)
         }
         return exampleView
     }()
     
     
     lazy var vipView: UIImageView = {
-        let vipView = UIImageView.createImageView(imageName: "ring_vip")
+        let vipView = UIImageView.createImageV(imageName: "ring_vip")
         vipView.isHidden = true
         return vipView
     }()
@@ -161,7 +161,7 @@ extension ASMyRingCell {
     
     var currentOperation:ASGenerateBaseOperation?{
         guard let model = model else { return nil }
-//        dePrint("\(self.indexPath.item),刷新进度真self.uuid=\(model.uuid)")
+//        logPrint("\(self.indexPath.item),刷新进度真self.uuid=\(model.uuid)")
         if model.modelType == .ttr {
             return ASGenerateTextToRingOperationQueue.shared.findOperation(uuid: model.uuid)
         }else if model.modelType == .rtr {
@@ -174,7 +174,7 @@ extension ASMyRingCell {
         
         //处理model数据
         updataActionInfoModelView(model: model)
-        dePrint("\(self.indexPath.item),model actionStatus 收到=\(model.actionStatus)")
+        logPrint("\(self.indexPath.item),model actionStatus 收到=\(model.actionStatus)")
         
         //处理生成任务
         if let rintoneOperation = currentOperation {
@@ -185,13 +185,13 @@ extension ASMyRingCell {
                 }
                 handleStateDataPblishedChanged(state: state, actionInfoModel: actionInfoModel)
             }
-            dePrint("\(self.indexPath.item),刷新进度真handleStateDataPblishedChanged=\(rintoneOperation.stateDatauPblished)")
+            logPrint("\(self.indexPath.item),刷新进度真handleStateDataPblishedChanged=\(rintoneOperation.stateDatauPblished)")
             handleStateDataPblishedChanged(state: rintoneOperation.stateDatauPblished.0, actionInfoModel: rintoneOperation.stateDatauPblished.1)
         }
 
         //处理播放进度
         if playSelf{
-            dePrint("\(self.indexPath.item),playSelf")
+            logPrint("\(self.indexPath.item),playSelf")
             setPlayerStateChangedHandle()
         }else{
             changePlayerState(state: .stop)
@@ -202,7 +202,7 @@ extension ASMyRingCell {
         
         TSBusinessAudioPlayer.shared.stateChangedHandle = { [weak self] playerState in
             guard let self = self else { return }
-            dePrint("\(self.indexPath.item),stateChangedHandle self=\(self)")
+            logPrint("\(self.indexPath.item),stateChangedHandle self=\(self)")
             
             if playSelf {
                 self.changePlayerState(state: playerState)
@@ -275,7 +275,7 @@ extension ASMyRingCell {
         case .success:
             generateView.isHidden = true
             
-            ringView.timeLab.text = Float(model.response.duration).floatToMinuteSecond()
+            ringView.timeLab.text = Float(model.response.duration).timeMMSS
             ringView.nameLab.text = model.response.title
             ringView.setCoverImageView(urlString: model.response.coverUrl)
             exampleView.isHidden = model.modelType != .example

+ 8 - 6
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift

@@ -13,13 +13,13 @@ class APMyRingVC: ASBaseViewController {
     lazy var navBarView: ASBaseNavContentBarView = {
         let navBarView = ASBaseNavContentBarView()
 
-        let titleImageView = UIImageView.createImageView(imageName: "nav_title_myRingtones", contentMode: .scaleToFill)
+        let titleImageView = UIImageView.createImageV(imageName: "nav_title_myRingtones", contentMode: .scaleToFill)
         navBarView.barView.addSubview(titleImageView)
         titleImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()
         }
         
-//        let vipBtn = UIButton.createButton(image: .aiRintoneIcon) { [weak self] in
+//        let vipBtn = UIButton.createBtn(image: .aiRintoneIcon) { [weak self] in
 //            guard let self = self else { return }
 //      
 //            if let model = dbHistory.listModels.first,model.modelType != 1 {
@@ -93,7 +93,7 @@ class APMyRingVC: ASBaseViewController {
     
     override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
-//        debugPrint("viewWillAppear listModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
+//        logPrint("viewWillAppear listModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
     }
     
     override func viewWillDisappear(_ animated: Bool) {
@@ -120,11 +120,11 @@ class APMyRingVC: ASBaseViewController {
     }
     
     @objc func updateListView(){
-        dePrint("dbHistory.getModelList拿数据前,\(dbHistory.listModels.count))")
+        logPrint("dbHistory.getModelList拿数据前,\(dbHistory.listModels.count))")
         
         dbHistory.getModelList { [weak self] array in
             guard let self = self else { return }
-            dePrint("dbHistory.getModelList拿数据后,\(dbHistory.listModels.count))")
+            logPrint("dbHistory.getModelList拿数据后,\(dbHistory.listModels.count))")
             listModelArray = array
             updateView()
         }
@@ -216,7 +216,9 @@ extension APMyRingVC: SwipeCollectionViewCellDelegate {
                     updateListView()
                     TSBusinessAudioPlayer.shared.stop()
                 }
-            })
+            }) {
+                
+            }
         }
         
         deleteAction.backgroundColor = "#E83E3E".uiColor

+ 5 - 5
AIPlayRingtones/AppPage/APRingTonesVC/APRingStyleVC/APRingStyleVC.swift

@@ -39,7 +39,7 @@ class APRingStyleVC: ASBaseViewController {
         return ptpStyleModels
     }()
     
-    private var collectionViewObserver: TSCollectionViewObserver!
+    private var collectionViewObserver: ASColObserver!
     lazy var colView: TSSimpleCollectionView = {
         let identifier = "APRingStyleCell"
 
@@ -73,7 +73,7 @@ class APRingStyleVC: ASBaseViewController {
     override func dealThings() {
 
         // 监听collectionView 的 contentSize
-        collectionViewObserver = TSCollectionViewObserver(collectionView: colView.collectionView)
+        collectionViewObserver = ASColObserver(collectionView: colView.collectionView)
         collectionViewObserver.onContentSizeChange = { [weak self] size in
             guard let self = self else { return }
             print("collectionViewObserver 内容大小变化: \(size)")
@@ -127,12 +127,12 @@ class APRingStyleCell: ASBaseCollectionCell ,TSSimpleConfigurableView {
     }
     
     lazy var bgImageView: UIImageView = {
-        let bgImageView = UIImageView.createImageView(image: .ringTextUnSelectBg)
+        let bgImageView = UIImageView.createImageV(image: .ringTextUnSelectBg)
         return bgImageView
     }()
     
     lazy var boardImageView: UIImageView = {
-        let boardImageView = UIImageView.createImageView(image: .ringTextSelectedBoard)
+        let boardImageView = UIImageView.createImageV(image: .ringTextSelectedBoard)
         boardImageView.isHidden = true
         return boardImageView
     }()
@@ -144,7 +144,7 @@ class APRingStyleCell: ASBaseCollectionCell ,TSSimpleConfigurableView {
     }()
     
     lazy var proImageView:UIImageView = {
-        let proImageView = UIImageView.createImageView(image: .PRO)
+        let proImageView = UIImageView.createImageV(image: .PRO)
         return proImageView
     }()
     

+ 3 - 3
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC+View.swift

@@ -9,7 +9,7 @@
 extension APRingTonesVC {
     
 //    func creatVipBtn()->UIButton{
-//        let vipBtn = UIButton.createButton(image: UIImage(named: "nav_vip")) { [weak self] in
+//        let vipBtn = UIButton.createBtn(image: UIImage(named: "nav_vip")) { [weak self] in
 //            guard let self = self else { return }
 //            TSPurchaseVC.show(target: self) {}
 //        }
@@ -20,7 +20,7 @@ extension APRingTonesVC {
     func creatNavBarView()->ASBaseNavContentBarView{
         let navBarView = ASBaseNavContentBarView()
 
-        let titleImageView = UIImageView.createImageView(imageName: "nav_title_aiRingtone", contentMode: .scaleToFill)
+        let titleImageView = UIImageView.createImageV(imageName: "nav_title_aiRingtone", contentMode: .scaleToFill)
         navBarView.barView.addSubview(titleImageView)
         titleImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()
@@ -51,7 +51,7 @@ extension APRingTonesVC {
     
     func creatCreatBtnView() -> ASAppBtnView{
         let creatBtnView = ASAppBtnView()
-        creatBtnView.setUpButton(style: .generate) { [weak self] in
+        creatBtnView.setUpBtn(style: .generate) { [weak self] in
             guard let self = self else { return }
             generateAI()
         }

+ 2 - 2
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/View/ASDurationColView.swift

@@ -91,12 +91,12 @@ class ASDurationColViewCell: ASBaseCollectionCell ,TSSimpleConfigurableView {
     }
     
     lazy var proImageView:UIImageView = {
-        let proImageView = UIImageView.createImageView(image: .PRO)
+        let proImageView = UIImageView.createImageV(image: .PRO)
         return proImageView
     }()
     
     lazy var bgImageView: UIImageView = {
-        let bgImageView = UIImageView.createImageView(image: .secUnSelectedBg)
+        let bgImageView = UIImageView.createImageV(image: .secUnSelectedBg)
         return bgImageView
     }()
     

+ 15 - 16
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/View/ASPromptTextView.swift

@@ -22,13 +22,13 @@ class ASPromptTextView : ASBaseView{
     }
     
 
-    lazy var randomTextPicker: TSRandomTextTool = {
-        let textPicker = TSRandomTextTool(texts: randomTextArray)
+    lazy var randomTextPicker: ASRandomTextTool = {
+        let textPicker = ASRandomTextTool(texts: randomTextArray)
         return textPicker
     }()
     
     lazy var boardImageView: UIImageView = {
-        let boardImageView = UIImageView.createImageView(imageName: "textView_board",contentMode: .scaleToFill)
+        let boardImageView = UIImageView.createImageV(imageName: "textView_board",contentMode: .scaleToFill)
         boardImageView.isHidden = true
         return boardImageView
     }()
@@ -36,7 +36,7 @@ class ASPromptTextView : ASBaseView{
     lazy var textBgView: UIView = {
         let textBgView = UIView()
         textBgView.cornerRadius = 16.0
-//        let bgImageView = UIImageView.createImageView(imageName: "textView_bg",contentMode: .scaleToFill)
+//        let bgImageView = UIImageView.createImageV(imageName: "textView_bg",contentMode: .scaleToFill)
 //        textBgView.addSubview(bgImageView)
 //        bgImageView.snp.makeConstraints { make in
 //            make.edges.equalToSuperview()
@@ -50,17 +50,16 @@ class ASPromptTextView : ASBaseView{
         return textBgView
     }()
     
-    lazy var customTextView: TSPlaceholderTextView = {
-        let customTextView = TSPlaceholderTextView(
-            placeholder: "Type your idea here.",
-            text: "",
-            font: .font(size: 14),
-            textColor: .white,
-            backgroundColor: .clear
+    lazy var customTextView: XHInputView = {
+        let customTextView = XHInputView(
+            initialText: "Type your idea here.",
+            textFont: .font(size: 14),
+            contentColor: .white,
+            background: .clear
         )
         customTextView.delegate = self
         customTextView.returnKeyType = .done
-        customTextView.textViewTextChanged = { [weak self]  in
+        customTextView.onTextUpdate = { [weak self]  in
             guard let self = self else { return }
             textViewTextChanged(textView: customTextView)
         }
@@ -69,7 +68,7 @@ class ASPromptTextView : ASBaseView{
     
  
     lazy var inspirationBtn: UIButton = {
-        let inspirationBtn = UIButton.createButton(
+        let inspirationBtn = UIButton.createBtn(
             title: "💡Get Inspired?".localized,
             font: .font(size: 12),
             titleColor: "#F3F0EA".uiColor
@@ -85,9 +84,9 @@ class ASPromptTextView : ASBaseView{
     }()
     
     
-    lazy var clearBtn: ASUIExpandedTouchButton = {
-        let clearBtn = ASUIExpandedTouchButton()
-        clearBtn.setUpButton(image: UIImage(named: "clear_text"))
+    lazy var clearBtn: ASTouchBtn = {
+        let clearBtn = ASTouchBtn()
+        clearBtn.setUpBtn(image: UIImage(named: "clear_text"))
         { [weak self]  in
             guard let self = self else { return }
             customTextView.text = ""

+ 1 - 1
AIPlayRingtones/AppPage/APSettingVC/APSettingVC+Col.swift

@@ -91,7 +91,7 @@ class APSettingCell: ASBaseCollectionCell {
     }
     
     lazy var arrowImageView: UIImageView = {
-        let arrowImageView = UIImageView.createImageView(image: .rightArrowWhite)
+        let arrowImageView = UIImageView.createImageV(image: .rightArrowWhite)
         return arrowImageView
     }()
 

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

@@ -12,7 +12,7 @@ class APSettingVC: ASBaseViewController {
     lazy var navBarView: ASBaseNavContentBarView = {
         let navBarView = ASBaseNavContentBarView()
 
-        let titleImageView = UIImageView.createImageView(imageName: "nav_title_setting", contentMode: .scaleToFill)
+        let titleImageView = UIImageView.createImageV(imageName: "nav_title_setting", contentMode: .scaleToFill)
         navBarView.barView.addSubview(titleImageView)
         titleImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()
@@ -25,7 +25,7 @@ class APSettingVC: ASBaseViewController {
         return cusStackView
     }()
     
-    private var collectionViewObserver: TSCollectionViewObserver!
+    private var collectionViewObserver: ASColObserver!
     lazy var collectionView = creatCollectionView()
     
     
@@ -85,7 +85,7 @@ class APSettingVC: ASBaseViewController {
                    guard let self = self else { return }
                     
                     let httpAppStoreLink = "https://apps.apple.com/app/id\(appid)"
-                    let final = ShareActivityItemProvider(placeholderItem: UIImage(named: "App-Icon")!.compressImageSize(to: CGSize(width: 100, height: 100)))
+                    let final = ShareActivityItemProvider(placeholderItem: UIImage(named: "App-Icon")!.compressSize(to: CGSize(width: 100, height: 100)))
                     let url = URL(string: httpAppStoreLink)!
                     let vc = UIActivityViewController(activityItems: [url, final], applicationActivities: nil)
                     vc.completionWithItemsHandler = { activity, _, _, _ in
@@ -154,7 +154,7 @@ class APSettingVC: ASBaseViewController {
     override func dealThings() {
 
         // 监听collectionView 的 contentSize
-        collectionViewObserver = TSCollectionViewObserver(collectionView: collectionView)
+        collectionViewObserver = ASColObserver(collectionView: collectionView)
         collectionViewObserver.onContentSizeChange = { [weak self] size in
             guard let self = self else { return }
             print("collectionViewObserver 内容大小变化: \(size)")

+ 1 - 1
AIPlayRingtones/AppPage/APSettingVC/ASTutorialsVC/ASTutorialsVC.swift

@@ -18,7 +18,7 @@ class ASTutorialsVC: ASBaseViewController {
     }()
     
     lazy var imageView: UIImageView = {
-        let imageView = UIImageView.createImageView(imageName: "tutorials",contentMode: .scaleToFill)
+        let imageView = UIImageView.createImageV(imageName: "tutorials",contentMode: .scaleToFill)
         
         let imageWidth = imageView.image?.size.width ?? k_ScreenWidth
         let imageHeight = imageView.image?.size.height ?? k_ScreenHeight

+ 1 - 1
AIPlayRingtones/AppPage/ASBusinessWebVC/ASBusinessWebVC.swift

@@ -63,7 +63,7 @@ class ASBusinessWebVC: ASBaseViewController , WKNavigationDelegate {
 
     private func loadURL() {
         guard let url = URL(string: urlType.rawValue) else {
-            debugPrint("无效的 URL")
+            logPrint("无效的 URL")
             return
         }
         let request = URLRequest(url: url)

+ 6 - 4
AIPlayRingtones/AppPage/ASCommonView/ASBtnView/ASAppBtnView.swift

@@ -43,7 +43,7 @@ class ASAppBtnView: ASBaseView {
         
     }
 
-    func setUpButton(style:ViewStyle,btnSize:CGSize = .zero,clickBlock: @escaping () -> Void) {
+    func setUpBtn(style:ViewStyle,btnSize:CGSize = .zero,clickBlock: @escaping () -> Void) {
         self.btnSize = btnSize
         self.style = style
 //        self.vipFreeNumType = vipFreeNumType
@@ -139,7 +139,7 @@ extension ASAppBtnView{
             frame: CGRect(origin: .zero, size: btnSize),
             action: { [weak self]  in
             guard let self = self else { return }
-//            if let vc = WindowHelper.getCurrentViewController() {
+//            if let vc = ASWindTool.getCurrentViewController() {
 //                if kJudgeVip(externalBool: isClickVipBlock?() ?? false, vc: vc) { return }  //判断 vip
 //            }
 
@@ -174,9 +174,11 @@ extension ASAppBtnView{
 func kCreateNormalSubmitBtn(title:String,frame:CGRect,action: (() -> Void)? = nil) -> UIButton {
     let btn = UIButton()
     btn.frame = frame
-    btn.setUpButton(title:title,font: UIFont.font(size: 16,weight: .medium),titleColor:.black,corner: frame.height/2,action: action)
-    btn.setTitleImageSpace(spacing: 8)
+    btn.setUpBtn(title:title,font: UIFont.font(size: 16,weight: .medium),titleColor:.black,corner: frame.height/2,action: action)
 
+    btn.contentEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0) // 只调整 title 的 left
+    btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -8, bottom: 0, right: 0) // 只调整 image 的
+    
     var buttonBgImage = UIImage(named: "submit_btn_bg")!
     buttonBgImage = buttonBgImage.resizableImage(withCapInsets: UIEdgeInsets(top:24, left: 24, bottom: 24, right: 24), resizingMode: .stretch)
     btn.setBackgroundImage(buttonBgImage, for: .normal)

+ 1 - 1
AIPlayRingtones/AppPage/ASCommonView/ASBtnView/ASLeftHeaderView.swift

@@ -47,7 +47,7 @@ extension ASLeftHeaderView {
 //            make.leading.top.bottom.equalTo(0)
 //        }
 //        
-//        let imageView = UIImageView.createImageView(imageName: "gray_right_arrow")
+//        let imageView = UIImageView.createImageV(imageName: "gray_right_arrow")
 //        
 //        moreView.addSubview(imageView)
 //        imageView.snp.makeConstraints { make in

+ 5 - 5
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorBaseVC.swift

@@ -32,7 +32,7 @@ class ASRingGeneratorBaseVC: ASBaseViewController {
     }()
     
 //    lazy var closePageBtn: UIButton = {
-//        let xBtn = UIButton.createButton(image: .pageX) { [weak self]  in
+//        let xBtn = UIButton.createBtn(image: .pageX) { [weak self]  in
 //            guard let self = self else { return }
 //            closePage()
 //        }
@@ -40,8 +40,8 @@ class ASRingGeneratorBaseVC: ASBaseViewController {
 //    }()
     
     lazy var xBtn: UIButton = {
-        let xBtn = ASUIExpandedTouchButton()
-        xBtn.setUpButton(image: UIImage(named: "x")) { [weak self]  in
+        let xBtn = ASTouchBtn()
+        xBtn.setUpBtn(image: UIImage(named: "x")) { [weak self]  in
             guard let self = self else { return }
             clickXBtn()
         }
@@ -50,7 +50,7 @@ class ASRingGeneratorBaseVC: ASBaseViewController {
     
 
     lazy var saveBtn: UIButton = {
-        let saveBtn = UIButton.createButton(title:"Set as Ringtone".localized,backgroundImage:.setAsBg,font: UIFont.font(size: 14,weight: .medium),titleColor:.white)
+        let saveBtn = UIButton.createBtn(title:"Set as Ringtone".localized,backgroundImage:.setAsBg,font: UIFont.font(size: 14,weight: .medium),titleColor:.white)
         { [weak self]  in
             guard let self = self else { return }
             clickSubmitBtn()
@@ -94,7 +94,7 @@ class ASRingGeneratorBaseVC: ASBaseViewController {
  
 //        contentView.addSubview(closePageBtn)
 //        closePageBtn.snp.makeConstraints { make in
-//            make.top.equalTo(4.0+k_Height_StatusBar)
+//            make.top.equalTo(4.0+k_StatusBar_H)
 //            make.leading.equalTo(16.0)
 //            make.width.height.equalTo(36)
 //        }

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

@@ -71,7 +71,7 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
         if progressState.isResult {
             self.dismiss(animated: true, completion: nil)
         }else{
-            TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
+            ASCustomAlert.show(in: self, config: ASCustomAlert.AlertConfig(
                 message: "As you leave, your generation will be interrupted and no result.".localized,
                 messageColor: .white,
                 messageFont: .systemFont(ofSize: 16),
@@ -262,7 +262,7 @@ extension ASRingGeneratorVC{
     }
 
     func setRingViewData(model:ASActionInfoModel) {
-        ringView.timeLab.text = Float(model.request.duration).floatToMinuteSecond()
+        ringView.timeLab.text = Float(model.request.duration).timeMMSS
         ringView.nameLab.text = model.response.title
         ringView.setCoverImageView(urlString: model.response.coverUrl)
     }

+ 4 - 4
AIPlayRingtones/AppPage/CustomTabBarController/CustomTabBarController.m

@@ -29,15 +29,15 @@
     APAudioToRingVC *firstVC = [[APAudioToRingVC alloc] init];
     ASBaseNavigationController *firstNav = [[ASBaseNavigationController alloc] initWithRootViewController:firstVC];
     firstNav.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Create".localized
-                                                        image:[[UIImage imageNamed:@"tabbar_unSelect_audio"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
-                                                selectedImage:[[UIImage imageNamed:@"tabbar_selected_audio"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
+                                                        image:[[UIImage imageNamed:@"tabbar_unSelect_create"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
+                                                selectedImage:[[UIImage imageNamed:@"tabbar_selected_create"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
     
 
     APRingTonesVC *secondVC = [[APRingTonesVC alloc] init];
     ASBaseNavigationController *secondNav = [[ASBaseNavigationController alloc] initWithRootViewController:secondVC];
     secondNav.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Audio".localized
-                                                         image:[[UIImage imageNamed:@"tabbar_unSelect_create"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
-                                                 selectedImage:[[UIImage imageNamed:@"tabbar_selected_create"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
+                                                         image:[[UIImage imageNamed:@"tabbar_unSelect_audio"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]
+                                                 selectedImage:[[UIImage imageNamed:@"tabbar_selected_audio"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
     
     APMyRingVC *thirdVC = [[APMyRingVC alloc] init];
     ASBaseNavigationController *thirdNav = [[ASBaseNavigationController alloc] initWithRootViewController:thirdVC];

+ 0 - 15
AIPlayRingtones/Classes/Ex/Array+Ex.swift

@@ -1,15 +0,0 @@
-//
-//  Array+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-public extension Array {
-    func safeAny(At index: Int) -> Element? {
-        if index >= 0,  index < count {
-            return self[index]
-        }
-        return nil
-    }
-}

+ 0 - 24
AIPlayRingtones/Classes/Ex/CGFloat+Ex.swift

@@ -1,24 +0,0 @@
-//
-//  CGFloat+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/23.
-//
-
-public extension Float {
-    //float 转 分秒
-    func floatToMinuteSecond() -> String {
-        // 将 Float 类型的时间转换为整数秒
-        let totalSeconds = Int(self)
-        // 计算分钟数
-        let minutes = totalSeconds / 60
-        // 计算剩余的秒数
-        let seconds = totalSeconds % 60
-        // 将分钟数和秒数格式化为两位数的字符串
-        let minuteString = String(format: "%02d", minutes)
-        let secondString = String(format: "%02d", seconds)
-        // 拼接成分秒格式的字符串
-        return "\(minuteString):\(secondString)"
-    }
-}
-

+ 0 - 19
AIPlayRingtones/Classes/Ex/Date+Ex.swift

@@ -1,19 +0,0 @@
-//
-//  Date+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-public extension Date {
-    static var hmsString: String {
-        let formatter = DateFormatter()
-        formatter.dateFormat = "HH:mm:ss:SSS"
-        formatter.locale = Locale(identifier: "en")
-        return formatter.string(from: Date())
-    }
-    
-    static var timestampInt: Int {
-        return Int(Date().timeIntervalSince1970)
-    }
-}

+ 0 - 36
AIPlayRingtones/Classes/Ex/NSString+Ex.swift

@@ -1,36 +0,0 @@
-//
-//  NSString+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-import CommonCrypto
-public extension String {
-    
-    var uiColor: UIColor {
-        if isEmpty {
-            return .clear
-        }
-        return UIColor.fromHex(self)
-    }
-    
-    var uiCGColor: CGColor {
-        uiColor.cgColor
-    }
-}
-
-
-public extension String {
-    var md5:String {
-        let data = Data(self.utf8)
-        var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
-        data.withUnsafeBytes {
-            _ = CC_MD5($0.baseAddress, CC_LONG(data.count), &digest)
-        }
-        return digest.map { String(format: "%02x", $0) }.joined()
-    }
-    
-    var localized:String {
-        return NSLocalizedString(self, comment: self)
-    }
-}

+ 0 - 47
AIPlayRingtones/Classes/Ex/SwiftUI/Color+Ex.swift

@@ -1,47 +0,0 @@
-//
-//  Color+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2025/1/14.
-//
-
-import SwiftUI
-
-public extension Color {
-    public static func hex(_ hex: String) -> Color {
-        let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
-        var int: UInt64 = 0
-        Scanner(string: hex).scanHexInt64(&int)
-
-        let a, r, g, b: UInt64
-        switch hex.count {
-        case 3: // RGB (12-bit)
-            (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
-        case 6: // RGB (24-bit)
-            (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
-        case 8: // ARGB (32-bit)
-            (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
-        default:
-            (a, r, g, b) = (255, 0, 0, 0)
-        }
-
-        return Self(
-            .sRGB,
-            red: Double(r) / 255,
-            green: Double(g) / 255,
-            blue: Double(b) / 255,
-            opacity: Double(a) / 255
-        )
-    }
-
-    // 随机生成一个颜色
-    public static var randomColor: Color {
-        // 随机生成 R, G, B 和 alpha(透明度)值
-        let red = Double.random(in: 0 ... 1)
-        let green = Double.random(in: 0 ... 1)
-        let blue = Double.random(in: 0 ... 1)
-        let alpha = Double.random(in: 0.5 ... 1) // 可选,透明度的范围
-
-        return Color(red: red, green: green, blue: blue, opacity: alpha)
-    }
-}

+ 0 - 16
AIPlayRingtones/Classes/Ex/SwiftUI/Font+Ex.swift

@@ -1,16 +0,0 @@
-//
-//  Font+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2025/1/14.
-//
-
-
-import SwiftUI
-public extension Font {
-    static func font(name: FontName = .PingFangSC, size: CGFloat, weight: UIFont.Weight = .regular) -> Font {
-        let uiFont =  UIFont.font(name: name,size: size,weight: weight)
-        return Font(uiFont as CTFont)
-    }
-}
-

+ 0 - 34
AIPlayRingtones/Classes/Ex/SwiftUI/Text+Ex.swift

@@ -1,34 +0,0 @@
-//
-//  Text+Ex.swift
-//  Pods
-//
-//  Created by 100Years on 2025/3/13.
-//
-
-import SwiftUI
-public extension Text {
-    func gradientForeground(colors: [Color], startPoint: UnitPoint, endPoint: UnitPoint) -> some View {
-        self
-            .overlay(
-                LinearGradient(
-                    gradient: Gradient(colors: colors),
-                    startPoint: startPoint,
-                    endPoint: endPoint
-                )
-                .mask(self)
-            )
-    }
-}
-public extension View {
-    func gradientForeground(colors: [Color], startPoint: UnitPoint, endPoint: UnitPoint) -> some View {
-        self
-            .overlay(
-                LinearGradient(
-                    gradient: Gradient(colors: colors),
-                    startPoint: startPoint,
-                    endPoint: endPoint
-                )
-                .mask(self)
-            )
-    }
-}

+ 0 - 144
AIPlayRingtones/Classes/Ex/UIButton+Ex.swift

@@ -1,144 +0,0 @@
-//
-//  UIButton+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-public extension UIButton {
-    
-    private struct AssociatedKeys {
-        static var actionKey = "UIButtonActionKey"
-    }
-
-    // 存储回调闭包
-    private var actionClosure: (() -> Void)? {
-        get {
-            return objc_getAssociatedObject(self, &AssociatedKeys.actionKey) as? (() -> Void)
-        }
-        set {
-            objc_setAssociatedObject(self, &AssociatedKeys.actionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-    
-    
-    
-    /// 快速创建 UIButton
-    /// - Parameters:
-    ///   - title: 按钮的标题
-    ///   - image: 按钮的图标
-    ///   - backgroundImage: 按钮的背景图
-    ///   - backgroundColor: 按钮的背景色
-    ///   - font: 按钮的字体
-    ///   - titleColor: 按钮的字体颜色
-    ///   - action: 按钮点击事件的回调
-    static func createButton(title: String? = nil,
-                             image: UIImage? = nil,
-                             backgroundImage: UIImage? = nil,
-                             backgroundColor: UIColor? = nil,
-                             font: UIFont? = nil,
-                             titleColor: UIColor? = nil,
-                             corner:CGFloat = 0,
-                             action: (() -> Void)? = nil) -> UIButton {
-        let button = UIButton(type: .custom)
-        button.setUpButton(title: title,
-                           image: image,
-                           backgroundImage: backgroundImage,
-                           backgroundColor: backgroundColor,
-                           font: font,
-                           titleColor: titleColor,
-                           corner:corner,
-                           action: action)
-        return button
-    }
-
-    func setUpButton(title: String? = nil,
-                             image: UIImage? = nil,
-                             backgroundImage: UIImage? = nil,
-                             backgroundColor: UIColor? = nil,
-                             font: UIFont? = nil,
-                             titleColor: UIColor? = nil,
-                             corner:CGFloat = 0,
-                             action: (() -> Void)? = nil){
-        let button = self
-        button.showsTouchWhenHighlighted = false
-        button.adjustsImageWhenHighlighted = false
-        // 设置标题
-        if let title = title {
-            button.setTitle(title, for: .normal)
-        }
-        
-        // 设置图片
-        if let image = image {
-            button.setImage(image, for: .normal)
-        }
-        
-        // 设置背景图片
-        if let backgroundImage = backgroundImage {
-            button.setBackgroundImage(backgroundImage, for: .normal)
-        }
-        
-        // 设置背景色
-        if let backgroundColor = backgroundColor {
-            button.backgroundColor = backgroundColor
-        }
-        
-        // 设置字体
-        if let font = font {
-            button.titleLabel?.font = font
-        }
-        
-        // 设置字体颜色
-        if let titleColor = titleColor {
-            button.setTitleColor(titleColor, for: .normal)
-        }
-        
-        if corner > 0 {
-            button.cornerRadius = corner
-        }
-
-        if let action = action {
-            button.actionClosure = action
-            button.addTarget(button, action: #selector(buttonTapped), for: .touchUpInside)
-        }
-
-    }
-    
-    // 按钮点击事件
-    @objc private func buttonTapped() {
-        actionClosure?()
-    }
-    
-    
-
-    public func preventMultipleTaps(delay: Double = 0.75) {
-        self.isEnabled = false
-        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
-            self.isEnabled = true
-        }
-    }
-  
-
-
-}
-
-public extension UIButton {
-    
-    public func setTitleImageSpace(spacing:CGFloat = 4){
-//        titleEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0) // 只调整 title 的 left
-        contentEdgeInsets = UIEdgeInsets(top: 0, left: spacing, bottom: 0, right: 0) // 只调整 title 的 left
-        imageEdgeInsets = UIEdgeInsets(top: 0, left: -spacing, bottom: 0, right: 0) // 只调整 image 的 right
-    }
-    
-}
-public class ASUIExpandedTouchButton: UIButton {
-    public var indexPath: IndexPath = IndexPath(item: 0, section: 0)
-    
-    override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
-        let buttonBounds = self.bounds
-        let widthDelta = self.width * 0.5 // 增加点击区域的比例,这里增加了50%
-        let heightDelta = self.height * 0.5
-        let expandedBounds = buttonBounds.insetBy(dx: -widthDelta, dy: -heightDelta)
-        return expandedBounds.contains(point)
-    }
-}

+ 0 - 49
AIPlayRingtones/Classes/Ex/UIColor+Ex.swift

@@ -1,49 +0,0 @@
-//
-//  UIColor+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-import UIKit
-import SwiftUI
-public extension UIColor {
-    /// 返回一个随机颜色
-    static var random: UIColor {
-        return UIColor(
-            red: CGFloat.random(in: 0...1),
-            green: CGFloat.random(in: 0...1),
-            blue: CGFloat.random(in: 0...1),
-            alpha: 1.0
-        )
-    }
-    
-    static func fromHex(_ hex: String, alpha: CGFloat = 1.0) -> UIColor {
-        var cleanedHex = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
-        
-        // Remove leading "#" if present
-        if cleanedHex.hasPrefix("#") {
-            cleanedHex.removeFirst()
-        }
-        
-        // Ensure valid hex length
-        guard cleanedHex.count == 6 else {
-            return UIColor.clear // Return clear color for invalid input
-        }
-        
-        // Extract RGB components
-        var rgbValue: UInt64 = 0
-        Scanner(string: cleanedHex).scanHexInt64(&rgbValue)
-        
-        let red = CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0
-        let green = CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0
-        let blue = CGFloat(rgbValue & 0x0000FF) / 255.0
-        
-        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
-    }
-    
-    var color: Color {
-        return Color(self)
-    }
-
-}

+ 0 - 56
AIPlayRingtones/Classes/Ex/UIFont+Ex.swift

@@ -1,56 +0,0 @@
-//
-//  UIFont+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-public typealias FontName = String
-
-public extension FontName {
-    static public let PingFangSC   = "PingFangSC"
-    static public let PoppinsBoldItalic   = "Poppins-BoldItalic"
-}
-
-
-public extension UIFont {
-    class public func font(name: FontName = .PingFangSC, size: CGFloat, weight: UIFont.Weight = .regular) -> UIFont {
-        guard !name.isEmpty,
-                let _ = UIFont(name: name, size: size) else {
-            return UIFont.systemFont(ofSize: size, weight: weight)
-        }
-        var finalFontName = name
-        
-        let fontNames = UIFont.fontNames(forFamilyName: name)
-        switch weight {
-        case .light://细体 300
-            if let aName = fontNames.first(where: { $0.lowercased().hasSuffix("-light") || $0.lowercased().hasSuffix("_light") }) {
-                finalFontName = aName
-            }
-        case .medium://中黑体 500
-            if let aName = fontNames.first(where: { $0.lowercased().hasSuffix("-medium") || $0.lowercased().hasSuffix("_medium") }) {
-                finalFontName = aName
-            }
-        case .bold:// 粗体 700
-            if let aName = fontNames.first(where: { $0.lowercased().hasSuffix("-bold") || $0.lowercased().hasSuffix("_bold") }) {
-                finalFontName = aName
-            }
-        case .semibold://半粗体 600
-            if let aName = fontNames.first(where: { $0.lowercased().hasSuffix("-semibold") || $0.lowercased().hasSuffix("_semibold") }) {
-                finalFontName = aName
-            }
-        case .heavy: //粗黑体 800
-            if let aName = fontNames.first(where: { $0.lowercased().hasSuffix("-heavy") || $0.lowercased().hasSuffix("_heavy") }) {
-                finalFontName = aName
-            }
-        case .black: // 黑体 900
-            if let aName = fontNames.first(where: { $0.lowercased().hasSuffix("-black") || $0.lowercased().hasSuffix("_black") }) {
-                finalFontName = aName
-            }
-        default:
-            break
-        }
-        
-        return UIFont(name: finalFontName, size: size)!
-    }
-}

+ 0 - 45
AIPlayRingtones/Classes/Ex/UIImage+Ex.swift

@@ -1,45 +0,0 @@
-//
-//  UIImage+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/23.
-//
-
-public extension UIImage {
-    /// 将颜色转换为 UIImage
-    /// - Parameters:
-    ///   - color: 目标颜色
-    ///   - size: 图片尺寸(默认 1x1)
-    /// - Returns: 转换后的 UIImage
-    public static func colorFrom(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) -> UIImage? {
-        // 创建一个矩形
-        let rect = CGRect(origin: .zero, size: size)
-        
-        // 开始图形上下文
-        UIGraphicsBeginImageContextWithOptions(size, false, 0)
-        
-        // 设置颜色填充
-        color.setFill()
-        UIRectFill(rect)
-        
-        // 获取生成的图片
-        let image = UIGraphicsGetImageFromCurrentImageContext()
-        
-        // 结束图形上下文
-        UIGraphicsEndImageContext()
-        
-        return image
-    }
-}
-
-public extension UIImage {
-    // 压缩图片到指定尺寸
-    func compressImageSize(to size: CGSize) -> UIImage {
-        let targetSize = size
-        if self.size.width > targetSize.width || self.size.height > targetSize.height {
-            return kf.resize(to: targetSize)
-        }
-        return self
-    }
-    
-}

+ 0 - 123
AIPlayRingtones/Classes/Ex/UIView+Ex.swift

@@ -1,123 +0,0 @@
-//
-//  View+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-
-import UIKit
-
-public extension UIView {
-
-    
-    /// 增加渐变背景,需要先确定当前 view 的 frame
-    /// - Parameters:
-    ///   - colors: 渐变背景颜色数组
-    ///   - startPoint: 渐变启示位置
-    ///   - endPoint: 渐变结束位置
-    ///   - layerSize: 指定 layer 的 size,否则和自己当前一样大
-    public func addGradientBg(colors: [CGColor],
-                       startPoint: CGPoint = .zero,
-                       endPoint: CGPoint = CGPoint(x: 1, y: 1),
-                       layerSize: CGSize? = nil) {
-        let gl = CAGradientLayer()
-        gl.colors = colors
-        gl.startPoint = startPoint
-        gl.endPoint = endPoint
-        gl.frame = CGRect(origin: .zero, size: layerSize ?? self.bounds.size)
-        gl.zPosition =  -1 // 将 gradientLayer 放在底层
-        layer.insertSublayer(gl, at: 0)
-    }
-    
-}
-
-public extension UIView {
-    // 部分圆角(必须Frame已知)
-    func makeCorner(_ corners: UIRectCorner, radius: CGFloat) {
-        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
-        let maskLayer = CAShapeLayer()
-        maskLayer.frame = bounds
-        maskLayer.path = path.cgPath
-        layer.mask = maskLayer
-    }
-}
-
-
-public extension UIView {
-    func removeAllSubViews() {
-        subviews.forEach { subview in
-            subview.removeFromSuperview()
-        }
-    }
-}
-
-
-public extension UIView {
-    /// 添加渐变色边框
-    /// - Parameters:
-    ///   - colors: 渐变色数组
-    ///   - width: 边框宽度
-    ///   - radius: 圆角半径(nil 时使用视图的现有圆角)
-    ///   - startPoint: 渐变起点 (默认从左到右)
-    ///   - endPoint: 渐变终点 (默认从左到右)
-    func addGradientBorder(
-        colors: [UIColor],
-        width: CGFloat = 3,
-        radius: CGFloat? = nil,
-        startPoint: CGPoint = CGPoint(x: 0, y: 0.5),
-        endPoint: CGPoint = CGPoint(x: 1, y: 0.5)
-    ) {
-        // 移除旧的渐变边框
-        removeGradientBorder()
-        
-        let gradientLayer = CAGradientLayer()
-        gradientLayer.name = "GradientBorder"
-        gradientLayer.frame = bounds
-        gradientLayer.colors = colors.map { $0.cgColor }
-        gradientLayer.startPoint = startPoint
-        gradientLayer.endPoint = endPoint
-        
-        let cornerRadius = radius ?? layer.cornerRadius
-        let path = UIBezierPath(
-            roundedRect: bounds.insetBy(dx: width/2, dy: width/2),
-            cornerRadius: cornerRadius
-        )
-        
-        let shapeLayer = CAShapeLayer()
-        shapeLayer.name = "GradientBorderMask"
-        shapeLayer.path = path.cgPath
-        shapeLayer.lineWidth = width
-        shapeLayer.fillColor = nil
-        shapeLayer.strokeColor = UIColor.black.cgColor
-        
-        gradientLayer.mask = shapeLayer
-        layer.addSublayer(gradientLayer)
-    }
-    
-    /// 更新渐变色边框的frame(在layoutSubviews中调用)
-    func updateGradientBorder() {
-        guard let gradientLayer = layer.sublayers?.first(where: { $0.name == "GradientBorder" }) as? CAGradientLayer,
-              let shapeLayer = gradientLayer.mask as? CAShapeLayer else {
-            return
-        }
-        
-        gradientLayer.frame = bounds
-        
-        let width = shapeLayer.lineWidth
-        let cornerRadius = layer.cornerRadius
-        let path = UIBezierPath(
-            roundedRect: bounds.insetBy(dx: width/2, dy: width/2),
-            cornerRadius: cornerRadius
-        )
-        
-        shapeLayer.path = path.cgPath
-    }
-    
-    /// 移除渐变色边框
-    func removeGradientBorder() {
-        layer.sublayers?.filter { $0.name == "GradientBorder" }.forEach {
-            $0.removeFromSuperlayer()
-        }
-    }
-}

+ 0 - 118
AIPlayRingtones/Classes/Ex/UIView+Frame.swift

@@ -1,118 +0,0 @@
-//
-//  UIView+Basic.swift
-//  Pods
-//
-//  Created by 100Years on 2025/3/6.
-//
-
-// Frame
-public extension UIView {
-    
-    
-    @IBInspectable
-    public var cornerRadius: CGFloat {
-        set {
-            clipsToBounds = true
-            layer.cornerRadius = newValue
-        }
-        get {
-            layer.cornerRadius
-        }
-    }
-    
-    @IBInspectable
-    public var borderWidth: CGFloat {
-        set {
-            layer.borderWidth = newValue
-        }
-        get {
-            layer.borderWidth
-        }
-    }
-    
-    @IBInspectable
-    public var borderColor: UIColor? {
-        set {
-            layer.borderColor = newValue?.cgColor
-        }
-        get {
-            if let cgColor = layer.borderColor {
-                return UIColor(cgColor: cgColor)
-            }
-            return nil
-        }
-    }
-    
-    
-    var x: CGFloat {
-        set {
-            frame.origin.x = newValue
-        }
-        get {
-            return frame.origin.x
-        }
-    }
-    
-    var y: CGFloat {
-        set {
-            frame.origin.y = newValue
-        }
-        get {
-            return frame.origin.y
-        }
-    }
-    
-    var width: CGFloat {
-        set {
-            frame.size.width = newValue
-        }
-        get {
-            return frame.size.width
-        }
-    }
-    
-    var height: CGFloat {
-        set {
-            frame.size.height = newValue
-        }
-        get {
-            return frame.size.height
-        }
-    }
-    
-    var size: CGSize {
-        get { frame.size }
-        set {
-            var rect = frame
-            rect.size = newValue
-            frame = rect
-        }
-    }
-    
-    var centerX: CGFloat {
-        set {
-            let newCenter = CGPoint(x: newValue, y: center.y)
-            center = newCenter
-        }
-        get {
-            return center.x
-        }
-    }
-    
-    var centerY: CGFloat {
-        set {
-            let newCenter = CGPoint(x: center.x, y: newValue)
-            center = newCenter
-        }
-        get {
-            return center.y
-        }
-    }
-    
-    var bottom: CGFloat {
-        get {
-            return frame.origin.y + frame.size.height
-        }
-    }
-    
-}

+ 0 - 49
AIPlayRingtones/Classes/Ex/UIView+Rotating.swift

@@ -1,49 +0,0 @@
-//
-//  UIView+A.swift
-//  Pods
-//
-//  Created by 100Years on 2025/3/6.
-//
-
-import UIKit
-
-public extension UIView {
-    // MARK: - 旋转动画控制
-    /// 开始旋转动画
-    /// - Parameters:
-    ///   - duration: 单圈旋转时间(默认 1 秒)
-    ///   - clockwise: 是否顺时针旋转(默认 true)
-    ///   - repeatCount: 重复次数(默认无限循环 .greatestFiniteMagnitude)
-    func startRotating(duration: CFTimeInterval = 1.0,
-                     clockwise: Bool = true,
-                     repeatCount: Float = .greatestFiniteMagnitude) {
-        // 同步移除已有旋转动画
-        self.stopRotating()
-        
-        DispatchQueue.main.async {
-            // 创建旋转动画
-            let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
-            rotationAnimation.fromValue = 0
-            rotationAnimation.toValue = clockwise ? CGFloat.pi * 2.0 : -CGFloat.pi * 2.0
-            rotationAnimation.duration = duration
-            rotationAnimation.isCumulative = true
-            rotationAnimation.repeatCount = repeatCount
-            rotationAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
-            
-            // 防止动画结束后恢复初始状态
-            rotationAnimation.fillMode = .forwards
-            rotationAnimation.isRemovedOnCompletion = false
-            
-            // 添加动画到视图的 layer
-            self.layer.add(rotationAnimation, forKey: "rotationAnimation")
-        }
-    }
-    
-    /// 停止旋转动画
-    func stopRotating() {
-        // 同步移除旋转动画
-        DispatchQueue.main.async {
-            self.layer.removeAnimation(forKey: "rotationAnimation")
-        }
-    }
-}

+ 0 - 58
AIPlayRingtones/Classes/Ex/UIViewController+Ex.swift

@@ -1,58 +0,0 @@
-//
-//  UIViewController+Ex.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/30.
-//
-
-public extension UIViewController {
-    func showCustomAlert(
-        title: String? = "",
-        message: String?,
-        rightActionString:String = "Delete".localized,
-        deleteHandler: (() -> Void)? = nil,
-        cancelHandler: (() -> Void)? = nil
-    ) {
-        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
-        
-        // 自定义标题
-        if let title = title {
-            let titleAttributes: [NSAttributedString.Key: Any] = [
-                .font: UIFont.boldSystemFont(ofSize: 20),
-                .foregroundColor: UIColor.white
-            ]
-            let attributedTitle = NSAttributedString(string: title, attributes: titleAttributes)
-            alert.setValue(attributedTitle, forKey: "attributedTitle")
-        }
-        
-        // 自定义消息
-        if let message = message {
-            let messageAttributes: [NSAttributedString.Key: Any] = [
-                .font: UIFont.boldSystemFont(ofSize: 17),
-                .foregroundColor: UIColor.white
-            ]
-            let attributedMessage = NSAttributedString(string: message, attributes: messageAttributes)
-            alert.setValue(attributedMessage, forKey: "attributedMessage")
-        }
-        
-        // 添加按钮
-        let cancelAction = UIAlertAction(title: "Cancel".localized, style: .cancel) { _ in
-            cancelHandler?()
-        }
-        alert.addAction(cancelAction)
-        
-        let deleteAction = UIAlertAction(title: rightActionString, style: .destructive) { _ in
-            deleteHandler?()
-        }
-        alert.addAction(deleteAction)
-        
-        // 设置黑暗模式
-        alert.overrideUserInterfaceStyle = .dark
-        
-        // 显示弹窗
-        present(alert, animated: true, completion: nil)
-    }
-
-}
-
-

+ 0 - 149
AIPlayRingtones/Classes/GlobalImports/GlobalImports.swift

@@ -1,149 +0,0 @@
-//
-//  GlobalImports.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/20.
-//
-
-@_exported import Foundation
-@_exported import UIKit
-@_exported import SnapKit
-
-import AVFoundation
-
-public func k_Height_statusBar() -> CGFloat {
-    var statusBarHeight: CGFloat = 0;
-    if #available(iOS 13.0, *) {
-        let scene = UIApplication.shared.connectedScenes.first;
-        guard let windowScene = scene as? UIWindowScene else {return 0};
-        guard let statusBarManager = windowScene.statusBarManager else {return 0};
-        statusBarHeight = statusBarManager.statusBarFrame.height;
-    } else {
-        statusBarHeight = UIApplication.shared.statusBarFrame.height;
-    }
-    return statusBarHeight;
-}
-/// ②、顶部安全区高度 k_Height_safeAreaInsetsTop
-public func k_Height_safeAreaInsetsTop() -> CGFloat {
-    if #available(iOS 13.0, *) {
-        let scene = UIApplication.shared.connectedScenes.first;
-        guard let windowScene = scene as? UIWindowScene else {return 0};
-        guard let window = windowScene.windows.first else {return 0};
-        return window.safeAreaInsets.top;
-    } else if #available(iOS 11.0, *) {
-        guard let window = UIApplication.shared.windows.first else {return 0};
-        return window.safeAreaInsets.top;
-    }
-    return 0;
-}
-
-/// ③、底部安全区高度
-public func k_Height_safeAreaInsetsBottom() -> CGFloat {
-    if #available(iOS 13.0, *) {
-        let scene = UIApplication.shared.connectedScenes.first;
-        guard let windowScene = scene as? UIWindowScene else {return 0};
-        guard let window = windowScene.windows.first else {return 0};
-        return window.safeAreaInsets.bottom;
-    } else if #available(iOS 11.0, *) {
-        guard let window = UIApplication.shared.windows.first else {return 0};
-        return window.safeAreaInsets.bottom;
-    }
-    return 0;
-}
-/** 屏幕宽度 */
-public let k_ScreenWidth = UIScreen.main.bounds.size.width
-/** 屏幕高度 */
-public let k_ScreenHeight = UIScreen.main.bounds.size.height
-/* 导航栏高度 固定高度 = 44.0f */
-//let k_Height_NavContentBar :CGFloat  = UINavigationBar.appearance().frame.size.height
-public let k_Height_NavBar :CGFloat = 44.0
-/** 状态栏高度 */
-public let k_Height_StatusBar :CGFloat = k_Height_statusBar()
-/** 状态栏+导航栏的高度 */
-public let k_Nav_Height: CGFloat = k_Height_NavBar + k_Height_StatusBar
-/** 底部tabBar栏高度(不包含安全区,即:在 iphoneX 之前的手机) */
-public let k_TabBar_Height :CGFloat = 49.0
-/** 底部导航栏高度(包括安全区),一般使用这个值 */
-public let k_Height_TabBar :CGFloat = k_Height_safeAreaInsetsBottom() + k_TabBar_Height
-
-
-//判断是否是 x、及x以上 系列
-public func isIphoneX() -> Bool {
-    return k_Height_safeAreaInsetsBottom() > 0.0; // 底部安全区 > 0 时,
-    
-}
-
-//设计稿为 375*812 比例,所以比例系数为 375.0/kScreenWidth
-public let kDesignScale = k_ScreenWidth/375.0
-
-
-public func kGetUIH(designSize:CGSize,currentW:CGFloat) -> CGFloat {
-    let scale = designSize.width/currentW
-    return designSize.height/scale
-}
-    
-
-public func debugPrint<T>(_ messsage: T, file: String = #file, funcName: String = #function, lineNum: Int = #line) {
-//    #if DEBUG
-    let fileName = (file as NSString).lastPathComponent
-    print(Date.hmsString + " \(fileName) (\(funcName)): [\(lineNum)]- \(messsage)")
-//    #endif
-}
-
-public func dePrint<T>(_ messsage: T) {
-    #if DEBUG
-    print(Date.hmsString + " \(messsage)")
-    #endif
-}
-
-public func className(from object: Any) -> String {
-    return String(describing: type(of: object))
-}
-
-public func appShortVersion() ->String{
-    let short = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
-    return short
-}
-
-public func appVersion() ->String{
-    let short = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
-    return "V" + short
-}
-
-
-public func kPresentModalVC(target:UIViewController,
-                     modelVC:UIViewController,
-                       style:UIModalPresentationStyle = .overFullScreen,
-             transitionStyle:UIModalTransitionStyle = .coverVertical,
-                  completion: (() -> Void)? = nil){
-    let navi = ASBaseNavigationController(rootViewController: modelVC)
-    navi.modalPresentationStyle = style
-    navi.modalTransitionStyle = transitionStyle
-    target.present(navi, animated: true,completion: completion)
-}
-
-public func kPushVC(target:UIViewController,modelVC:UIViewController){
-    modelVC.hidesBottomBarWhenPushed = true
-    target.navigationController?.pushViewController(modelVC, animated: true)
-}
-
-public func kGetVideoThumbnail(from videoURL: URL) -> UIImage? {
-    let asset = AVAsset(url: videoURL)
-    let assetImgGenerate = AVAssetImageGenerator(asset: asset)
-    assetImgGenerate.appliesPreferredTrackTransform = true
-    
-    let time = CMTimeMakeWithSeconds(0.0, preferredTimescale: 600) // 获取第0秒的帧
-    do {
-        let imgRef = try assetImgGenerate.copyCGImage(at: time, actualTime: nil)
-        return UIImage(cgImage: imgRef)
-    } catch {
-        print("Error generating thumbnail: \(error.localizedDescription)")
-        return nil
-    }
-}
-
-public func kShowToastDataMissing(){
-    
-}
-
-

+ 0 - 151
AIPlayRingtones/Classes/Tool/TSBusinessFileManager.swift

@@ -1,151 +0,0 @@
-//
-//  TSBusinessFileManager.swift
-//  AIRingtone
-//
-//  Created by 100Years on 2025/3/27.
-//
-
-class TSBusinessFileManager {
-    
-    /// 获取 Video 下载后保存的的文件件路径
-    static var saveVideoPathURL:URL = {
-        let saveRingPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("video")
-        return saveRingPathURL
-    }()
-    
-    static var saveCacheAllPathURL:URL = {
-        let saveRingPathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("cacheAll")
-        return saveRingPathURL
-    }()
-    
-    public static func generateFileName(
-        urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil
-    )->String?{
-        guard let url = URL(string: urlString) else{
-            return nil
-        }
-        
-        var fileName = url.path.md5
-
-        // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
-        var fileExtension = ""
-        if let fileEx = fileEx {
-            fileExtension = fileEx
-        }else{
-            var missingExStr = ""
-            if let missingEx = missingEx {
-                missingExStr = missingEx
-            }
-            fileExtension = url.pathExtension.isEmpty ? missingExStr : url.pathExtension
-        }
-
-        if fileExtension.count > 0 {
-            fileName = url.path.md5 + ".\(fileExtension)"
-        }
-         
-        return fileName
-    }
-    
-    //获取 urlstring 本地的缓存 url path
-    public static func getLocalURL(
-        urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil)->URL?{
-        
-        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
-            return nil
-        }
-        
-        //检查文件是否已存在于缓存中
-        let ringFileURL = saveVideoPathURL.appendingPathComponent(fileName)
-        if FileManager.default.fileExists(atPath: ringFileURL.path) {
-            print("文件已存在于缓存中: \(ringFileURL)")
-            return ringFileURL
-        }
-        
-        let cachedFileURL = saveCacheAllPathURL.appendingPathComponent(fileName)
-        if FileManager.default.fileExists(atPath: cachedFileURL.path) {
-            print("文件已存在于缓存中: \(cachedFileURL)")
-            return cachedFileURL
-        }
-        
-        return nil
-    }
-    
-
-}
-
-//缓存路径
-extension TSBusinessFileManager {
-    
-    //检查 url 对不对
-    public static func generateCachesURL(
-        from urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil,
-        cacheDirectory:String = "cacheAll",
-        completion:((String?, Error?) -> Void)? = nil
-    )->URL?
-    {
-        guard let url = URL(string: urlString) else{
-            completion?(nil, NSError(domain: "url null", code: 0))
-            return nil
-        }
-        
-        if !urlString.contains("http") && urlString.contains("/"){
-            completion?(urlString.fillCachePath, nil)
-            return nil
-        }
-        
-        let fileManager = FileManager.default
-        
-        // 获取缓存目录下的 `cacheAll` 文件夹路径
-        let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
-        let cacheAllDirectory = cachesDirectory.appendingPathComponent(cacheDirectory)
-        
-        // 创建 `cacheAll` 文件夹(如果不存在)
-        if !fileManager.fileExists(atPath: cacheAllDirectory.path) {
-            do {
-                try fileManager.createDirectory(at: cacheAllDirectory, withIntermediateDirectories: true, attributes: nil)
-            } catch {
-                completion?(nil, error)
-                return nil
-            }
-        }
-        
-        
-        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
-            completion?(nil, NSError(domain: "url error", code: 0))
-            return nil
-        }
-
-        let cachedFileURL = cacheAllDirectory.appendingPathComponent(fileName)
-        return cachedFileURL
-    }
-    
-    //获取 urlstring 本地的缓存 url path
-    public static func getCachesURL(
-        from urlString: String,
-        fileEx:String? = nil,
-    missingEx:String? = nil,
-        cacheDirectory:String = "cacheAll")->URL?{
-        
-        if let cachedFileURL = generateCachesURL(
-            from: urlString,
-            fileEx: fileEx,
-            missingEx: missingEx,
-            cacheDirectory: cacheDirectory
-        ){
-            //检查文件是否已存在于缓存中
-            if FileManager.default.fileExists(atPath: cachedFileURL.path) {
-                print("文件已存在于缓存中: \(cachedFileURL)")
-                return cachedFileURL
-            }
-        }
-        
-        return nil
-    }
-    
-}

+ 0 - 78
AIPlayRingtones/Classes/Tool/TSCollectionViewObserver.swift

@@ -1,78 +0,0 @@
-//
-//  Untitled.swift
-//  Pods
-//
-//  Created by 100Years on 2025/5/16.
-//
-
-
-public class TSCollectionViewObserver {
-    private weak var collectionView: UICollectionView?
-    private var observers: [NSKeyValueObservation] = []
-    
-    public var onContentSizeChange: ((CGSize) -> Void)?
-    public var onContentInsetChange: ((UIEdgeInsets) -> Void)?
-    public var onContentOffsetChange: ((CGPoint) -> Void)?
-    
-    public init(collectionView: UICollectionView) {
-        self.collectionView = collectionView
-        setupObservers()
-    }
-    
-    private func setupObservers() {
-        guard let collectionView = collectionView else { return }
-        
-        observers.append(
-            collectionView.observe(\.contentSize, options: [.new, .old]) { [weak self] (_, change) in
-                guard let newSize = change.newValue, newSize != change.oldValue else { return }
-                self?.onContentSizeChange?(newSize)
-            }
-        )
-        
-        observers.append(
-            collectionView.observe(\.contentInset, options: [.new, .old]) { [weak self] (_, change) in
-                guard let newInset = change.newValue, newInset != change.oldValue else { return }
-                self?.onContentInsetChange?(newInset)
-            }
-        )
-        
-        observers.append(
-            collectionView.observe(\.contentOffset, options: [.new]) { [weak self] (_, change) in
-                guard let newOffset = change.newValue else { return }
-                self?.onContentOffsetChange?(newOffset)
-            }
-        )
-    }
-    
-    deinit {
-        observers.forEach { $0.invalidate() }
-    }
-}
-
-
-
-//        collectionViewObserverHandle()
-//
-//private var collectionViewObserver: CollectionViewObserver!
-//func collectionViewObserverHandle(){
-//    collectionViewObserver = CollectionViewObserver(collectionView: collectionComponent.collectionView)
-//
-//    collectionViewObserver.onContentSizeChange = { size in
-//        print("collectionViewObserver 内容大小变化: \(size)")
-//    }
-//
-//    collectionViewObserver.onContentInsetChange = { inset in
-//        print("collectionViewObserver 内边距变化: \(inset)")
-//    }
-//
-//    collectionViewObserver.onContentOffsetChange = { offset in
-//        print("collectionViewObserver 偏移量变化: \(offset)")
-//    }
-//
-//}
-//
-//
-//func scrollViewDidScroll(_ scrollView: UIScrollView) {
-//    print("contentOffset 变化: \(scrollView.contentOffset)")
-//    // 实时监听偏移量变化
-//}

+ 0 - 173
AIPlayRingtones/Classes/Tool/TSFileManagerTool.swift

@@ -1,173 +0,0 @@
-//
-//  TSFileManagerTool.swift
-//  TSLiveWallpaper
-//
-//  Created by 100Years on 2024/12/26.
-//
-
-public class TSFileManagerTool {
-
-    /// 获取沙盒 Documents 目录路径
-    public static var documentsDirectory: URL {
-        return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
-    }
-
-    /// 获取沙盒 Cache 目录路径
-    public static var cacheDirectory: URL {
-        return FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
-    }
-
-    /// 获取沙盒 Temporary 目录路径
-    public static var temporaryDirectory: URL {
-        return FileManager.default.temporaryDirectory
-    }
-
-    public  static func copyFileWithOverwrite(from sourceURL: URL, to targetURL: URL) {
-        let fileManager = FileManager.default
-        do {
-            removeItem(from: targetURL)
-            checkFolderAndCreate(from: targetURL)
-            try fileManager.copyItem(at: sourceURL, to: targetURL)
-            debugPrint("文件复制成功!")
-        } catch {
-            debugPrint("文件复制失败: \(error.localizedDescription)")
-        }
-    }
-    
-    public static func removeItem(from sourceURL: URL) {
-        let fileManager = FileManager.default
-        do {
-            // 如果目标路径存在同名文件,先删除旧文件
-            if fileManager.fileExists(atPath: sourceURL.path) {
-                try fileManager.removeItem(at: sourceURL)
-            }
-            debugPrint("文件删除成功!")
-        } catch {
-            debugPrint("文件删除失败: \(error.localizedDescription)")
-        }
-    }
-    
-    /// 移动文件的方法(自动创建目标文件夹)
-    /// - Parameters:
-    ///   - sourceURL: 文件的源 URL
-    ///   - destinationURL: 目标 URL
-    /// - Throws: 如果移动失败,会抛出错误
-    public static func moveFile(from sourceURL: URL, to destinationURL: URL) {
-        let fileManager = FileManager.default
-        
-        // 检查源文件是否存在
-        guard fileManager.fileExists(atPath: sourceURL.path) else {
-            let error = NSError(domain: "FileMoveError", code: 404, userInfo: [NSLocalizedDescriptionKey: "源文件不存在"])
-            debugPrint(error)
-            return
-        }
-        
-        // 获取目标文件夹的路径
-        let destinationDirectory = destinationURL.deletingLastPathComponent()
-        do {
-            // 如果目标文件夹不存在,创建文件夹
-            if !fileManager.fileExists(atPath: destinationDirectory.path) {
-                try fileManager.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
-            }
-            
-            // 检查目标路径是否已经存在文件
-            if fileManager.fileExists(atPath: destinationURL.path) {
-                // 如果需要覆盖,可以选择先删除目标文件
-                try fileManager.removeItem(at: destinationURL)
-            }
-            
-            // 尝试移动文件
-            try fileManager.moveItem(at: sourceURL, to: destinationURL)
-        } catch {
-            debugPrint("尝试移动文件失败: \(error.localizedDescription)")
-        }
-    }
-    
-    public static func getFileName(from url: URL, includeExtension: Bool = true) -> String {
-        if includeExtension {
-            return url.lastPathComponent
-        } else {
-            return url.deletingPathExtension().lastPathComponent
-        }
-    }
-    
-    public static func checkFolderAndCreate(from destinationURL: URL){
-        let fileManager = FileManager.default
-        let destinationDirectory = destinationURL.deletingLastPathComponent()
-        // 如果目标文件夹不存在,创建文件夹
-        if !fileManager.fileExists(atPath: destinationDirectory.path) {
-            do {
-                try fileManager.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
-            } catch {
-                debugPrint("尝试创建文件夹失败: \(error.localizedDescription)")
-            }
-        }
-    }
-
-    // MARK: - 文件操作方法
-
-    /// 检查文件或文件夹是否存在
-    public static func fileExists(at url: URL) -> Bool {
-        return FileManager.default.fileExists(atPath: url.path)
-    }
-
-    /// 创建文件夹
-    public static func createDirectory(at url: URL) throws {
-        if !fileExists(at: url) {
-            try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
-        }
-    }
-    
-    //获取缓存目录下文件夹路径
-    public static func getCacheSubPath(at url: URL) ->String? {
-        let array = url.path.components(separatedBy:"/Caches/")
-        let cashFilePath = array.last
-        return cashFilePath
-    }
-    
-}
-
-public extension String {
-    
-    public var isCachesPath:Bool{
-        return self.contains("/Caches/")
-    }
-    
-    public var fillCachePath:String{
-        return TSFileManagerTool.cacheDirectory.appendingPathComponent(self).path
-    }
-    
-    public var fillCacheURL:URL{
-        return TSFileManagerTool.cacheDirectory.appendingPathComponent(self)
-    }
-    
-    public var cachesLastURLString:String{
-        let parts = self.components(separatedBy: "/Caches/")
-        if let last = parts.last {
-            return last
-        }
-        return self
-    }
-}
-public extension String {
-    
-    public var isDocumentPath:Bool{
-        return self.contains("/Documents/")
-    }
-    
-    public var fillDocumentPath:String{
-        return TSFileManagerTool.documentsDirectory.appendingPathComponent(self).path
-    }
-    
-    public var fillDocumentURL:URL{
-        return TSFileManagerTool.documentsDirectory.appendingPathComponent(self)
-    }
-    
-    public var documentLastURLString:String{
-        let parts = self.components(separatedBy: "/Documents/")
-        if let last = parts.last {
-            return last
-        }
-        return self
-    }
-}

+ 0 - 27
AIPlayRingtones/Classes/Tool/TSRandomTextTool.swift

@@ -1,27 +0,0 @@
-//
-//  TSRandomTextTool.swift
-//  Pods
-//
-//  Created by 100Years on 2025/5/15.
-//
-
-public class TSRandomTextTool {
-    private var texts: [String]
-    private var lastIndex: Int?
-
-    public init(texts: [String]) {
-        self.texts = texts
-    }
-    
-    public func getRandomText() -> String? {
-        guard !texts.isEmpty else { return nil }
-        
-        var randomIndex: Int
-        repeat {
-            randomIndex = Int.random(in: 0..<texts.count)
-        } while randomIndex == lastIndex
-        
-        lastIndex = randomIndex
-        return texts[randomIndex]
-    }
-}

+ 84 - 139
AIPlayRingtones/Classes/View/TSPlaceholderTextView/TSPlaceholderTextView.swift

@@ -5,190 +5,135 @@
 //  Created by 100Years on 2025/3/4.
 //
 
-open class TSPlaceholderTextView: UITextView {
-    
-//    // MARK: - 垂直对齐模式
-//    public enum VerticalAlignment {
-//        case top
-//        case center
-//        case bottom
-//    }
-//    
-//    public var verticalAlignment: VerticalAlignment = .top {
-//        didSet { setNeedsLayout() }
-//    }
-    
-    // Placeholder Label
-    public lazy var placeholderLabel: TopLeftLabel = {
-        let placeholderLabel = TopLeftLabel()
-        placeholderLabel.font = font
-        placeholderLabel.textColor = placeholderColor
-        placeholderLabel.text = placeholder
-        placeholderLabel.numberOfLines = 0
-        placeholderLabel.isUserInteractionEnabled = false
-        placeholderLabel.textAlignment = .left
-        return placeholderLabel
+
+class XHInputView: UITextView {
+    
+    // MARK: - UI Components
+    private lazy var hintLabel: ASTLLabel = {
+        let label = ASTLLabel()
+        label.font = self.font
+        label.textColor = hintTextColor
+        label.text = hintText
+        label.numberOfLines = 0
+        label.isUserInteractionEnabled = false
+        label.textAlignment = .left
+        return label
     }()
     
-    public var maxLength:Int = 1000 {
+    // MARK: - Properties
+    var maximumCharacters: Int = 1000 {
         didSet {
-            handleTextViewTextCount(textView: self)
+            validateCharacterCount(inputView: self)
         }
     }
-    // Placeholder Text
-    public  var placeholder: String? {
+    
+    var hintText: String? {
         didSet {
-            placeholderLabel.text = placeholder
+            hintLabel.text = hintText
         }
     }
     
-    // Placeholder Color
-    public var placeholderColor: UIColor = .lightGray {
+    var hintTextColor: UIColor = .lightGray {
         didSet {
-            placeholderLabel.textColor = placeholderColor
+            hintLabel.textColor = hintTextColor
         }
     }
     
-    // Placeholder Insets
-    public var textInsets: UIEdgeInsets = .zero {
+    var contentInsets: UIEdgeInsets = .zero {
         didSet {
-            updateTextContainerInset()
+            adjustContentInsets()
         }
     }
     
-    // Override text property to manage placeholder visibility
-    open override var text: String! {
+    override var text: String! {
         didSet {
-            updatePlaceholderVisibility()
+            toggleHintVisibility()
         }
     }
     
-    public var textViewTextChanged:(()->Void)?
+    var onTextUpdate: (() -> Void)?
     
-    // Initializer
-    public init(placeholder: String? = nil,
-         text: String? = nil,
-         font: UIFont? = nil,
-         textColor: UIColor = .black,
-         backgroundColor: UIColor = .white,
-         textInsets: UIEdgeInsets = .zero) {
+    // MARK: - Initialization
+    init(hint: String? = nil,
+                    initialText: String? = nil,
+                    textFont: UIFont? = nil,
+                    contentColor: UIColor = .black,
+                    background: UIColor = .white,
+                    insets: UIEdgeInsets = .zero) {
         super.init(frame: .zero, textContainer: nil)
         
-        self.placeholder = placeholder
-        self.font = font
-        self.textColor = textColor
-        self.backgroundColor = backgroundColor
-        self.textInsets = textInsets
+        self.hintText = hint
+        self.font = textFont
+        self.textColor = contentColor
+        self.backgroundColor = background
+        self.contentInsets = insets
         
-        setupPlaceholder()
-        self.text = text
+        configureHintDisplay()
+        self.text = initialText
     }
     
-    required public init?(coder: NSCoder) {
+    required init?(coder: NSCoder) {
         super.init(coder: coder)
-        setupPlaceholder()
+        configureHintDisplay()
+    }
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
     }
     
-    // Setup placeholder label
-    private func setupPlaceholder() {
- 
-        addSubview(placeholderLabel)
-        updatePlaceholderVisibility()
+    // MARK: - Configuration
+    private func configureHintDisplay() {
+        addSubview(hintLabel)
+        toggleHintVisibility()
         
-        // Observe text changes to update placeholder
-        NotificationCenter.default.addObserver(self,
-                                               selector: #selector(textDidChange(_:)),
-                                               name: UITextView.textDidChangeNotification,
-                                               object: self)
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(handleTextUpdate(_:)),
+            name: UITextView.textDidChangeNotification,
+            object: self
+        )
         
-        // Update text container insets
-        updateTextContainerInset()
+        adjustContentInsets()
     }
     
-    deinit {
-        NotificationCenter.default.removeObserver(self)
+    // MARK: - Layout
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        
+        let xPosition = contentInsets.left + 5
+        let yPosition = contentInsets.top
+        let labelWidth = bounds.width - contentInsets.left - contentInsets.right - 10
+        let labelHeight = bounds.height - contentInsets.top - contentInsets.bottom
+        
+        hintLabel.frame = CGRect(
+            x: xPosition,
+            y: yPosition,
+            width: labelWidth,
+            height: labelHeight
+        )
     }
     
-    // Update placeholder visibility
-    private func updatePlaceholderVisibility() {
-        placeholderLabel.isHidden = !text.isEmpty
+    // MARK: - Helper Methods
+    private func toggleHintVisibility() {
+        hintLabel.isHidden = !text.isEmpty
     }
     
-    
-    @objc private func textDidChange(_ notification: Notification) {
+    @objc private func handleTextUpdate(_ notification: Notification) {
         if let textView = notification.object as? UITextView {
-            handleTextViewTextCount(textView: textView)
-            textViewTextChanged?()
+            validateCharacterCount(inputView: textView)
+            onTextUpdate?()
         }
-        updatePlaceholderVisibility()
+        toggleHintVisibility()
     }
     
-    open func handleTextViewTextCount(textView:UITextView) {
-        if textView.text.count > maxLength {
-            textView.text = String(textView.text.prefix(maxLength))
+    func validateCharacterCount(inputView: UITextView) {
+        if inputView.text.count > maximumCharacters {
+            inputView.text = String(inputView.text.prefix(maximumCharacters))
         }
     }
     
-    // Update textContainerInset and placeholder frame
-    private func updateTextContainerInset() {
-        textContainerInset = textInsets
+    private func adjustContentInsets() {
+        textContainerInset = contentInsets
         setNeedsLayout()
     }
-
-    
-    // Layout placeholder
-    open override func layoutSubviews() {
-        super.layoutSubviews()
-
-  
-//        let textInsets = textCntainerInset
-        let placeholderX = textInsets.left + 5 // Add padding for placeholder
-        let placeholderY = textInsets.top
-        let placeholderWidth = bounds.width - textInsets.left - textInsets.right - 10 // Adjust for padding
-        let placeholderHeight = bounds.height - textInsets.top - textInsets.bottom
-        
-        placeholderLabel.frame = CGRect(x: placeholderX,
-                                        y: placeholderY,
-                                        width: placeholderWidth,
-                                        height: placeholderHeight)
-        
-//        handleVerticalAlignment()
-    }
-    
-    func handleVerticalAlignment() {
-      
-//          guard !bounds.isEmpty else { return }
-//          
-//        
-//        let label = UILabel()
-//        label.text = text
-//        label.font = font
-//        label.numberOfLines = 0
-//        var height = label.sizeThatFits(CGSize(width: bounds.width, height: .greatestFiniteMagnitude)).height
-//
-//        
-////          let size = sizeThatFits(CGSize(
-////              width: bounds.width,
-////              height: CGFloat.greatestFiniteMagnitude
-////          ))
-//          
-//          let topInset: CGFloat
-//          switch verticalAlignment {
-//          case .top:
-//              topInset = 0
-//          case .center:
-//              topInset = max(0, (bounds.height - height) / 2)
-//          case .bottom:
-//              topInset = max(0, bounds.height - height)
-//          }
-//          
-//          textContainerInset = UIEdgeInsets(
-//              top: topInset,
-//              left: textContainerInset.left,
-//              bottom: textContainerInset.bottom,
-//              right: textContainerInset.right
-//          )
-      }
 }
-
-

+ 2 - 2
AIPlayRingtones/Classes/View/TSSaveSuccessTool/TSSaveSuccessTool.swift

@@ -27,7 +27,7 @@ open class TSSaveSuccessTool {
     
     private lazy var viewButton:UIView = {
         let color = "4FEA9D".uiColor
-        let viewButton = UIButton.createButton(title: "View".localized ,backgroundColor: color.withAlphaComponent(0.1),font: UIFont.font(size: 12),titleColor: color,corner: 14) { [weak self]  in
+        let viewButton = UIButton.createBtn(title: "View".localized ,backgroundColor: color.withAlphaComponent(0.1),font: UIFont.font(size: 12),titleColor: color,corner: 14) { [weak self]  in
             guard let self = self else { return }
             if let clickViewHandle = clickViewHandle {
                 clickViewHandle()
@@ -99,7 +99,7 @@ open class TSSaveSuccessTool {
     
     public func getBottom(topY:CGFloat)->CGFloat{
         let bottom = -(k_ScreenHeight - 48 - topY)
-        debugPrint("bottom=\(bottom)")
+        logPrint("bottom=\(bottom)")
         return bottom
     }
     

+ 25 - 0
AIPlayRingtones/Common/ASColObserver.h

@@ -0,0 +1,25 @@
+//
+//  ASColObserver.h
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+NS_ASSUME_NONNULL_BEGIN
+typedef void(^TSContentSizeChangeBlock)(CGSize newSize);
+typedef void(^TSContentInsetChangeBlock)(UIEdgeInsets newInset);
+typedef void(^TSContentOffsetChangeBlock)(CGPoint newOffset);
+
+@interface ASColObserver : NSObject
+
+@property (nonatomic, copy) TSContentSizeChangeBlock onContentSizeChange;
+@property (nonatomic, copy) TSContentInsetChangeBlock onContentInsetChange;
+@property (nonatomic, copy) TSContentOffsetChangeBlock onContentOffsetChange;
+
+- (instancetype)initWithCollectionView:(UICollectionView *)collectionView;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 87 - 0
AIPlayRingtones/Common/ASColObserver.m

@@ -0,0 +1,87 @@
+//
+//  ASColObserver.m
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+#import "ASColObserver.h"
+#import <objc/runtime.h>
+
+@interface ASColObserver ()
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+@property (nonatomic, strong) NSMutableArray *observers;
+
+@end
+
+@implementation ASColObserver
+
+
+- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
+    self = [super init];
+    if (self) {
+        _collectionView = collectionView;
+        _observers = [NSMutableArray array];
+        [self setupObservers];
+    }
+    return self;
+}
+
+- (void)setupObservers {
+    if (!self.collectionView) return;
+    
+    // ContentSize Observer
+    [self.collectionView addObserver:self
+                         forKeyPath:@"contentSize"
+                            options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
+                            context:nil];
+    
+    // ContentInset Observer
+    [self.collectionView addObserver:self
+                         forKeyPath:@"contentInset"
+                            options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
+                            context:nil];
+    
+    // ContentOffset Observer
+    [self.collectionView addObserver:self
+                         forKeyPath:@"contentOffset"
+                            options:NSKeyValueObservingOptionNew
+                            context:nil];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
+                       context:(void *)context {
+    if (object == self.collectionView) {
+        if ([keyPath isEqualToString:@"contentSize"]) {
+            CGSize newSize = [change[NSKeyValueChangeNewKey] CGSizeValue];
+            CGSize oldSize = [change[NSKeyValueChangeOldKey] CGSizeValue];
+            if (!CGSizeEqualToSize(newSize, oldSize) && self.onContentSizeChange) {
+                self.onContentSizeChange(newSize);
+            }
+        }
+        else if ([keyPath isEqualToString:@"contentInset"]) {
+            UIEdgeInsets newInset = [change[NSKeyValueChangeNewKey] UIEdgeInsetsValue];
+            UIEdgeInsets oldInset = [change[NSKeyValueChangeOldKey] UIEdgeInsetsValue];
+            if (!UIEdgeInsetsEqualToEdgeInsets(newInset, oldInset) && self.onContentInsetChange) {
+                self.onContentInsetChange(newInset);
+            }
+        }
+        else if ([keyPath isEqualToString:@"contentOffset"]) {
+            CGPoint newOffset = [change[NSKeyValueChangeNewKey] CGPointValue];
+            if (self.onContentOffsetChange) {
+                self.onContentOffsetChange(newOffset);
+            }
+        }
+    }
+}
+
+- (void)dealloc {
+    [self.observers enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        [self.collectionView removeObserver:self forKeyPath:obj];
+    }];
+}
+
+@end

+ 44 - 0
AIPlayRingtones/Common/ASFileManager.h

@@ -0,0 +1,44 @@
+//
+//  ASFileManager.h
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ASFileManager : NSObject
++ (NSURL *)documentsDirectory;
++ (NSURL *)cacheDirectory;
+
++ (void)copyFileWithOverwriteFrom:(NSURL *)sourceURL to:(NSURL *)targetURL;
++ (void)removeItemFrom:(NSURL *)sourceURL;
++ (void)checkFolderAndCreateFrom:(NSURL *)destinationURL;
+
++ (BOOL)fileExistsAtURL:(NSURL *)url;
++ (void)createDirectoryAtURL:(NSURL *)url error:(NSError **)error;
++ (NSString *)getCacheSubPathAtURL:(NSURL *)url;
+@end
+
+@interface NSString (CachePath)
+
+@property (nonatomic, readonly) BOOL isCachesPath;
+@property (nonatomic, readonly) NSString *fillCachePath;
+@property (nonatomic, readonly) NSURL *fillCacheURL;
+@property (nonatomic, readonly) NSString *cachesLastURLString;
+
+@end
+
+
+@interface NSString (DocumentPath)
+
+@property (nonatomic, readonly) BOOL isDocumentPath;
+@property (nonatomic, readonly) NSString *fillDocumentPath;
+@property (nonatomic, readonly) NSURL *fillDocumentURL;
+@property (nonatomic, readonly) NSString *documentLastURLString;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 124 - 0
AIPlayRingtones/Common/ASFileManager.m

@@ -0,0 +1,124 @@
+//
+//  ASFileManager.m
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+#import "ASFileManager.h"
+
+@implementation ASFileManager
+
+
++ (NSURL *)documentsDirectory {
+    return [NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
+}
+
++ (NSURL *)cacheDirectory {
+    return [NSFileManager.defaultManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask].firstObject;
+}
+
++ (void)copyFileWithOverwriteFrom:(NSURL *)sourceURL to:(NSURL *)targetURL {
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    @try {
+        [self removeItemFrom:targetURL];
+        [self checkFolderAndCreateFrom:targetURL];
+        [fileManager copyItemAtURL:sourceURL toURL:targetURL error:nil];
+        NSLog(@"文件复制成功!");
+    } @catch (NSException *exception) {
+        NSLog(@"文件复制失败: %@", exception.description);
+    }
+}
+
++ (void)removeItemFrom:(NSURL *)sourceURL {
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    @try {
+        if ([fileManager fileExistsAtPath:sourceURL.path]) {
+            [fileManager removeItemAtURL:sourceURL error:nil];
+        }
+        NSLog(@"文件删除成功!");
+    } @catch (NSException *exception) {
+        NSLog(@"文件删除失败: %@", exception.description);
+    }
+}
+
++ (void)checkFolderAndCreateFrom:(NSURL *)destinationURL {
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    NSURL *destinationDirectory = [destinationURL URLByDeletingLastPathComponent];
+    
+    if (![fileManager fileExistsAtPath:destinationDirectory.path]) {
+        @try {
+            [fileManager createDirectoryAtURL:destinationDirectory withIntermediateDirectories:YES attributes:nil error:nil];
+        } @catch (NSException *exception) {
+            NSLog(@"尝试创建文件夹失败: %@", exception.description);
+        }
+    }
+}
+
++ (BOOL)fileExistsAtURL:(NSURL *)url {
+    return [[NSFileManager defaultManager] fileExistsAtPath:url.path];
+}
+
++ (void)createDirectoryAtURL:(NSURL *)url error:(NSError **)error {
+    if (![self fileExistsAtURL:url]) {
+        [[NSFileManager defaultManager] createDirectoryAtURL:url withIntermediateDirectories:YES attributes:nil error:error];
+    }
+}
+
++ (NSString *)getCacheSubPathAtURL:(NSURL *)url {
+    NSArray *array = [url.path componentsSeparatedByString:@"/Caches/"];
+    NSString *cashFilePath = array.lastObject;
+    return cashFilePath ?: @"";
+}
+
+@end
+
+
+@implementation NSString (CachePath)
+
+- (BOOL)isCachesPath {
+    return [self containsString:@"/Caches/"];
+}
+
+- (NSString *)fillCachePath {
+    return [[ASFileManager cacheDirectory] URLByAppendingPathComponent:self].path;
+}
+
+- (NSURL *)fillCacheURL {
+    return [[ASFileManager cacheDirectory] URLByAppendingPathComponent:self];
+}
+
+- (NSString *)cachesLastURLString {
+    NSArray *parts = [self componentsSeparatedByString:@"/Caches/"];
+    if (parts.count > 1) {
+        return parts.lastObject;
+    }
+    return self;
+}
+
+@end
+
+
+@implementation NSString (DocumentPath)
+
+- (BOOL)isDocumentPath {
+    return [self containsString:@"/Documents/"];
+}
+
+- (NSString *)fillDocumentPath {
+    return [[ASFileManager documentsDirectory] URLByAppendingPathComponent:self].path;
+}
+
+- (NSURL *)fillDocumentURL {
+    return [[ASFileManager documentsDirectory] URLByAppendingPathComponent:self];
+}
+
+- (NSString *)documentLastURLString {
+    NSArray *parts = [self componentsSeparatedByString:@"/Documents/"];
+    if (parts.count > 1) {
+        return parts.lastObject;
+    }
+    return self;
+}
+
+@end

+ 7 - 0
AIPlayRingtones/Common/ASFileManager.swift

@@ -0,0 +1,7 @@
+//
+//  ASFileManager.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+

+ 17 - 0
AIPlayRingtones/Common/ASRandomTextTool.h

@@ -0,0 +1,17 @@
+//
+//  ASRandomTextTool.h
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ASRandomTextTool : NSObject
+- (instancetype)initWithTexts:(NSArray<NSString *> *)texts;
+- (NSString *)getRandomText;
+@end
+
+NS_ASSUME_NONNULL_END

+ 39 - 0
AIPlayRingtones/Common/ASRandomTextTool.m

@@ -0,0 +1,39 @@
+//
+//  ASRandomTextTool.m
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+#import "ASRandomTextTool.h"
+
+@interface ASRandomTextTool ()
+@property (nonatomic, strong) NSArray<NSString *> *texts;
+@property (nonatomic, assign) NSInteger lastIndex;
+@end
+
+@implementation ASRandomTextTool
+
+- (instancetype)initWithTexts:(NSArray<NSString *> *)texts {
+    self = [super init];
+    if (self) {
+        _texts = [texts copy];
+        _lastIndex = -1; // 初始化为无效索引
+    }
+    return self;
+}
+
+- (NSString *)getRandomText {
+    if (self.texts.count == 0) {
+        return nil;
+    }
+    
+    NSInteger randomIndex;
+    do {
+        randomIndex = arc4random_uniform((uint32_t)self.texts.count);
+    } while (randomIndex == self.lastIndex && self.texts.count > 1); // 只有1个元素时不循环
+    
+    self.lastIndex = randomIndex;
+    return self.texts[randomIndex];
+}
+@end

+ 8 - 25
AIPlayRingtones/Classes/Tool/WindowHelper.swift → AIPlayRingtones/Common/ASWindTool.swift

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

+ 1 - 1
AIPlayRingtones/Common/BaseClass/ASBaseNavContentBarView.m

@@ -21,7 +21,7 @@
         
         [_statuView mas_makeConstraints:^(MASConstraintMaker *make) {
             make.top.leading.trailing.equalTo(@0);
-            make.height.equalTo(@(k_Height_StatusBar));
+            make.height.equalTo(@(k_StatusBar_H));
         }];
         
         [_barView mas_makeConstraints:^(MASConstraintMaker *make) {

+ 130 - 0
AIPlayRingtones/Common/Common.swift

@@ -13,6 +13,91 @@ func kAddCommonGradientBg(view:UIView){
 }
 
 
+
+public func k_StatusBarH() -> CGFloat {
+    let scene = UIApplication.shared.connectedScenes.first;
+    guard let windowScene = scene as? UIWindowScene else {return 0};
+    guard let statusBarManager = windowScene.statusBarManager else {return 0};
+    return statusBarManager.statusBarFrame.height
+}
+
+public func k_Height_safeAreaInsetsBottom() -> CGFloat {
+    let scene = UIApplication.shared.connectedScenes.first;
+    guard let windowScene = scene as? UIWindowScene else {return 0};
+    guard let window = windowScene.windows.first else {return 0};
+    return window.safeAreaInsets.bottom;
+}
+/** 屏幕宽度 */
+public let k_ScreenWidth = UIScreen.main.bounds.size.width
+/** 屏幕高度 */
+public let k_ScreenHeight = UIScreen.main.bounds.size.height
+/* 导航栏高度 固定高度 = 44.0f */
+public let k_Height_NavBar :CGFloat = 44.0
+/** 状态栏高度 */
+public let k_StatusBar_H : CGFloat = k_StatusBarH()
+/** 状态栏+导航栏的高度 */
+public let k_Nav_Height: CGFloat = k_Height_NavBar + k_StatusBar_H
+/** 底部tabBar栏高度(不包含安全区,即:在 iphoneX 之前的手机) */
+public let k_TabBar_Height :CGFloat = 49.0
+/** 底部导航栏高度(包括安全区),一般使用这个值 */
+public let k_Height_TabBar :CGFloat = k_Height_safeAreaInsetsBottom() + k_TabBar_Height
+
+
+//判断是否是 x、及x以上 系列
+public func isIphoneX() -> Bool {
+    return k_Height_safeAreaInsetsBottom() > 0.0; // 底部安全区 > 0 时,
+    
+}
+
+//设计稿为 375*812 比例,所以比例系数为 375.0/kScreenWidth
+public let kDesignScale = k_ScreenWidth/375.0
+
+
+public func kGetUIH(designSize:CGSize,currentW:CGFloat) -> CGFloat {
+    let scale = designSize.width/currentW
+    return designSize.height/scale
+}
+    
+
+public func logPrint<T>(_ messsage: T) {
+    #if DEBUG
+    print(Date.hmsString + " \(messsage)")
+    #endif
+}
+
+public func appShortVersion() ->String{
+    let short = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
+    return short
+}
+
+public func appVersion() ->String{
+    return "V" + appShortVersion()
+}
+
+
+public func kPresentModalVC(target:UIViewController,
+                     modelVC:UIViewController,
+                       style:UIModalPresentationStyle = .overFullScreen,
+             transitionStyle:UIModalTransitionStyle = .coverVertical,
+                  completion: (() -> Void)? = nil){
+    let navi = ASBaseNavigationController(rootViewController: modelVC)
+    navi.modalPresentationStyle = style
+    navi.modalTransitionStyle = transitionStyle
+    target.present(navi, animated: true,completion: completion)
+}
+
+public func kPushVC(target:UIViewController,modelVC:UIViewController){
+    modelVC.hidesBottomBarWhenPushed = true
+    target.navigationController?.pushViewController(modelVC, animated: true)
+}
+
+public func kShowToastDataMissing(){
+    logPrint("参数缺失")
+}
+
+
+
+
 var modelIdentifier: String {
     var systemInfo = utsname()
     uname(&systemInfo)
@@ -214,3 +299,48 @@ public func kGetCollectionViewCellSize(sectionInset:UIEdgeInsets,
     let cellSize = CGSizeMake(w, h)
     return cellSize
 }
+
+
+public extension Array {
+    func safeAny(At index: Int) -> Element? {
+        if index >= 0,  index < count {
+            return self[index]
+        }
+        return nil
+    }
+}
+
+
+public extension Float {
+    var timeMMSS:String {
+        return "\(String(format: "%02d", Int(self) / 60)):\(String(format: "%02d", Int(self) % 60))"
+    }
+}
+
+public extension Date {
+    static var timestampInt: Int {
+        return Int(Date().timeIntervalSince1970)
+    }
+    
+    static var hmsString: String {
+        let formatter = DateFormatter()
+        formatter.locale = Locale(identifier: "en")
+        formatter.dateFormat = "HH:mm:ss:SSS"
+        return formatter.string(from: Date())
+    }
+}
+
+
+public extension UIImage {
+    // 压缩图片到指定尺寸
+    func compressSize(to size: CGSize) -> UIImage {
+        let targetSize = size
+        if self.size.width > targetSize.width || self.size.height > targetSize.height {
+            return kf.resize(to: targetSize)
+        }
+        return self
+    }
+    
+}
+
+

+ 0 - 0
AIPlayRingtones/Classes/Ex/OC/NSString+AS.h → AIPlayRingtones/Common/Ex/NSString+AS.h


+ 0 - 0
AIPlayRingtones/Classes/Ex/OC/NSString+AS.m → AIPlayRingtones/Common/Ex/NSString+AS.m


+ 105 - 0
AIPlayRingtones/Common/Ex/UIButton+AS.swift

@@ -0,0 +1,105 @@
+//
+//  UIButton+AS.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/27.
+//
+
+public extension UIButton {
+    static func createBtn(title: String? = nil,
+                             image: UIImage? = nil,
+                             backgroundImage: UIImage? = nil,
+                             backgroundColor: UIColor? = nil,
+                             font: UIFont? = nil,
+                             titleColor: UIColor? = nil,
+                             corner:CGFloat = 0,
+                             action: (() -> Void)? = nil) -> UIButton {
+        let button = UIButton(type: .custom)
+        button.setUpBtn(title: title,
+                           image: image,
+                           backgroundImage: backgroundImage,
+                           backgroundColor: backgroundColor,
+                           font: font,
+                           titleColor: titleColor,
+                           corner:corner,
+                           action: action)
+        return button
+    }
+
+    func setUpBtn(title: String? = nil,
+                             image: UIImage? = nil,
+                             backgroundImage: UIImage? = nil,
+                             backgroundColor: UIColor? = nil,
+                             font: UIFont? = nil,
+                             titleColor: UIColor? = nil,
+                             corner:CGFloat = 0,
+                             action: (() -> Void)? = nil){
+
+        if let image = image {
+            setImage(image, for: .normal)
+        }
+        if let title = title {
+            setTitle(title, for: .normal)
+        }
+        
+        if corner > 0 {
+            cornerRadius = corner
+        }
+   
+        if let backgroundImage = backgroundImage {
+            setBackgroundImage(backgroundImage, for: .normal)
+        }
+        if let font = font {
+            titleLabel?.font = font
+        }
+
+        showsTouchWhenHighlighted = false
+        adjustsImageWhenHighlighted = false
+
+        if let titleColor = titleColor {
+            setTitleColor(titleColor, for: .normal)
+        }
+        if let backgroundColor = backgroundColor {
+            self.backgroundColor = backgroundColor
+        }
+    
+        if let action = action {
+            actionClosure = action
+            addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
+        }
+
+    }
+
+    // 按钮点击事件
+    @objc private func buttonTapped() {
+        actionClosure?()
+    }
+}
+public extension UIButton {
+    
+    private struct AssociatedKeys {
+        static var actionKey = "ASButtonActionKey"
+    }
+    
+    private var actionClosure: (() -> Void)? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.actionKey) as? (() -> Void)
+        }
+        set {
+            objc_setAssociatedObject(self, &AssociatedKeys.actionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+    
+}
+
+
+public extension UIButton {
+    
+    func preventMultipleTaps(delay: Double = 0.75) {
+        isEnabled = false
+        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
+            self.isEnabled = true
+        }
+    }
+    
+}

+ 0 - 0
AIPlayRingtones/Classes/Ex/OC/UIColor+AS.h → AIPlayRingtones/Common/Ex/UIColor+AS.h


+ 0 - 0
AIPlayRingtones/Classes/Ex/OC/UIColor+AS.m → AIPlayRingtones/Common/Ex/UIColor+AS.m


+ 52 - 0
AIPlayRingtones/Common/Ex/UIFont+AS.swift

@@ -0,0 +1,52 @@
+//
+//  UIFont+AS.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+public extension String {
+    static let PingFangSC   = "PingFangSC"
+    static let PoppinsBoldItalic   = "Poppins-BoldItalic"
+}
+
+public extension UIFont {
+    static func font(name: String = .PingFangSC, size: CGFloat, weight: UIFont.Weight = .regular) -> UIFont {
+        guard !name.isEmpty,let _ = UIFont(name: name, size: size) else {
+            return UIFont.systemFont(ofSize: size, weight: weight)
+        }
+        var finalName = name
+        
+        let fontNames = UIFont.fontNames(forFamilyName: name)
+        switch weight {
+        case .light://细体 300
+            if let fontName = fontNames.first(where: { $0.lowercased().hasSuffix("-light") || $0.lowercased().hasSuffix("_light") }) {
+                finalName = fontName
+            }
+        case .medium://中黑体 500
+            if let fontName = fontNames.first(where: { $0.lowercased().hasSuffix("-medium") || $0.lowercased().hasSuffix("_medium") }) {
+                finalName = fontName
+            }
+        case .bold:// 粗体 700
+            if let fontName = fontNames.first(where: { $0.lowercased().hasSuffix("-bold") || $0.lowercased().hasSuffix("_bold") }) {
+                finalName = fontName
+            }
+        case .semibold://半粗体 600
+            if let fontName = fontNames.first(where: { $0.lowercased().hasSuffix("-semibold") || $0.lowercased().hasSuffix("_semibold") }) {
+                finalName = fontName
+            }
+        case .heavy: //粗黑体 800
+            if let fontName = fontNames.first(where: { $0.lowercased().hasSuffix("-heavy") || $0.lowercased().hasSuffix("_heavy") }) {
+                finalName = fontName
+            }
+        case .black: // 黑体 900
+            if let fontName = fontNames.first(where: { $0.lowercased().hasSuffix("-black") || $0.lowercased().hasSuffix("_black") }) {
+                finalName = fontName
+            }
+        default:
+            break
+        }
+        
+        return UIFont(name: finalName, size: size)!
+    }
+}

+ 14 - 22
AIPlayRingtones/Classes/Ex/UIImageView+Ex.swift → AIPlayRingtones/Common/Ex/UIImageView+AS.swift

@@ -1,27 +1,20 @@
 //
-//  UIImageView+Ex.swift
-//  TSLiveWallpaper
+//  UIImageView+AS.swift
+//  AIPlayRingtones
 //
-//  Created by 100Years on 2024/12/20.
+//  Created by mini on 2025/5/28.
 //
-import Kingfisher
-
 
+import Kingfisher
 
 public extension UIImageView {
-
-    /// 创建并配置 UIImageView
-    /// - Parameters:
-    ///   - imageName: 图片名称
-    ///   - contentMode: 内容模式,默认为 `.scaleAspectFit`
-    ///   - backgroundColor: 背景颜色,默认为透明
-    /// - Returns: 配置完成的 UIImageView 实例
-    static public func createImageView(
-                                image:UIImage? = nil,
-                                imageName: String? = nil,
-                                contentMode: UIView.ContentMode = .scaleAspectFit,
-                                backgroundColor: UIColor = .clear,
-                                corner: CGFloat = 0.0) -> UIImageView {
+ static func createImageV(
+        image:UIImage? = nil,
+        imageName: String? = nil,
+        contentMode: UIView.ContentMode = .scaleAspectFit,
+        backgroundColor: UIColor = .clear,
+        corner: CGFloat = 0.0)
+    -> UIImageView {
         let imageView = UIImageView()
                                     
         if let image = image{
@@ -38,7 +31,7 @@ public extension UIImageView {
         return imageView
     }
 
-    public func setAsyncImage(urlString: String?,
+    func setImageAsync(urlString: String?,
                      placeholder: UIImage? = nil,
                      contentMode: UIView.ContentMode = .scaleAspectFit,
                  adaptiveMode:Bool = false,
@@ -56,7 +49,7 @@ public extension UIImageView {
             return
         }
       
-        if urlString.count == 0 {
+        if urlString.isEmpty{
             completion?(nil)
             return
         }
@@ -76,7 +69,7 @@ public extension UIImageView {
             }){ result in
                 
                 if let image = try? result.get().image {
-                    kDelayMainShort {
+                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                         completion?(image)
                     }
                 }else{
@@ -94,5 +87,4 @@ public extension UIImageView {
             }
         }
     }
-
 }

+ 9 - 37
AIPlayRingtones/Classes/Ex/UILabel+Ex.swift → AIPlayRingtones/Common/Ex/UILabel+AS.swift

@@ -1,23 +1,12 @@
 //
-//  UILabel+Ex.swift
-//  TSLiveWallpaper
+//  UILabel+AS.swift
+//  AIPlayRingtones
 //
-//  Created by 100Years on 2024/12/20.
+//  Created by mini on 2025/5/27.
 //
 
 public extension UILabel {
-    /// 快速创建 UILabel
-    /// - Parameters:
-    ///   - text: 文本内容
-    ///   - font: 字体
-    ///   - textColor: 文本颜色
-    ///   - textAlignment: 文本对齐方式
-    ///   - numberOfLines: 行数,默认 1
-    ///   - backgroundColor: 背景颜色
-    ///   - adjustsFontSizeToFitWidth: 是否自适应宽度,默认 false
-    ///   - cornerRadius: 圆角,默认 0
-    /// - Returns: 配置好的 UILabel 实例
-    static public func createLabel(text: String? = nil,
+    static func createLabel(text: String? = nil,
                             font: UIFont? = nil,
                             textColor: UIColor? = nil,
                             textAlignment: NSTextAlignment = .left,
@@ -26,40 +15,23 @@ public extension UILabel {
                             adjustsFontSizeToFitWidth: Bool = false,
                             cornerRadius: CGFloat = 0) -> UILabel {
         let label = UILabel()
-        
-        // 设置文本内容
-        label.text = text
-        
-        // 设置字体
         if let font = font {
             label.font = font
         }
-        
-        // 设置文本颜色
         if let textColor = textColor {
             label.textColor = textColor
         }
-        
-        // 设置文本对齐方式
-        label.textAlignment = textAlignment
-        
-        // 设置行数
         label.numberOfLines = numberOfLines
-        
-        // 设置背景颜色
-        if let backgroundColor = backgroundColor {
-            label.backgroundColor = backgroundColor
-        }
-        
-        // 设置是否自适应宽度
+        label.text = text
         label.adjustsFontSizeToFitWidth = adjustsFontSizeToFitWidth
-        
-        // 设置圆角
+        label.textAlignment = textAlignment
         if cornerRadius > 0 {
             label.layer.cornerRadius = cornerRadius
             label.layer.masksToBounds = true
         }
-        
+        if let backgroundColor = backgroundColor {
+            label.backgroundColor = backgroundColor
+        }
         return label
     }
 }

+ 200 - 0
AIPlayRingtones/Common/Ex/UIView+AS.swift

@@ -0,0 +1,200 @@
+//
+//  UIView+AS.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+public extension UIView {
+
+    var borderColor: UIColor? {
+        set {
+            layer.borderColor = newValue?.cgColor
+        }
+        get {
+            if let cgColor = layer.borderColor {
+                return UIColor(cgColor: cgColor)
+            }
+            return nil
+        }
+    }
+    
+    
+    var x: CGFloat {
+        set {
+            frame.origin.x = newValue
+        }
+        get {
+            return frame.origin.x
+        }
+    }
+    
+    var y: CGFloat {
+        set {
+            frame.origin.y = newValue
+        }
+        get {
+            return frame.origin.y
+        }
+    }
+    
+    var width: CGFloat {
+        set {
+            frame.size.width = newValue
+        }
+        get {
+            return frame.size.width
+        }
+    }
+    
+    var height: CGFloat {
+        set {
+            frame.size.height = newValue
+        }
+        get {
+            return frame.size.height
+        }
+    }
+    
+    var size: CGSize {
+        get { frame.size }
+        set {
+            var rect = frame
+            rect.size = newValue
+            frame = rect
+        }
+    }
+    
+    var centerX: CGFloat {
+        set {
+            let newCenter = CGPoint(x: newValue, y: center.y)
+            center = newCenter
+        }
+        get {
+            return center.x
+        }
+    }
+    
+    var centerY: CGFloat {
+        set {
+            let newCenter = CGPoint(x: center.x, y: newValue)
+            center = newCenter
+        }
+        get {
+            return center.y
+        }
+    }
+    
+    var bottom: CGFloat {
+        get {
+            return frame.origin.y + frame.size.height
+        }
+    }
+    
+    var cornerRadius: CGFloat {
+        set {
+            clipsToBounds = true
+            layer.cornerRadius = newValue
+        }
+        get {
+            layer.cornerRadius
+        }
+    }
+
+    var borderWidth: CGFloat {
+        set {
+            layer.borderWidth = newValue
+        }
+        get {
+            layer.borderWidth
+        }
+    }
+    
+}
+
+public extension UIView {
+    func removeAllSubViews() {
+        subviews.forEach { subview in
+            subview.removeFromSuperview()
+        }
+    }
+
+    // 部分圆角(必须Frame已知)
+    func maskCorner(_ corners: UIRectCorner, radius: CGFloat) {
+        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
+        let maskLayer = CAShapeLayer()
+        maskLayer.frame = bounds
+        maskLayer.path = path.cgPath
+        layer.mask = maskLayer
+    }
+    
+    func addGradientBorder(
+        colors: [UIColor],
+        width: CGFloat = 2,
+        radius: CGFloat? = nil,
+        startPoint: CGPoint = CGPoint(x: 0, y: 0.5),
+        endPoint: CGPoint = CGPoint(x: 1, y: 0.5)
+    ) {
+        let gradientLayer = CAGradientLayer()
+        gradientLayer.name = "GradientBorder"
+        gradientLayer.endPoint = endPoint
+        gradientLayer.colors = colors.map { $0.cgColor }
+        gradientLayer.startPoint = startPoint
+        gradientLayer.frame = bounds
+        
+        let cornerRadius = radius ?? layer.cornerRadius
+        let path = UIBezierPath(
+            roundedRect: bounds.insetBy(dx: width/2, dy: width/2),
+            cornerRadius: cornerRadius
+        )
+        
+        let shapeLayer = CAShapeLayer()
+        shapeLayer.name = "GradientBorderMask"
+        shapeLayer.path = path.cgPath
+        shapeLayer.lineWidth = width
+        shapeLayer.fillColor = nil
+        shapeLayer.strokeColor = UIColor.black.cgColor
+        
+        gradientLayer.mask = shapeLayer
+        layer.addSublayer(gradientLayer)
+    }
+    
+    func addGradientBg(colors: [CGColor],
+                       startPoint: CGPoint = .zero,
+                       endPoint: CGPoint = CGPoint(x: 1, y: 1),
+                       layerSize: CGSize? = nil) {
+        let gl = CAGradientLayer()
+        gl.colors = colors
+        gl.zPosition = -1
+        gl.startPoint = startPoint
+        gl.endPoint = endPoint
+        gl.frame = CGRect(origin: .zero, size: layerSize ?? self.bounds.size)
+        layer.insertSublayer(gl, at: 0)
+    }
+    
+    func startRotating(duration: CFTimeInterval = 1.0,
+                     clockwise: Bool = true,
+                     repeatCount: Float = .greatestFiniteMagnitude) {
+
+        self.stopRotating()
+        
+        DispatchQueue.main.async {
+            let rotation = CABasicAnimation(keyPath: "transform.rotation.z")
+            rotation.repeatCount = repeatCount
+            rotation.toValue = clockwise ? CGFloat.pi * 2.0 : -CGFloat.pi * 2.0
+            rotation.isCumulative = true
+            rotation.timingFunction = CAMediaTimingFunction(name: .linear)
+            rotation.fromValue = 0
+            rotation.duration = duration
+            rotation.fillMode = .forwards
+            rotation.isRemovedOnCompletion = false
+            self.layer.add(rotation, forKey: "rotation")
+        }
+    }
+    
+    func stopRotating() {
+        DispatchQueue.main.async {
+            self.layer.removeAnimation(forKey: "rotation")
+        }
+    }
+}

+ 40 - 0
AIPlayRingtones/Common/Ex/UIViewController+AS.swift

@@ -0,0 +1,40 @@
+//
+//  UIViewController+AS.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+
+public extension UIViewController {
+    
+    func showCustomAlert(
+        title: String? = "",
+        message: String?,
+        rightActionString:String = "Delete".localized,
+        deleteHandler: (() -> Void)? = nil,
+        cancelHandler: (() -> Void)? = nil
+    ) {
+        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
+        alert.overrideUserInterfaceStyle = .dark
+        if let title = title {
+            alert.setValue(NSAttributedString(string: title, attributes: [
+                .font: UIFont.boldSystemFont(ofSize: 20),
+                .foregroundColor: UIColor.white
+            ]), forKey: "attributedTitle")
+        }
+        if let message = message {
+            alert.setValue(NSAttributedString(string: message, attributes: [
+                .font: UIFont.boldSystemFont(ofSize: 17),
+                .foregroundColor: UIColor.white
+            ]), forKey: "attributedMessage")
+        }
+        alert.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel) { _ in
+            cancelHandler?()
+        })
+        alert.addAction(UIAlertAction(title: rightActionString, style: .destructive) { _ in
+            deleteHandler?()
+        })
+        present(alert, animated: true, completion: nil)
+    }
+
+}

+ 27 - 0
AIPlayRingtones/Common/Ex/UIViewController+CustomAlert.h

@@ -0,0 +1,27 @@
+//
+//  UIViewController+CustomAlert.h
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/27.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface UIViewController (CustomAlert)
+
+- (void)showCustomAlertWithTitle:(NSString *)title
+                        message:(NSString *)message
+              rightActionString:(NSString *)rightActionString
+                  deleteHandler:(void(^)(void))deleteHandler
+                  cancelHandler:(void(^)(void))cancelHandler;
+
+- (void)showCustomAlertWithMessage:(NSString *)message
+                 rightActionString:(NSString *)rightActionString
+                     deleteHandler:(void(^)(void))deleteHandler
+                     cancelHandler:(void(^)(void))cancelHandler;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 84 - 0
AIPlayRingtones/Common/Ex/UIViewController+CustomAlert.m

@@ -0,0 +1,84 @@
+//
+//  UIViewController+CustomAlert.m
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/27.
+//
+
+#import "UIViewController+CustomAlert.h"
+
+@implementation UIViewController (CustomAlert)
+
+
+- (void)showCustomAlertWithTitle:(NSString *)title
+                        message:(NSString *)message
+              rightActionString:(NSString *)rightActionString
+                  deleteHandler:(void(^)(void))deleteHandler
+                  cancelHandler:(void(^)(void))cancelHandler {
+    
+    UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleAlert];
+    
+    // 自定义标题
+    if (title.length > 0) {
+        NSDictionary *titleAttributes = @{
+            NSFontAttributeName: [UIFont boldSystemFontOfSize:20],
+            NSForegroundColorAttributeName: [UIColor whiteColor]
+        };
+        NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString:title attributes:titleAttributes];
+        [alert setValue:attributedTitle forKey:@"attributedTitle"];
+    }
+    
+    // 自定义消息
+    if (message.length > 0) {
+        NSDictionary *messageAttributes = @{
+            NSFontAttributeName: [UIFont boldSystemFontOfSize:17],
+            NSForegroundColorAttributeName: [UIColor whiteColor]
+        };
+        NSAttributedString *attributedMessage = [[NSAttributedString alloc] initWithString:message attributes:messageAttributes];
+        [alert setValue:attributedMessage forKey:@"attributedMessage"];
+    }
+    
+    // 添加取消按钮
+    NSString *cancelTitle = NSLocalizedString(@"Cancel", nil);
+    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelTitle
+                                                          style:UIAlertActionStyleCancel
+                                                        handler:^(UIAlertAction * _Nonnull action) {
+        if (cancelHandler) {
+            cancelHandler();
+        }
+    }];
+    [alert addAction:cancelAction];
+    
+    // 添加删除/确认按钮
+    NSString *actionTitle = rightActionString ?: NSLocalizedString(@"Delete", nil);
+    UIAlertAction *deleteAction = [UIAlertAction actionWithTitle:actionTitle
+                                                          style:UIAlertActionStyleDestructive
+                                                        handler:^(UIAlertAction * _Nonnull action) {
+        if (deleteHandler) {
+            deleteHandler();
+        }
+    }];
+    [alert addAction:deleteAction];
+    
+    // 设置黑暗模式
+    if (@available(iOS 13.0, *)) {
+        alert.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
+    }
+    
+    // 显示弹窗
+    [self presentViewController:alert animated:YES completion:nil];
+}
+
+- (void)showCustomAlertWithMessage:(NSString *)message
+                 rightActionString:(NSString *)rightActionString
+                     deleteHandler:(void(^)(void))deleteHandler
+                     cancelHandler:(void(^)(void))cancelHandler {
+    
+    [self showCustomAlertWithTitle:nil
+                          message:message
+                rightActionString:rightActionString
+                    deleteHandler:deleteHandler
+                    cancelHandler:cancelHandler];
+}
+
+@end

+ 9 - 0
AIPlayRingtones/Common/GlobalImports.swift

@@ -0,0 +1,9 @@
+//
+//  GlobalImports.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/28.
+//
+@_exported import UIKit
+@_exported import SnapKit
+@_exported import Foundation

+ 5 - 5
AIPlayRingtones/Classes/GlobalImports/GlobalMacros.h → AIPlayRingtones/Common/GlobalMacros.h

@@ -1,5 +1,5 @@
 //
-//  GlobalImportsOC.h
+//  GlobalMacros.h
 //  AIPlayRingtones
 //
 //  Created by mini on 2025/5/27.
@@ -18,7 +18,7 @@
 #define k_TabBar_Height 49.0f
 
 // 状态栏高度
-static inline CGFloat k_Height_statusBar() {
+static inline CGFloat k_StatusBar_H() {
     if (@available(iOS 13.0, *)) {
         UIWindowScene *windowScene = [UIApplication sharedApplication].connectedScenes.allObjects.firstObject;
         return windowScene.statusBarManager.statusBarFrame.size.height;
@@ -49,8 +49,8 @@ static inline CGFloat k_Height_safeAreaInsetsBottom() {
 }
 
 // 组合高度
-#define k_Height_StatusBar k_Height_statusBar()
-#define k_Nav_Height (k_Height_NavBar + k_Height_StatusBar)
+#define k_StatusBar_H k_StatusBar_H()
+#define k_Nav_Height (k_Height_NavBar + k_StatusBar_H)
 #define k_Height_TabBar (k_Height_safeAreaInsetsBottom() + k_TabBar_Height)
 
 // 判断iPhoneX系列
@@ -58,6 +58,6 @@ static inline BOOL isIphoneX() {
     return k_Height_safeAreaInsetsBottom() > 0.0;
 }
 
-#define k_Height_StatusBar k_Height_statusBar()
+#define k_StatusBar_H k_StatusBar_H()
 
 #endif /* GlobalMacros_h */

+ 3 - 3
AIPlayRingtones/Common/TSAudioPlayer/TSAudioPlayer.swift

@@ -224,7 +224,7 @@ class TSAudioPlayer: NSObject {
 //            try audioSession.setActive(true) // 激活音频会话
 //
 //        } catch {
-//            dePrint("TSAudioPlayer 音频文件加载失败: \(error.localizedDescription)")
+//            logPrint("TSAudioPlayer 音频文件加载失败: \(error.localizedDescription)")
 //            return nil
 //        }
 //    }
@@ -233,7 +233,7 @@ class TSAudioPlayer: NSObject {
 //    func play() {
 //        guard let audioPlayer = audioPlayer else { return }
 //        let outputVolume = AVAudioSession.sharedInstance().outputVolume
-//        dePrint("TSAudioPlayer outputVolume\(outputVolume)")
+//        logPrint("TSAudioPlayer outputVolume\(outputVolume)")
 //        
 //        if outputVolume == 0.0 {
 //            TSToastShared.showToast(text: "Please turn up the volume".localized)
@@ -246,7 +246,7 @@ class TSAudioPlayer: NSObject {
 //            guard let self = self else { return }
 //            
 //            let currentTime = audioPlayer.currentTime
-//            dePrint("TSAudioPlayer Current playback time: \(currentTime) seconds")
+//            logPrint("TSAudioPlayer Current playback time: \(currentTime) seconds")
 //            currentTimeChanged?(currentTime)
 //          }
 //    }

+ 8 - 8
AIPlayRingtones/Common/TSAudioPlayer/TSBusinessAudioPlayer.swift

@@ -63,7 +63,7 @@ class TSBusinessAudioPlayer {
     
     var playProgress:Double{
         let playProgress = currentTime / duration
-//        dePrint("TSAudioPlayer playProgress = \(playProgress)")
+//        logPrint("TSAudioPlayer playProgress = \(playProgress)")
         return playProgress
     }
     
@@ -116,8 +116,8 @@ class TSBusinessAudioPlayer {
 
             let palyFile:(URL)->Void = { [weak self] url in
                 guard let self = self else { return }
-                debugPrint("TSAudioPlayer 正在播放url:\(currentURLString)")
-                debugPrint("TSAudioPlayer 正在播放path:\(url)")
+                logPrint("TSAudioPlayer 正在播放url:\(currentURLString)")
+                logPrint("TSAudioPlayer 正在播放path:\(url)")
                 self.audioPlayer = TSAudioPlayer(url: url)
                 self.audioPlayer?.setLoop(loop)
                 
@@ -132,7 +132,7 @@ class TSBusinessAudioPlayer {
                 }
                 
                 self.play()
-                dePrint(self.audioPlayer?.duration)
+                logPrint(self.audioPlayer?.duration)
                 
                 self.audioPlayer?.audioPlayerDidFinishHandle = { [weak self] flag in
                     guard let self = self else { return }
@@ -144,14 +144,14 @@ class TSBusinessAudioPlayer {
             
             isStopPlayingAfterLoading = false
             
-            if let path = self.currentLocalURL,TSFileManagerTool.fileExists(at: path){
+            if let path = self.currentLocalURL,ASFileManager.fileExists(at: path){
                 palyFile(path) //播放
                 
             }else{
                 self.changePlayerState(.loading(0.0))
                 
                 _ = ASDownloadManager.getDownLoadRing(urlString: urlString, progressHandler: { progress in
-                    dePrint("ASDownloadManager.etDownLoadRing progress = \(progress)")
+                    logPrint("ASDownloadManager.etDownLoadRing progress = \(progress)")
                 }, complete: {[weak self] url, success in
                     
                     guard let self = self else { return }
@@ -209,7 +209,7 @@ class TSBusinessAudioPlayer {
     func changePlayerState(_ state:PlayerState){
 
         if case .currentTime(let time) = state {} else {
-            debugPrint("TSAudioPlayer changePlayerState=\(state)")
+            logPrint("TSAudioPlayer changePlayerState=\(state)")
         }
         currentPlayerState = state
         kExecuteOnMainThread{
@@ -219,7 +219,7 @@ class TSBusinessAudioPlayer {
     }
      
     deinit {
-        dePrint("TSAudioPlayer TSBusinessAudioPlayer deinit")
+        logPrint("TSAudioPlayer TSBusinessAudioPlayer deinit")
     }
 }
 

+ 1 - 1
AIPlayRingtones/Common/TSBandRingTool/AudioTool.swift

@@ -40,7 +40,7 @@ class AudioTool {
         }
         
         completion?(copyBandURL)
-        debugPrint("===bandPath: \(copyBandURL)")
+        logPrint("===bandPath: \(copyBandURL)")
     }
     
 

+ 4 - 4
AIPlayRingtones/Common/TSBandRingTool/TSBandRingTool.swift

@@ -25,7 +25,7 @@ class TSBandRingTool:NSObject {
     }
     
     deinit {
-        dePrint("TSBandRingTool deinit")
+        logPrint("TSBandRingTool deinit")
     }
     func checkGarageBandInstallation() -> Bool {
         // GarageBand 的 URL Scheme
@@ -61,7 +61,7 @@ class TSBandRingTool:NSObject {
             completion?(false)
             return
         }
-        if TSFileManagerTool.fileExists(at: fileURL) == false{
+        if ASFileManager.fileExists(at: fileURL) == false{
             completion?(false)
             return
         }
@@ -73,7 +73,7 @@ class TSBandRingTool:NSObject {
                 self.shareRing(fileUrl: url)
             }else{
                 completion?(false)
-                dePrint("Failed to set, please try another")
+                logPrint("Failed to set, please try another")
             }
         }
     }
@@ -111,7 +111,7 @@ class TSBandRingTool:NSObject {
             // 延迟检查是否真正弹出
             DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                 if self.targetVC?.presentedViewController != vc {
-                    dePrint("⚠️ present 失败:系统未正确响应")
+                    logPrint("⚠️ present 失败:系统未正确响应")
                     // 这里可以触发回调或通知
                     self.playContentView.removeFromSuperview()
                 }

+ 4 - 4
AIPlayRingtones/Common/TSNetWork/TSNetWork+Business.swift

@@ -167,10 +167,10 @@ extension TSNetworkManager {
             completion: { result in
                 switch result {
                 case .success(let fileURL):
-                    dePrint("下载完成,文件保存在: \(fileURL.path)")
+                    logPrint("下载完成,文件保存在: \(fileURL.path)")
                     completion(fileURL,nil)
                 case .failure(let error):
-                    dePrint("下载失败: \(error.localizedDescription)")
+                    logPrint("下载失败: \(error.localizedDescription)")
                     completion(nil,error)
                 }
             }
@@ -223,7 +223,7 @@ extension TSNetworkManager {
         let urlString = TSNeURLType.upload.getUrlString()
         
         
-        dePrint("✈️✈️✈️网络请求:\(urlString)")
+        logPrint("✈️✈️✈️网络请求:\(urlString)")
         guard let url = URL(string: urlString) else {
             completion(nil,NSError(domain: "url nil", code: 0))
             return nil
@@ -235,7 +235,7 @@ extension TSNetworkManager {
             to: url
         )
         .uploadProgress { progress in
-            dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
+            logPrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
             progressHandler(Float(progress.fractionCompleted))
         }
         .responseString { response in

+ 17 - 17
AIPlayRingtones/Common/TSNetWork/TSNetworkManager.swift

@@ -60,7 +60,7 @@ class TSNetworkManager {
             let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [.withoutEscapingSlashes])//去掉转义
             urlRequest.httpBody = jsonData
         } catch {
-            dePrint("Failed to encode parameters: \(error)")
+            logPrint("Failed to encode parameters: \(error)")
             completion(.failure(error))
             return nil
         }
@@ -72,18 +72,18 @@ class TSNetworkManager {
             case .stream(let result):
                 switch result {
                 case .success(let string):
-                    dePrint("🚰🚰🚰Stream Received string string: \(string)")
+                    logPrint("🚰🚰🚰Stream Received string string: \(string)")
                     streamHandler(string)
                 case .failure(let error):
-                    dePrint("Stream error: \(error)")
+                    logPrint("Stream error: \(error)")
                     completion(.failure(error))
                 }
             case .complete(let cpl):
                 if let error = cpl.error {
-                    dePrint("Stream Request failed with error: \(error)")
+                    logPrint("Stream Request failed with error: \(error)")
                     completion(.failure(error))
                 } else {
-                    dePrint("Stream success")
+                    logPrint("Stream success")
                     completion(.success("Stream success"))
                 }
             }
@@ -97,8 +97,8 @@ class TSNetworkManager {
         parameters: [String: any Any & Sendable]? = nil,
         completion: @escaping (Result<Any, Error>) -> Void
     ) -> Request{
-        dePrint("✈️✈️✈️网络请求:\(urlString)")
-        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
+        logPrint("✈️✈️✈️网络请求:\(urlString)")
+        logPrint("✈️✈️✈️参数:\(String(describing: parameters))")
         
         var encoding: ParameterEncoding = URLEncoding.default
         if method == .post {
@@ -168,9 +168,9 @@ extension TSNetworkManager {
             customHeaders.forEach { defaultHeaders[$0.name] = $0.value }
         }
         
-        dePrint("✈️✈️✈️网络请求:\(urlString)")
-        dePrint("✈️✈️✈️dataArray:\(String(describing: dataArray))")
-        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
+        logPrint("✈️✈️✈️网络请求:\(urlString)")
+        logPrint("✈️✈️✈️dataArray:\(String(describing: dataArray))")
+        logPrint("✈️✈️✈️参数:\(String(describing: parameters))")
         // 2. 使用 Alamofire 上传 Data
         let request = afSession.upload(
             multipartFormData: { multipartFormData in
@@ -206,7 +206,7 @@ extension TSNetworkManager {
             .uploadProgress{ progress in
                 // 3. 上传进度回调
                 // 上传进度回调
-                dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
+                logPrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
                 progressHandler(progress)
             }
             .responseString{ response in
@@ -225,7 +225,7 @@ extension TSNetworkManager {
         progressHandler: @escaping (Progress) -> Void, // 上传进度回调
         completion: @escaping (Result<Any, Error>) -> Void
     )-> Request?{
-        dePrint("✈️✈️✈️网络请求:\(urlString)")
+        logPrint("✈️✈️✈️网络请求:\(urlString)")
         guard let url = URL(string: urlString) else {
             completion(.failure(NSError(domain: "url nil", code: 0)))
             return nil
@@ -235,7 +235,7 @@ extension TSNetworkManager {
             to: url
         )
         .uploadProgress { progress in
-            dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
+            logPrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
             progressHandler(progress)
         }
         .responseString { response in
@@ -346,16 +346,16 @@ extension TSNetworkManager {
     func handleSuccess(data:Any,
                        response: AFDataResponse<String>,
                        completion: @escaping (Result<Any, Error>) -> Void){
-        dePrint("🚗🚗🚗网络请求成功:\(String(describing: response.request?.url?.absoluteString))")
-        dePrint("🚗🚗🚗网络请求成功:\(response)")
+        logPrint("🚗🚗🚗网络请求成功:\(String(describing: response.request?.url?.absoluteString))")
+        logPrint("🚗🚗🚗网络请求成功:\(response)")
         completion(.success(data))
        }
     
     func handleFail(error:Error,
                     response: AFDataResponse<String>,
                     completion: @escaping (Result<Any, Error>) -> Void){
-        dePrint("🚗🚗🚗网络请求失败:\(String(describing: response.request?.url?.absoluteString))")
-        dePrint("🚗🚗🚗网络请求失败:\(response)")
+        logPrint("🚗🚗🚗网络请求失败:\(String(describing: response.request?.url?.absoluteString))")
+        logPrint("🚗🚗🚗网络请求失败:\(response)")
         completion(.failure(error))
     }
     

+ 5 - 17
AIPlayRingtones/Classes/Tool/TSCustomAlertController.swift → AIPlayRingtones/CommonView/ASCustomAlert.swift

@@ -1,14 +1,11 @@
 //
-//  TSCustomAlertController.swift
-//  Pods
+//  ASCustomAlert.swift
+//  AIPlayRingtones
 //
-//  Created by 100Years on 2025/3/26.
+//  Created by mini on 2025/5/28.
 //
 
-import UIKit
-
-
-public class TSCustomAlertController {
+public class ASCustomAlert {
     
     // MARK: - 配置模型
     public struct AlertConfig {
@@ -42,10 +39,7 @@ public class TSCustomAlertController {
     
     // MARK: - 显示弹窗
     public static func show(in viewController: UIViewController, config: AlertConfig) {
-        // 1. 创建AlertController (title设为空字符串而不是nil,避免自动上移)
         let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)
-        
-        // 2. 自定义message
         let messageAttributed = NSAttributedString(
             string: config.message,
             attributes: [
@@ -54,23 +48,17 @@ public class TSCustomAlertController {
             ]
         )
         alert.setValue(messageAttributed, forKey: "attributedMessage")
-        // 设置黑暗模式
-        alert.overrideUserInterfaceStyle = config.style
-        // 3. 添加取消按钮
         let cancelAction = UIAlertAction(title: config.cancelTitle, style: .default) { _ in
             config.cancelAction?()
         }
         cancelAction.setValue(config.cancelColor, forKey: "titleTextColor")
         alert.addAction(cancelAction)
-        
-        // 4. 添加确定按钮
         let confirmAction = UIAlertAction(title: config.confirmTitle, style: .default) { _ in
             config.confirmAction?()
         }
         confirmAction.setValue(config.confirmColor, forKey: "titleTextColor")
         alert.addAction(confirmAction)
-        
-        // 5. 显示弹窗
+        alert.overrideUserInterfaceStyle = config.style
         viewController.present(alert, animated: true)
     }
 }

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

@@ -9,7 +9,7 @@ class ASGeneratorErrorView: ASBaseView {
     
     var style:ASGeneratorView.Style = .generalError{
         didSet{
-            debugPrint("ASGeneratorErrorView style = \(style)")
+            logPrint("ASGeneratorErrorView style = \(style)")
             switch style {
             case .sensitiveError:
                 sensitiveErrorView()
@@ -30,7 +30,7 @@ class ASGeneratorErrorView: ASBaseView {
     }()
     
     lazy var errorImageView: UIImageView = {
-        let errorImageView = UIImageView.createImageView(imageName: "yellow_warning")
+        let errorImageView = UIImageView.createImageV(imageName: "yellow_warning")
         return errorImageView
     }()
     
@@ -41,7 +41,7 @@ class ASGeneratorErrorView: ASBaseView {
     
     lazy var submitBtn: UIButton = {
         let textColor = "#B48EFF".uiColor
-        let btn = UIButton.createButton(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
+        let btn = UIButton.createBtn(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
         btn.layer.borderColor = textColor.cgColor
         btn.layer.borderWidth = 1.0
         btn.titleLabel?.adjustsFontSizeToFitWidth = true

+ 1 - 1
AIPlayRingtones/CommonView/ASGeneratorView/ASGeneratorLoadingView.swift

@@ -66,7 +66,7 @@ class ASGeneratorLoadingView : ASBaseView {
     
     lazy var backgroundGenerateBtn: UIButton = {
         let textColor = "#B48EFF".uiColor
-        let btn = UIButton.createButton(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
+        let btn = UIButton.createBtn(title: "Generate in the background".localized,font: .font(size: 16),titleColor: textColor,corner: 24)
         btn.layer.borderColor = textColor.cgColor
         btn.layer.borderWidth = 1.0
         btn.titleLabel?.adjustsFontSizeToFitWidth = true

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

@@ -50,7 +50,7 @@ class ASGeneratorView: ASBaseView {
     }()
     
     lazy var xBtn: UIButton = {
-        let xBtn = UIButton.createButton(image: UIImage(named: "page_x")) { [weak self]  in
+        let xBtn = UIButton.createBtn(image: UIImage(named: "page_x")) { [weak self]  in
             guard let self = self else { return }
 //            self.isHidden = true
             clickClosePage?()
@@ -79,7 +79,7 @@ class ASGeneratorView: ASBaseView {
         //关闭按钮
         contentView.addSubview(xBtn)
         xBtn.snp.makeConstraints { make in
-            make.top.equalTo(k_Height_StatusBar + 4)
+            make.top.equalTo(k_StatusBar_H + 4)
             make.leading.equalTo(16)
             make.width.equalTo(36)
             make.height.equalTo(36)

+ 1 - 1
AIPlayRingtones/CommonView/ASPageNullView.swift

@@ -8,7 +8,7 @@
 class ASPageNullView: ASBaseView {
 
     lazy var imageView: UIImageView = {
-        return UIImageView.createImageView(imageName: "pageNull")
+        return UIImageView.createImageV(imageName: "pageNull")
     }()
     
     lazy var titleLabel: UILabel = {

+ 2 - 1
AIPlayRingtones/CommonView/ASRingLoadingView.swift

@@ -13,7 +13,8 @@ class ASRingLoadingView: ASBaseView {
     static let shared = ASRingLoadingView(frame: CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight))
     
     func showWindow(){
-        if let window = WindowHelper.getKeyWindow() {
+        let window:UIWindow? = ASWindTool.getKeyWindow()
+        if let window = window {
             window.addSubview(ASRingLoadingView.shared)
             ASRingLoadingView.shared.isRotating = true
         }

+ 17 - 17
AIPlayRingtones/CommonView/ASRingToneCellView.swift

@@ -37,15 +37,15 @@ class ASRingToneCellView: ASBaseView {
         return progressView
     }()
     
-    let playBtn = UIButton.createButton(image: UIImage(named: "cell_ring_play"))
+    let playBtn = UIButton.createBtn(image: UIImage(named: "cell_ring_play"))
     let nameLab = UILabel.createLabel(text: "--",font: .font(size: 14),textColor: .white,numberOfLines: 1)
     let timeLab = UILabel.createLabel(text:"--:--",font: .font(size: 12),textColor: .white.withAlphaComponent(0.6))
     
  
     var clickSetUpHandel:(()->Void)?
-    lazy var setRingBtn: ASUIExpandedTouchButton = {
-        let setRingBtn = ASUIExpandedTouchButton()
-        setRingBtn.setUpButton(image: UIImage(named: "cell_setRing_icon")){ [weak self]  in
+    lazy var setRingBtn: ASTouchBtn = {
+        let setRingBtn = ASTouchBtn()
+        setRingBtn.setUpBtn(image: UIImage(named: "cell_setRing_icon")){ [weak self]  in
             guard let self = self else { return }
             clickSetUpHandel?()
         }
@@ -54,9 +54,9 @@ class ASRingToneCellView: ASBaseView {
     }()
     
     var clickEditHandel:(()->Void)?
-    lazy var editBtn: ASUIExpandedTouchButton = {
-        let editBtn = ASUIExpandedTouchButton()
-        editBtn.setUpButton(image: UIImage(named: "edit_ring_icon")){ [weak self]  in
+    lazy var editBtn: ASTouchBtn = {
+        let editBtn = ASTouchBtn()
+        editBtn.setUpBtn(image: UIImage(named: "edit_ring_icon")){ [weak self]  in
             guard let self = self else { return }
             clickEditHandel?()
         }
@@ -64,13 +64,13 @@ class ASRingToneCellView: ASBaseView {
         return editBtn
     }()
     
-    lazy var clearBtn = UIButton.createButton{[weak self]  in
+    lazy var clearBtn = UIButton.createBtn{[weak self]  in
         guard let self = self else { return }
         clickPlayHandel?(self.isPlay)
     }
     
     lazy var rightShade: UIImageView = {
-        let rightShade = UIImageView.createImageView(imageName: "play_right_shade",contentMode: .scaleAspectFill)
+        let rightShade = UIImageView.createImageV(imageName: "play_right_shade",contentMode: .scaleAspectFill)
         rightShade.isHidden = true
         return rightShade
     }()
@@ -183,7 +183,7 @@ class ASRingToneCellView: ASBaseView {
     
     
     func setCoverImageView(urlString:String){
-        coverImageView.setAsyncImage(urlString: urlString,placeholder:.cellRing,contentMode: .scaleAspectFill,showLoading: false)
+        coverImageView.setImageAsync(urlString: urlString,placeholder:.cellRing,contentMode: .scaleAspectFill,showLoading: false)
     }
     
 }
@@ -200,7 +200,7 @@ extension ASRingToneCellView {
     }
     
     func handelAudioPlayerStateChange(state:TSBusinessAudioPlayer.PlayerState){
-        dePrint("ASRingToneCellView handelAudioPlayerStateChange=\(state),self=\(self)")
+        logPrint("ASRingToneCellView handelAudioPlayerStateChange=\(state),self=\(self)")
         switch state {
         case .loading(let progress):
             if progress == 0.0 {
@@ -233,7 +233,7 @@ class TSRingToneGenerateView:ASBaseView {
     var refreshHandel:(()->Void)?
 
     lazy var bgImageView: UIImageView = {
-        let bgImageView = UIImageView.createImageView(image: .cellRingBg,contentMode: .scaleToFill)
+        let bgImageView = UIImageView.createImageV(image: .cellRingBg,contentMode: .scaleToFill)
         return bgImageView
     }()
     
@@ -248,7 +248,7 @@ class TSRingToneGenerateView:ASBaseView {
     }()
     
     lazy var iconImageView: UIImageView = {
-        let iconImageView = UIImageView.createImageView(imageName: "cell_ring_icon",contentMode: .scaleToFill)
+        let iconImageView = UIImageView.createImageV(imageName: "cell_ring_icon",contentMode: .scaleToFill)
         return iconImageView
     }()
     
@@ -258,9 +258,9 @@ class TSRingToneGenerateView:ASBaseView {
         return infoLabel
     }()
     
-    lazy var refreshBtn: ASUIExpandedTouchButton = {
-        let refreshBtn = ASUIExpandedTouchButton()
-        refreshBtn.setUpButton(image: .refreshPurple){[weak self]  in
+    lazy var refreshBtn: ASTouchBtn = {
+        let refreshBtn = ASTouchBtn()
+        refreshBtn.setUpBtn(image: .refreshPurple){[weak self]  in
             guard let self = self else { return }
             refreshHandel?()
         }
@@ -347,7 +347,7 @@ class TSRingToneGenerateView:ASBaseView {
 class TSRingProgressView:ASBaseView {
     
     lazy var generateProgressView: UIImageView = {
-        let generateProgressView = UIImageView.createImageView(imageName: "cell_ring_progress",contentMode: .scaleToFill)
+        let generateProgressView = UIImageView.createImageV(imageName: "cell_ring_progress",contentMode: .scaleToFill)
         generateProgressView.backgroundColor = .white
         generateProgressView.cornerRadius = 1.0
         return generateProgressView

+ 16 - 32
AIPlayRingtones/Classes/View/TopLeftLabel.swift → AIPlayRingtones/CommonView/ASTLLabel.swift

@@ -1,12 +1,11 @@
 //
-//  TopLeftLabel.swift
+//  ASTLLabel.swift
 //  AIPlayRingtones
 //
-//  Created by mini on 2025/5/27.
+//  Created by mini on 2025/5/28.
 //
 
-import UIKit
-open class TopLeftLabel: UILabel {
+open class ASTLLabel: UILabel {
     
     // 设置内间距
     var textInsets: UIEdgeInsets = .zero {
@@ -15,6 +14,18 @@ open class TopLeftLabel: UILabel {
         }
     }
     
+    open override var intrinsicContentSize: CGSize {
+        // 根据内容大小和内间距调整固有内容大小
+        guard let text = text else { return .zero }
+        let textSize = (text as NSString).boundingRect(
+            with: CGSize(width: bounds.width - textInsets.left - textInsets.right, height: .greatestFiniteMagnitude),
+            options: [.usesLineFragmentOrigin, .usesFontLeading],
+            attributes: [.font: font ?? UIFont.systemFont(ofSize: 17)],
+            context: nil
+        ).size
+        return CGSize(width: textSize.width + textInsets.left + textInsets.right, height: textSize.height + textInsets.top + textInsets.bottom)
+    }
+    
     open override func drawText(in rect: CGRect) {
         // 根据内间距调整绘制区域
         let insetRect = rect.inset(by: textInsets)
@@ -33,32 +44,5 @@ open class TopLeftLabel: UILabel {
         // 调用父类的绘制方法
         super.drawText(in: adjustedRect)
     }
-    
-    open override var intrinsicContentSize: CGSize {
-        // 根据内容大小和内间距调整固有内容大小
-        guard let text = text else { return .zero }
-        let textSize = (text as NSString).boundingRect(
-            with: CGSize(width: bounds.width - textInsets.left - textInsets.right, height: .greatestFiniteMagnitude),
-            options: [.usesLineFragmentOrigin, .usesFontLeading],
-            attributes: [.font: font ?? UIFont.systemFont(ofSize: 17)],
-            context: nil
-        ).size
-        let width = textSize.width + textInsets.left + textInsets.right
-        let height = textSize.height + textInsets.top + textInsets.bottom
-        return CGSize(width: width, height: height)
-    }
-    
-    open override func sizeThatFits(_ size: CGSize) -> CGSize {
-        // 调整 `sizeThatFits` 的结果以包含内间距
-        guard let text = text else { return .zero }
-        let textSize = (text as NSString).boundingRect(
-            with: CGSize(width: size.width - textInsets.left - textInsets.right, height: .greatestFiniteMagnitude),
-            options: [.usesLineFragmentOrigin, .usesFontLeading],
-            attributes: [.font: font ?? UIFont.systemFont(ofSize: 17)],
-            context: nil
-        ).size
-        let width = textSize.width + textInsets.left + textInsets.right
-        let height = textSize.height + textInsets.top + textInsets.bottom
-        return CGSize(width: width, height: height)
-    }
+
 }

+ 12 - 0
AIPlayRingtones/CommonView/ASTouchBtn.swift

@@ -0,0 +1,12 @@
+//
+//  ASTouchBtn.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/27.
+//
+
+public class ASTouchBtn: UIButton {
+    override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
+        return self.bounds.insetBy(dx: -self.width * 0.5, dy: -self.height * 0.5).contains(point)
+    }
+}

+ 1 - 1
AIPlayRingtones/CommonView/ASViewTool.swift

@@ -24,7 +24,7 @@ func kAddNormalSubmitGradientBg(view:UIView){
 }
 
 func kCreateMoreInfoBtn() -> UIButton{
-    let btn = ASUIExpandedTouchButton()
+    let btn = ASTouchBtn()
     btn.setImage(UIImage(named: "more_info_white"), for: .normal)
     return btn
 }

+ 2 - 2
AIPlayRingtones/Data/ASDBHistoryManager.swift

@@ -72,7 +72,7 @@ class ASDBHistory: Object {
         ASRMShared.writeThread {
             if let index = listModels.firstIndex(where: { $0.id == id }) {
                 listModels.remove(at: index)
-                debugPrint("listModels.remove(at: \(index))")
+                logPrint("listModels.remove(at: \(index))")
             }
         }
     }
@@ -85,7 +85,7 @@ class ASDBHistory: Object {
                 realm.delete(allPersons)
             }
         } catch {
-            debugPrint("删除 TSDBPTPHistory 模型数据时出错: \(error)")
+            logPrint("删除 TSDBPTPHistory 模型数据时出错: \(error)")
         }
     }
     

+ 1 - 1
AIPlayRingtones/Data/ASRealmManager.swift

@@ -29,7 +29,7 @@ class ASRealmManager {
         }
         // 将修改后的配置设置为默认配置
         Realm.Configuration.defaultConfiguration = config
-        debugPrint("Realm 数据库已成功打开,版本号: \(newSchemaVersion)")
+        logPrint("Realm 数据库已成功打开,版本号: \(newSchemaVersion)")
     }
     
     var realm:Realm {

+ 2 - 2
AIPlayRingtones/OperationQueue/ASBaseOperation.swift

@@ -57,7 +57,7 @@ class ASBaseOperation: Operation , @unchecked Sendable{
     }
     
     override func cancel() {
-        debugPrint("ASBaseOperation cancel")
+        logPrint("ASBaseOperation cancel")
         cancelCleanContent()
         setCancelValue(value: true)
         if isExecuting {
@@ -125,6 +125,6 @@ class ASBaseOperation: Operation , @unchecked Sendable{
     
     
     deinit {
-        debugPrint("♻️♻️♻️ \(type(of: self)) deinit ♻️♻️♻️")
+        logPrint("♻️♻️♻️ \(type(of: self)) deinit ♻️♻️♻️")
     }
 }

+ 7 - 7
AIPlayRingtones/OperationQueue/ASBaseOperationQueue.swift

@@ -33,7 +33,7 @@ class ASBaseOperationQueue {
     
     init(maxConcurrentOperationCount: Int = 1) {
         queue.maxConcurrentOperationCount = maxConcurrentOperationCount
-        dePrint("ASBaseOperationQueue operationCountObservation")
+        logPrint("ASBaseOperationQueue operationCountObservation")
         // 监听 operationCount 的变化
            operationCountObservation = queue.observe(\.operationCount, options: [.new]) { [weak self] (queue, change) in
                guard let _ = self else { return }
@@ -51,7 +51,7 @@ class ASBaseOperationQueue {
             let operation = type.init(uuid: uuid)
             activeOperations[uuid] = operation
             queue.addOperation(operation)
-            dePrint("ASBaseOperationQueue addOperation \(operation)")
+            logPrint("ASBaseOperationQueue addOperation \(operation)")
             cancellables[uuid] = operation.$operationStatePblished.sink { [weak self] state in
                 guard let self = self else { return }
                 
@@ -67,7 +67,7 @@ class ASBaseOperationQueue {
                 default: break
                 }
                 
-                dePrint("ASBaseOperationQueue $operationStatePblished =\(state)")
+                logPrint("ASBaseOperationQueue $operationStatePblished =\(state)")
             }
             latestOperation = operation
             return operation
@@ -97,12 +97,12 @@ class ASBaseOperationQueue {
     }
 
     func clearOperationsData(uuid: String) {
-        dePrint("ASBaseOperationQueue cancelOperations activeOperations 前=\(activeOperations)")
-        dePrint("ASBaseOperationQueue cancelOperations cancellables 前=\(cancellables)")
+        logPrint("ASBaseOperationQueue cancelOperations activeOperations 前=\(activeOperations)")
+        logPrint("ASBaseOperationQueue cancelOperations cancellables 前=\(cancellables)")
         activeOperations.removeValue(forKey: uuid)
         cancellables.removeValue(forKey: uuid)
-        dePrint("ASBaseOperationQueue cancelOperations activeOperations 后=\(activeOperations)")
-        dePrint("ASBaseOperationQueue cancelOperations cancellables 后=\(cancellables)")
+        logPrint("ASBaseOperationQueue cancelOperations activeOperations 后=\(activeOperations)")
+        logPrint("ASBaseOperationQueue cancelOperations cancellables 后=\(cancellables)")
     }
     func waitUntilAllOperationsAreFinished() {
         queue.waitUntilAllOperationsAreFinished()

+ 9 - 9
AIPlayRingtones/OperationQueue/Generate/ASGenerateBaseOperation.swift

@@ -53,12 +53,12 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
     
     @Published var stateDatauPblished:(ASProgressState,ASActionInfoModel?) = (ASProgressState.none,nil){
         didSet{
-//            dePrint("ASBaseOperation stateDatauPblished didSet = \(stateDatauPblished)")
+//            logPrint("ASBaseOperation stateDatauPblished didSet = \(stateDatauPblished)")
 //                if let block = self.stateDataPblishedChanged{
-//                    debugPrint("刷新进度block 真=\(self.stateDatauPblished)")
+//                    logPrint("刷新进度block 真=\(self.stateDatauPblished)")
 //                    self.stateDataPblishedChanged?(self.stateDatauPblished.0,self.stateDatauPblished.1)
 //                }else{
-//                    debugPrint("刷新进度block 空=\(self.stateDatauPblished)")
+//                    logPrint("刷新进度block 空=\(self.stateDatauPblished)")
 //                }
             
             DispatchQueue.main.async {
@@ -129,7 +129,7 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
             }
             
             if let error = error {
-                debugPrint("getActionInfo error error = \(error)")
+                logPrint("getActionInfo error error = \(error)")
                 handleFailInfoModel(errorString: error.tsDesc,code: error.tsCode)
                 return
             }
@@ -158,11 +158,11 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                                     let progressInt = Int(progress*10.0)
                                     let progressString = "Generating".localized + " \(90 + progressInt)%"
                                 stateDatauPblished = (.progress(kPercentScale+Float(progress)*0.1,progressString),currentActionInfoModel)
-                                    dePrint("生成后下载进度 \(progress)")
+                                    logPrint("生成后下载进度 \(progress)")
                             } complete: { [weak self] url, success in
                                 guard let self = self else { return }
                                 if let url = url {
-                                    genmojiModel.ringSavePath = url.path.documentLastURLString
+                                    genmojiModel.ringSavePath = url.path.documentLastURL
                  
                                     if let info = TSBusinessAudioPlayer.getAudioFileInfo(path: url.path) {
                                         if let duration = info.durationInSeconds {
@@ -183,7 +183,7 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                             successBlock()
                         }
                     case .failed:
-                        debugPrint("getActionInfo error failed")
+                        logPrint("getActionInfo error failed")
                         handleFailInfoModel(errorString:genmojiModel.response.codeErrorMsg,code: genmojiModel.response.code)
                     default:
                         let progressText = generating(progress: genmojiModel.percent)
@@ -198,7 +198,7 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
                     return
                 }
             }
-            debugPrint("getActionInfo error nil")
+            logPrint("getActionInfo error nil")
             handleFailInfoModel(errorString: nil)
             
         }
@@ -228,7 +228,7 @@ class ASGenerateBaseOperation: ASBaseOperation , @unchecked Sendable{
      
 
     override func cancelCleanContent() {
-        debugPrint("cancelCleanContent")
+        logPrint("cancelCleanContent")
         stopNetwork = true
         queryRequest?.cancel()
     }

+ 1 - 1
AIPlayRingtones/OperationQueue/Generate/ASGenerateRingToRingOperation.swift

@@ -21,7 +21,7 @@ class ASGenerateRingToRingOperationQueue: ASGenerateBaseOperationQueue {
     
     override func getUUIDData(uuid:String)->(ASProgressState,ASActionInfoModel?){
         if let PosterOperation = ASGenerateRingToRingOperationQueue.shared.findOperation(uuid: uuid) as? ASGenerateRingToRingOperation {
-            dePrint("ASBaseOperation stateDatauPblished 发送 = \(PosterOperation.stateDatauPblished)")
+            logPrint("ASBaseOperation stateDatauPblished 发送 = \(PosterOperation.stateDatauPblished)")
             return (PosterOperation.stateDatauPblished.0,PosterOperation.currentActionInfoModel)
         }
         return (.none,ASActionInfoModel())

+ 11 - 11
AIPlayRingtones/OperationQueue/Generate/ASGenerateTextToRingOperation.swift

@@ -21,7 +21,7 @@ class ASGenerateTextToRingOperationQueue: ASGenerateBaseOperationQueue {
     
     override func getUUIDData(uuid:String)->(ASProgressState,ASActionInfoModel?){
         if let PosterOperation = ASGenerateTextToRingOperationQueue.shared.findOperation(uuid: uuid) as? ASGenerateTextToRingOperation {
-            dePrint("ASBaseOperation stateDatauPblished 发送 = \(PosterOperation.stateDatauPblished)")
+            logPrint("ASBaseOperation stateDatauPblished 发送 = \(PosterOperation.stateDatauPblished)")
             return (PosterOperation.stateDatauPblished.0,PosterOperation.currentActionInfoModel)
         }
         return (.none,ASActionInfoModel())
@@ -58,7 +58,7 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
         }
 
         currentActionInfoModel = model
-        dePrint("model actionStatus 发出=\(model.actionStatus)")
+        logPrint("model actionStatus 发出=\(model.actionStatus)")
         currentActionInfoModelChanged?(currentActionInfoModel)
     }
 
@@ -71,9 +71,9 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
         if currentActionInfoModel.id == 0 {
             return
         }
-        debugPrint("saveDataDB ASRMShared.ringDBHistory.listModels.count = \(ASRMShared.ringDBHistory.listModels.count),currentActionInfoModel.id = \(currentActionInfoModel.id)")
+        logPrint("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)")
+        logPrint("saveDataDB ASRMShared.ringDBHistory.listModels.count = \(ASRMShared.ringDBHistory.listModels.count)")
     }
     override func handleGenerateSuccess() {
         //只要是生成成功,就一定保存数据,且消耗次数
@@ -85,20 +85,20 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
         }
         
         
-        guard let window = WindowHelper.getKeyWindow() else {
-            debugPrint("getKeyWindow nil")
+        guard let window = ASWindTool.getKeyWindow() else {
+            logPrint("getKeyWindow nil")
             return
         }
         
-        guard let rootVC = WindowHelper.topViewController() else {
-            debugPrint("handleGenerateSuccess topViewController nil")
+        guard let rootVC = ASWindTool.topViewController() else {
+            logPrint("handleGenerateSuccess topViewController nil")
             return
         }
         
         let copyModel = self.currentActionInfoModel.copy()
         if let cyModel = copyModel as? ASActionInfoModel {
             let topY = k_Nav_Height+10
-//            debugPrint("topY=\(topY)")
+//            logPrint("topY=\(topY)")
             AudioServicesPlaySystemSound(1520)
             kSaveSuccesswShared.show(atView: window,text: "Successfully generated".localized,deadline: 5.0,bottom: kSaveSuccesswShared.getBottom(topY: topY)) {
                 let gennerateVC = ASRingGeneratorVC(generateStyleModel: ASGenerateStyleModel(),infoModel: cyModel) { model in }
@@ -107,7 +107,7 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
                 rootVC.present(gennerateVC, animated: true)
             }
         }else{
-            debugPrint("copyModel as? ASActionInfoModel error")
+            logPrint("copyModel as? ASActionInfoModel error")
         }
     }
     
@@ -270,7 +270,7 @@ class ASGenerateTextToRingOperation: ASGenerateBaseOperation , @unchecked Sendab
 
     override func cancelCleanContent() {
         super.cancelCleanContent()
-        debugPrint("cancelCleanContent")
+        logPrint("cancelCleanContent")
         creatRequest?.cancel()
     }
 }