100Years преди 1 месец
родител
ревизия
a096151ffc
променени са 100 файла, в които са добавени 822 реда и са изтрити 204 реда
  1. 28 16
      AIRingtone.xcodeproj/project.pbxproj
  2. 78 0
      AIRingtone.xcodeproj/xcshareddata/xcschemes/AIRingtone.xcscheme
  3. 8 0
      AIRingtone.xcodeproj/xcuserdata/100years.xcuserdatad/xcschemes/xcschememanagement.plist
  4. 6 0
      AIRingtone/Assets.xcassets/AIPhoto/example/Contents.json
  5. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_0.imageset/Contents.json
  6. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_0.imageset/photo_example_0@2x.png
  7. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_0.imageset/photo_example_0@3x.png
  8. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_1.imageset/Contents.json
  9. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_1.imageset/photo_example_1@2x.png
  10. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_1.imageset/photo_example_1@3x.png
  11. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_2.imageset/Contents.json
  12. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_2.imageset/photo_example_2@2x.png
  13. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_2.imageset/photo_example_2@3x.png
  14. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_0.imageset/Contents.json
  15. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_0.imageset/poster_example_0@2x.png
  16. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_0.imageset/poster_example_0@3x.png
  17. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_1.imageset/Contents.json
  18. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_1.imageset/poster_example_1@2x.png
  19. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_1.imageset/poster_example_1@3x.png
  20. 22 0
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_2.imageset/Contents.json
  21. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_2.imageset/poster_example_2@2x.png
  22. BIN
      AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_2.imageset/poster_example_2@3x.png
  23. BIN
      AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@2x.png
  24. BIN
      AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@3x.png
  25. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@2x.png
  26. BIN
      AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@3x.png
  27. BIN
      AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@2x.png
  28. BIN
      AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@3x.png
  29. BIN
      AIRingtone/Assets.xcassets/App-Icon.imageset/App-Icon 1.png
  30. 21 0
      AIRingtone/Assets.xcassets/App-Icon.imageset/Contents.json
  31. 117 32
      AIRingtone/Assets.xcassets/AppIcon.appiconset/Contents.json
  32. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-1024.png
  33. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
  34. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
  35. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
  36. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
  37. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-38@2x.png
  38. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-38@3x.png
  39. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
  40. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png
  41. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
  42. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
  43. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-64@2x.png
  44. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-64@3x.png
  45. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-68@2x.png
  46. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
  47. BIN
      AIRingtone/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
  48. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/textView_bg@2x.png
  49. BIN
      AIRingtone/Assets.xcassets/Common/TextView/textView_bg.imageset/textView_bg@3x.png
  50. 22 0
      AIRingtone/Assets.xcassets/Common/clear_gary_text.imageset/Contents.json
  51. BIN
      AIRingtone/Assets.xcassets/Common/clear_gary_text.imageset/clear_gary_text@2x.png
  52. BIN
      AIRingtone/Assets.xcassets/Common/clear_gary_text.imageset/clear_gary_text@3x.png
  53. BIN
      AIRingtone/Assets.xcassets/Common/ringtone_pause.imageset/ringtone_pause@2x.png
  54. BIN
      AIRingtone/Assets.xcassets/Common/ringtone_pause.imageset/ringtone_pause@3x.png
  55. BIN
      AIRingtone/Assets.xcassets/Common/ringtone_play.imageset/ringtone_play@2x.png
  56. BIN
      AIRingtone/Assets.xcassets/Common/ringtone_play.imageset/ringtone_play@3x.png
  57. BIN
      AIRingtone/Assets.xcassets/Setting/nav_title_setting.imageset/nav_title_setting@2x.png
  58. BIN
      AIRingtone/Assets.xcassets/Setting/nav_title_setting.imageset/nav_title_setting@3x.png
  59. 1 1
      AIRingtone/Assets.xcassets/Theme/icon/desktop_bg.imageset/Contents.json
  60. BIN
      AIRingtone/Assets.xcassets/Theme/icon/desktop_bg.imageset/desktop_bg.png
  61. BIN
      AIRingtone/Assets.xcassets/Theme/icon/desktop_bg.imageset/desktop_bg@2x.png
  62. BIN
      AIRingtone/Assets.xcassets/Theme/icon/sound_loading_icon.imageset/sound_loading_icon@2x.png
  63. BIN
      AIRingtone/Assets.xcassets/Theme/icon/sound_loading_icon.imageset/sound_loading_icon@3x.png
  64. BIN
      AIRingtone/Assets.xcassets/Theme/icon/sound_off_icon.imageset/sound_off_icon@2x.png
  65. BIN
      AIRingtone/Assets.xcassets/Theme/icon/sound_off_icon.imageset/sound_off_icon@3x.png
  66. BIN
      AIRingtone/Assets.xcassets/Theme/icon/sound_on_icon.imageset/sound_on_icon@2x.png
  67. BIN
      AIRingtone/Assets.xcassets/Theme/icon/sound_on_icon.imageset/sound_on_icon@3x.png
  68. BIN
      AIRingtone/Assets.xcassets/Theme/nav_title_theme.imageset/nav_title_theme@2x.png
  69. BIN
      AIRingtone/Assets.xcassets/Theme/nav_title_theme.imageset/nav_title_theme@3x.png
  70. BIN
      AIRingtone/Assets.xcassets/Theme/theme_phone_Island.imageset/theme_phone_Island@2x.png
  71. BIN
      AIRingtone/Assets.xcassets/Theme/theme_phone_Island.imageset/theme_phone_Island@3x.png
  72. 6 0
      AIRingtone/Assets.xcassets/Tutorials/Contents.json
  73. 21 0
      AIRingtone/Assets.xcassets/Tutorials/tutorials_ringtone.imageset/Contents.json
  74. BIN
      AIRingtone/Assets.xcassets/Tutorials/tutorials_ringtone.imageset/tutorials_ringtone.png
  75. 10 20
      AIRingtone/Base.lproj/LaunchScreen.storyboard
  76. 127 0
      AIRingtone/Business/Data/TSUserDefaultData.swift
  77. 3 2
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVC.swift
  78. 27 1
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/View/TSAIPhotoImageCell.swift
  79. 14 1
      AIRingtone/Business/TSAIPhotoVC/TSAIPhotoVC.swift
  80. 1 1
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicBrowseVC/TSGeneralPicBrowseVC.swift
  81. 1 1
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/Model/TSGeneralPicModel.swift
  82. 14 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC+Event.swift
  83. 3 0
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC.swift
  84. 5 7
      AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGenneralPicVM.swift
  85. 4 3
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSCreatBtnView.swift
  86. 15 12
      AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptTextView.swift
  87. 37 39
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/TSAIRintoneVC.swift
  88. 30 21
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/View/TSAIRintoneHistoryCell.swift
  89. 12 2
      AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/ViewModel/TSAIRintoneVM.swift
  90. 0 6
      AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVC+Event.swift
  91. 14 3
      AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVC.swift
  92. 24 22
      AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVM.swift
  93. 2 2
      AIRingtone/Business/TSSetingVC/SetingVC/TSSetingViewModel.swift
  94. 1 1
      AIRingtone/Business/TSSetingVC/SetingVC/View/TSSettingListView.swift
  95. 1 1
      AIRingtone/Business/TSTabBarController/TSTabBarController.swift
  96. 9 4
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/TSThemeBrowseVC.swift
  97. 1 0
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/VM/TSThemeBrowseVM.swift
  98. 3 2
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTBBtnView.swift
  99. 3 3
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTBDesktopPreviewView.swift
  100. 21 1
      AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTSIslandView.swift

+ 28 - 16
AIRingtone.xcodeproj/project.pbxproj

@@ -47,6 +47,7 @@
 		A8272E9D2D7A8F4600F1C814 /* TSGeneralRintoneVC+Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8272E9C2D7A8F3A00F1C814 /* TSGeneralRintoneVC+Event.swift */; };
 		A8272E9F2D7A8F6500F1C814 /* TSGeneralRintoneVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8272E9E2D7A8F6000F1C814 /* TSGeneralRintoneVM.swift */; };
 		A8272EBB2D7AFD0F00F1C814 /* TSBusinessAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8272EBA2D7AFD0D00F1C814 /* TSBusinessAudioPlayer.swift */; };
+		A83503CD2D7ED1440067002A /* TSThemeTutorialsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83503CC2D7ED1430067002A /* TSThemeTutorialsVC.swift */; };
 		A83F871D2D79409B00D29B1B /* TSUserDefaultData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F871C2D79409300D29B1B /* TSUserDefaultData.swift */; };
 		A83F87202D794FF000D29B1B /* TSAIPhotoImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F871F2D794FE600D29B1B /* TSAIPhotoImageCell.swift */; };
 		A83F87222D7953C000D29B1B /* Notification+TSEx.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83F87212D7953BA00D29B1B /* Notification+TSEx.swift */; };
@@ -70,7 +71,6 @@
 		A868A8C92D76A45900F6D884 /* TSThemeSetItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8C82D76A45200F6D884 /* TSThemeSetItemView.swift */; };
 		A868A8CE2D76AAC600F6D884 /* TSThemeSetRingToneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8CD2D76AAAF00F6D884 /* TSThemeSetRingToneView.swift */; };
 		A868A8D02D76D03900F6D884 /* TSRingToneCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8CF2D76D02300F6D884 /* TSRingToneCellView.swift */; };
-		A868A8D32D76DE7600F6D884 /* TSThemeSetVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8D22D76DC9E00F6D884 /* TSThemeSetVM.swift */; };
 		A868A8D52D76E41800F6D884 /* TSSetContactAvatar.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8D42D76E40E00F6D884 /* TSSetContactAvatar.swift */; };
 		A868A8DB2D76F00C00F6D884 /* TSBandRingTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8DA2D76F00800F6D884 /* TSBandRingTool.swift */; };
 		A868A8DE2D76F91500F6D884 /* AudioTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868A8DD2D76F91500F6D884 /* AudioTool.swift */; };
@@ -104,6 +104,7 @@
 		A8CC55892D798E5D002E0CAA /* TSTextGeneralRintoneVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8CC55882D798E5A002E0CAA /* TSTextGeneralRintoneVM.swift */; };
 		A8CC558B2D79905A002E0CAA /* TSCreatBtnView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8CC558A2D799051002E0CAA /* TSCreatBtnView.swift */; };
 		A8CC55902D799F9F002E0CAA /* TSAIRintoneVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8CC558F2D799F9C002E0CAA /* TSAIRintoneVM.swift */; };
+		A8DEC2702D7C395C002EB948 /* TSThemeCopyrightVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8DEC26F2D7C395B002EB948 /* TSThemeCopyrightVC.swift */; };
 		F5FF0EC10B0056B65FDB9C78 /* Pods_AIRingtone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39C823AB7F3D49E8B2356E07 /* Pods_AIRingtone.framework */; };
 /* End PBXBuildFile section */
 
@@ -153,6 +154,7 @@
 		A8272E9C2D7A8F3A00F1C814 /* TSGeneralRintoneVC+Event.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSGeneralRintoneVC+Event.swift"; sourceTree = "<group>"; };
 		A8272E9E2D7A8F6000F1C814 /* TSGeneralRintoneVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSGeneralRintoneVM.swift; sourceTree = "<group>"; };
 		A8272EBA2D7AFD0D00F1C814 /* TSBusinessAudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBusinessAudioPlayer.swift; sourceTree = "<group>"; };
+		A83503CC2D7ED1430067002A /* TSThemeTutorialsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeTutorialsVC.swift; sourceTree = "<group>"; };
 		A83F871C2D79409300D29B1B /* TSUserDefaultData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSUserDefaultData.swift; sourceTree = "<group>"; };
 		A83F871F2D794FE600D29B1B /* TSAIPhotoImageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIPhotoImageCell.swift; sourceTree = "<group>"; };
 		A83F87212D7953BA00D29B1B /* Notification+TSEx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+TSEx.swift"; sourceTree = "<group>"; };
@@ -176,7 +178,6 @@
 		A868A8C82D76A45200F6D884 /* TSThemeSetItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeSetItemView.swift; sourceTree = "<group>"; };
 		A868A8CD2D76AAAF00F6D884 /* TSThemeSetRingToneView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeSetRingToneView.swift; sourceTree = "<group>"; };
 		A868A8CF2D76D02300F6D884 /* TSRingToneCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSRingToneCellView.swift; sourceTree = "<group>"; };
-		A868A8D22D76DC9E00F6D884 /* TSThemeSetVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeSetVM.swift; sourceTree = "<group>"; };
 		A868A8D42D76E40E00F6D884 /* TSSetContactAvatar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSSetContactAvatar.swift; sourceTree = "<group>"; };
 		A868A8DA2D76F00800F6D884 /* TSBandRingTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBandRingTool.swift; sourceTree = "<group>"; };
 		A868A8DD2D76F91500F6D884 /* AudioTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioTool.swift; sourceTree = "<group>"; };
@@ -214,6 +215,7 @@
 		A8CC55882D798E5A002E0CAA /* TSTextGeneralRintoneVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralRintoneVM.swift; sourceTree = "<group>"; };
 		A8CC558A2D799051002E0CAA /* TSCreatBtnView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSCreatBtnView.swift; sourceTree = "<group>"; };
 		A8CC558F2D799F9C002E0CAA /* TSAIRintoneVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIRintoneVM.swift; sourceTree = "<group>"; };
+		A8DEC26F2D7C395B002EB948 /* TSThemeCopyrightVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSThemeCopyrightVC.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -453,6 +455,8 @@
 		A80EDF0D2D718E42003CD332 /* TSThemeVC */ = {
 			isa = PBXGroup;
 			children = (
+				A83503CB2D7ED1340067002A /* TSThemeTutorialsVC */,
+				A8DEC26E2D7C3948002EB948 /* TSThemeCopyrightVC */,
 				A868A8C52D76A43300F6D884 /* TSThemeSetVC */,
 				A868A8C42D76A42700F6D884 /* TSThemeVC */,
 				A868A8A82D75889700F6D884 /* TSThemeBrowseVC */,
@@ -544,6 +548,14 @@
 			path = TSGeneralRintoneVC;
 			sourceTree = "<group>";
 		};
+		A83503CB2D7ED1340067002A /* TSThemeTutorialsVC */ = {
+			isa = PBXGroup;
+			children = (
+				A83503CC2D7ED1430067002A /* TSThemeTutorialsVC.swift */,
+			);
+			path = TSThemeTutorialsVC;
+			sourceTree = "<group>";
+		};
 		A83F871B2D79408300D29B1B /* Data */ = {
 			isa = PBXGroup;
 			children = (
@@ -658,7 +670,6 @@
 		A868A8C52D76A43300F6D884 /* TSThemeSetVC */ = {
 			isa = PBXGroup;
 			children = (
-				A868A8D12D76DC9900F6D884 /* VM */,
 				A868A8CD2D76AAAF00F6D884 /* TSThemeSetRingToneView.swift */,
 				A868A8C82D76A45200F6D884 /* TSThemeSetItemView.swift */,
 				A868A8C62D76A43E00F6D884 /* TSThemeSetVC.swift */,
@@ -666,14 +677,6 @@
 			path = TSThemeSetVC;
 			sourceTree = "<group>";
 		};
-		A868A8D12D76DC9900F6D884 /* VM */ = {
-			isa = PBXGroup;
-			children = (
-				A868A8D22D76DC9E00F6D884 /* TSThemeSetVM.swift */,
-			);
-			path = VM;
-			sourceTree = "<group>";
-		};
 		A868A8DC2D76F90E00F6D884 /* TSBandRingTool */ = {
 			isa = PBXGroup;
 			children = (
@@ -821,6 +824,14 @@
 			path = ViewModel;
 			sourceTree = "<group>";
 		};
+		A8DEC26E2D7C3948002EB948 /* TSThemeCopyrightVC */ = {
+			isa = PBXGroup;
+			children = (
+				A8DEC26F2D7C395B002EB948 /* TSThemeCopyrightVC.swift */,
+			);
+			path = TSThemeCopyrightVC;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -956,6 +967,7 @@
 				A868A8EF2D77041400F6D884 /* TSLoadingAnimation.swift in Sources */,
 				A80EDE652D718CAF003CD332 /* GlobalImports.swift in Sources */,
 				A868A9092D7828EC00F6D884 /* TSTGPPhotoStyleView.swift in Sources */,
+				A8DEC2702D7C395C002EB948 /* TSThemeCopyrightVC.swift in Sources */,
 				A80EDF112D718ED1003CD332 /* TSAIRintoneVC.swift in Sources */,
 				A80EDF1B2D71AC90003CD332 /* TSCollectionViewVM.swift in Sources */,
 				A80EDE612D718AF4003CD332 /* TSConfig.swift in Sources */,
@@ -1010,9 +1022,9 @@
 				A868A8AA2D7588A500F6D884 /* TSThemeBrowseVC.swift in Sources */,
 				A868A8B12D758CA400F6D884 /* TSTBBtnView.swift in Sources */,
 				A8272E9B2D7A8F1000F1C814 /* TSGeneralRintoneVC.swift in Sources */,
-				A868A8D32D76DE7600F6D884 /* TSThemeSetVM.swift in Sources */,
 				A80EDF272D71C13D003CD332 /* TSColVVMHeaderModel.swift in Sources */,
 				A83F87222D7953C000D29B1B /* Notification+TSEx.swift in Sources */,
+				A83503CD2D7ED1440067002A /* TSThemeTutorialsVC.swift in Sources */,
 				A868A8AD2D758B6B00F6D884 /* TSTBCallPreviewView.swift in Sources */,
 				A868A9162D784E6500F6D884 /* TSBottomAlertVC.swift in Sources */,
 				A80EDF012D718DF1003CD332 /* TSBusinessWebVC.swift in Sources */,
@@ -1056,7 +1068,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 3;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1076,7 +1088,7 @@
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.tsyh.AIRingtone;
+				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
 				SUPPORTS_MACCATALYST = NO;
@@ -1098,7 +1110,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
+				CURRENT_PROJECT_VERSION = 3;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIRingtone/Info.plist;
@@ -1118,7 +1130,7 @@
 					"$(PROJECT_DIR)/AIRingtone/Common/Tool/TSBandRingTool/libmp3",
 				);
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.tsyh.AIRingtone;
+				PRODUCT_BUNDLE_IDENTIFIER = ai.ringtones.com;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
 				SUPPORTS_MACCATALYST = NO;

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

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

+ 8 - 0
AIRingtone.xcodeproj/xcuserdata/100years.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -10,5 +10,13 @@
 			<integer>36</integer>
 		</dict>
 	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>A80EDE352D7184D9003CD332</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
 </dict>
 </plist>

+ 6 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_0.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_0.imageset/photo_example_0@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_0.imageset/photo_example_0@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_1.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_1.imageset/photo_example_1@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_1.imageset/photo_example_1@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_2.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_2.imageset/photo_example_2@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/example/photo_example_2.imageset/photo_example_2@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_0.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_0.imageset/poster_example_0@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_0.imageset/poster_example_0@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_1.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_1.imageset/poster_example_1@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_1.imageset/poster_example_1@3x.png


+ 22 - 0
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_2.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_2.imageset/poster_example_2@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/example/poster_example_2.imageset/poster_example_2@3x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/nav_title_aiAvatar.imageset/nav_title_aiAvatar@3x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@2x.png


BIN
AIRingtone/Assets.xcassets/AIPhoto/style/ptp_style_9.imageset/ptp_style_9@3x.png


BIN
AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@2x.png


BIN
AIRingtone/Assets.xcassets/AIRing/nav_title_aiRing.imageset/nav_title_aiRing@3x.png


BIN
AIRingtone/Assets.xcassets/App-Icon.imageset/App-Icon 1.png


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

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

+ 117 - 32
AIRingtone/Assets.xcassets/AppIcon.appiconset/Contents.json

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

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

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


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


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


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


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


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


BIN
AIRingtone/Assets.xcassets/Setting/nav_title_setting.imageset/nav_title_setting@2x.png


BIN
AIRingtone/Assets.xcassets/Setting/nav_title_setting.imageset/nav_title_setting@3x.png


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

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

BIN
AIRingtone/Assets.xcassets/Theme/icon/desktop_bg.imageset/desktop_bg.png


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


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


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


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


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


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


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


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


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


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


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


+ 6 - 0
AIRingtone/Assets.xcassets/Tutorials/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 21 - 0
AIRingtone/Assets.xcassets/Tutorials/tutorials_ringtone.imageset/Contents.json

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

BIN
AIRingtone/Assets.xcassets/Tutorials/tutorials_ringtone.imageset/tutorials_ringtone.png


+ 10 - 20
AIRingtone/Base.lproj/LaunchScreen.storyboard

@@ -5,7 +5,6 @@
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
@@ -17,25 +16,19 @@
                         <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
-                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="view_bj" translatesAutoresizingMaskIntoConstraints="NO" id="KWR-Qo-hXN">
-                                <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="App-Icon" translatesAutoresizingMaskIntoConstraints="NO" id="DHb-sc-7Ah">
+                                <rect key="frame" x="96.666666666666686" y="326" width="200" height="200"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="200" id="TFM-be-ybJ"/>
+                                    <constraint firstAttribute="width" constant="200" id="ufV-Yj-JCO"/>
+                                </constraints>
                             </imageView>
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="AI Ringtone" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="e7M-sf-G3U">
-                                <rect key="frame" x="74.666666666666686" y="396" width="244" height="60"/>
-                                <fontDescription key="fontDescription" type="system" pointSize="50"/>
-                                <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                                <nil key="highlightedColor"/>
-                            </label>
                         </subviews>
                         <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
-                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                         <constraints>
-                            <constraint firstItem="KWR-Qo-hXN" firstAttribute="trailing" secondItem="6Tk-OE-BBY" secondAttribute="trailing" id="9zW-15-iQe"/>
-                            <constraint firstItem="KWR-Qo-hXN" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="CEc-45-FF7"/>
-                            <constraint firstItem="e7M-sf-G3U" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="DNd-ZK-6U7"/>
-                            <constraint firstAttribute="bottom" secondItem="KWR-Qo-hXN" secondAttribute="bottom" id="brW-CJ-Z0a"/>
-                            <constraint firstItem="e7M-sf-G3U" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="e4V-8W-7Nd"/>
-                            <constraint firstItem="KWR-Qo-hXN" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="nTW-sR-b2J"/>
+                            <constraint firstItem="DHb-sc-7Ah" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="PGr-ii-DSE"/>
+                            <constraint firstItem="DHb-sc-7Ah" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="dec-tx-yNP"/>
                         </constraints>
                     </view>
                 </viewController>
@@ -45,9 +38,6 @@
         </scene>
     </scenes>
     <resources>
-        <image name="view_bj" width="375" height="812"/>
-        <systemColor name="systemBackgroundColor">
-            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
+        <image name="App-Icon" width="512" height="512"/>
     </resources>
 </document>

+ 127 - 0
AIRingtone/Business/Data/TSUserDefaultData.swift

@@ -12,6 +12,13 @@ class TSPosterHistory{
     @UserDefault(key: "kPosterTextPicHistoryListString", defaultValue: "")
     static private var historyString: String
     static var listModelArray: [TSActionInfoModel] = {
+        
+        if UserDefaults.standard.string(forKey: "insertPosterExampleData") == nil {
+            insertExampleData()
+            UserDefaults.standard.set("1", forKey: "insertPosterExampleData")
+            UserDefaults.standard.synchronize()
+        }
+        
         if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyString){
             return listModelArray
         }
@@ -20,10 +27,46 @@ class TSPosterHistory{
     
     static func saveModel(model:TSActionInfoModel){
         listModelArray.insert(model, at: 0)
+        saveHistoryString()
+    }
+    
+    static func removeModel(model:TSActionInfoModel){
+        listModelArray.removeAll { $0 === model }
+        saveHistoryString()
+    }
+    
+    static func removeIndex(index:Int){
+        listModelArray.remove(at: index)
+        saveHistoryString()
+    }
+    
+    static func saveHistoryString(){
         if let jsonString = listModelArray.toJSONString() {
             historyString = jsonString
         }
     }
+    
+    private static func insertExampleData(){
+        let array = [
+            createExampleModel(imageName: "poster_example_0"),
+            createExampleModel(imageName: "poster_example_1"),
+            createExampleModel(imageName: "poster_example_2")
+        ]
+        if let jsonString = array.toJSONString() {
+            historyString = jsonString
+        }
+    }
+    
+    private static func createExampleModel(imageName:String)->TSActionInfoModel{
+        let model = TSActionInfoModel()
+        model.modelType = .example
+        model.request.prompt = "Example"
+        model.request.promptSort = "Example"
+        model.request.width = kTextPicW
+        model.request.height = kTextPicH
+        model.response.resultUrl = imageName
+        return model
+    }
 }
 
 //头像历史记录
@@ -31,6 +74,11 @@ class TSPhotoHistory{
     @UserDefault(key: "kPhotoTextPicHistoryListString", defaultValue: "")
     static private var historyString: String
     static var listModelArray: [TSActionInfoModel] = {
+        if UserDefaults.standard.string(forKey: "insertPhotoExampleData") == nil {
+            insertExampleData()
+            UserDefaults.standard.set("1", forKey: "insertPhotoExampleData")
+            UserDefaults.standard.synchronize()
+        }
         if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyString){
             return listModelArray
         }
@@ -39,10 +87,46 @@ class TSPhotoHistory{
     
     static func saveModel(model:TSActionInfoModel){
         listModelArray.insert(model, at: 0)
+        saveHistoryString()
+    }
+    
+    static func removeModel(model:TSActionInfoModel){
+        listModelArray.removeAll { $0 === model }
+        saveHistoryString()
+    }
+    
+    static func removeIndex(index:Int){
+        listModelArray.remove(at: index)
+        saveHistoryString()
+    }
+    
+    static func saveHistoryString(){
         if let jsonString = listModelArray.toJSONString() {
             historyString = jsonString
         }
     }
+    
+    private static func insertExampleData(){
+        let array = [
+            createExampleModel(imageName: "photo_example_0"),
+            createExampleModel(imageName: "photo_example_1"),
+            createExampleModel(imageName: "photo_example_2")
+        ]
+        if let jsonString = array.toJSONString() {
+            historyString = jsonString
+        }
+    }
+    
+    private static func createExampleModel(imageName:String)->TSActionInfoModel{
+        let model = TSActionInfoModel()
+        model.modelType = .example
+        model.request.prompt = "Example"
+        model.request.promptSort = "Example"
+        model.request.width = kTextPicW
+        model.request.height = kTextPicW
+        model.response.resultUrl = imageName
+        return model
+    }
 }
 
 //AI铃声历史记录
@@ -50,6 +134,13 @@ class TSAIRintoneHistory{
     @UserDefault(key: "kRintoneTextMusicHistoryListString", defaultValue: "")
     static private var historyString: String
     static var listModelArray: [TSActionInfoModel] = {
+        
+        if UserDefaults.standard.string(forKey: "insertRintoneExampleData") == nil {
+            insertExampleData()
+            UserDefaults.standard.set("1", forKey: "insertRintoneExampleData")
+            UserDefaults.standard.synchronize()
+        }
+        
         if let listModelArray = Mapper<TSActionInfoModel>().mapArray(JSONString: historyString){
             return listModelArray
         }
@@ -58,8 +149,44 @@ class TSAIRintoneHistory{
     
     static func saveModel(model:TSActionInfoModel){
         listModelArray.insert(model, at: 0)
+        saveHistoryString()
+    }
+    
+    static func removeModel(model:TSActionInfoModel){
+        listModelArray.removeAll { $0 === model }
+        saveHistoryString()
+    }
+    
+    static func removeIndex(index:Int){
+        listModelArray.remove(at: index)
+        saveHistoryString()
+    }
+    
+    static func saveHistoryString(){
         if let jsonString = listModelArray.toJSONString() {
             historyString = jsonString
         }
     }
+    
+
+    private static func insertExampleData(){
+        let array = [
+            createExampleModel(),
+        ]
+        if let jsonString = array.toJSONString() {
+            historyString = jsonString
+        }
+    }
+    
+    private static func createExampleModel()->TSActionInfoModel{
+        let model = TSActionInfoModel()
+        model.modelType = .example
+        model.request.duration = 30
+        model.request.prompt = "Example"
+        model.request.promptSort = "Example"
+        model.response.coverUrl = "http://d3a93z8fj970a4.cloudfront.net/53337c41-9610-4b92-a8fc-0871a0895880"
+        model.response.title = "Glass"
+        model.response.musicUrl = "http://d3a93z8fj970a4.cloudfront.net/328324a2-2576-4f55-8c77-2fa16b88e043"
+        return model
+    }
 }

+ 3 - 2
AIRingtone/Business/TSAIPhotoVC/TSAIPhotoChildVC/TSAIPhotoChildVC.swift

@@ -32,7 +32,7 @@ class TSAIPhotoChildVC: TSBaseVC {
     lazy var collectionComponent: TSCollectionViewComponent = {
         let layout = UICollectionViewFlowLayout()
         let cp = TSCollectionViewComponent(frame: CGRect.zero, layout: layout, attributes: [ :])
-        cp.collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+        cp.collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
         cp.itemDidSelectedHandler = { [weak self] (object, indexPath) in
             guard let self = self else { return }
             
@@ -83,7 +83,8 @@ class TSAIPhotoChildVC: TSBaseVC {
             if let userInfo = notification.userInfo as? [String: TSGennerateType], let myEnum = userInfo["TSGennerateType"] {
                 if myEnum == self.style {
                     self.vm.setRecentData()
-                    self.collectionComponent.reloadData()
+                    self.collectionComponent.clear()
+                    self.collectionComponent.reloadView(with:self.vm.colDataArray)
                 }
             }
         }

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

@@ -10,10 +10,28 @@ class TSAIPhotoImageCell: TSBaseCollectionCell {
     lazy var showImageView: UIImageView = {
         let showImageView = UIImageView.createImageView(imageName:"",contentMode: .scaleAspectFill)
         showImageView.backgroundColor = .gray
-        
         return showImageView
     }()
     
+    lazy var exampleView: UIView = {
+        let exampleView = UIView()
+        exampleView.backgroundColor = "#232323".uiColor.withAlphaComponent(0.3)
+        
+        let textLabel = UILabel.createLabel(
+            text: "Example".localized,
+            font: .font(size: 12),
+            textColor: .white
+        )
+        
+        exampleView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.top.edges.equalTo(UIEdgeInsets(top: 4, left: 6, bottom: 4, right: 6))
+        }
+        exampleView.isHidden = true
+        exampleView.cornerRadius = 10.0
+        return exampleView
+    }()
+    
     override func creatUI() {
         contentView.addSubview(showImageView)
         showImageView.snp.makeConstraints { make in
@@ -28,6 +46,13 @@ class TSAIPhotoImageCell: TSBaseCollectionCell {
             showImageView.layer.cornerRadius = 16
         }
         
+        contentView.addSubview(exampleView)
+        exampleView.snp.makeConstraints { make in
+            make.bottom.equalTo(-8)
+            make.centerX.equalToSuperview()
+            make.height.equalTo(20)
+        }
+        
     }
     
     override func renderView(with object: Any?, component: TSCollectionViewComponent, attributes: [String : Any]?) {
@@ -35,6 +60,7 @@ class TSAIPhotoImageCell: TSBaseCollectionCell {
         if let itemModel = object as? TSColVVMItemModel{
             if let generalPicModel = itemModel.dataModel as? TSActionInfoModel{
                 showImageView.setAsyncImage(urlString: generalPicModel.response.resultUrl,placeholder: kPlaceholderImage,contentMode: .scaleAspectFill)
+                exampleView.isHidden = generalPicModel.modelType == .example ? false : true
             }
         }
     }

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

@@ -79,7 +79,20 @@ class TSAIPhotoVC: TSBaseVC {
         let indicator = JXSegmentedIndicatorBackgroundView()
         indicator.isIndicatorConvertToItemFrameEnabled = true
         indicator.indicatorHeight = 28
-        indicator.indicatorColor = .themeColor
+        
+        
+//        indicator.indicatorColor = .themeColor
+        
+        
+        let gradientView = JXSegmentedComponetGradientView()
+        gradientView.gradientLayer.endPoint = CGPoint(x: 0, y: 1)
+        gradientView.gradientLayer.endPoint = CGPoint(x: 1, y: 1)
+        gradientView.gradientLayer.colors = ["#E961F6".uiColor.cgColor, "#7E57F4".uiColor.cgColor]
+        gradientView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+        gradientView.cornerRadius = 14
+        indicator.addSubview(gradientView)
+        
+        
         return indicator
     }()
     

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

@@ -206,7 +206,7 @@ extension TSGeneralPicBrowseVC {
     
     var cellImageSize:CGSize {
         if style == .photo {
-            return CGSizeMake(140 , 140)
+            return CGSizeMake(200 , 200)
         }
         return CGSize(width: 140, height: 272)
     }

+ 1 - 1
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/Model/TSGeneralPicModel.swift

@@ -58,7 +58,7 @@ class TSActionInfoRequestModel : TSBaseModel {
     //生成图用的
     var width:Int = 0
     var height:Int = 0
-    //成音乐用的
+    //成音乐用的
     var duration:Int = 0
     override func mapping(map: ObjectMapper.Map) {
         prompt              <- map["prompt"]

+ 14 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC+Event.swift

@@ -20,6 +20,13 @@ extension TSGeneralPicVC {
         }
         return CGSizeMake(140, 272)
     }
+    
+    var netWorkImageCorner:CGFloat{
+        if gennerateType == .photo{
+            return 100.0
+        }
+        return 12.0
+    }
 
     var resultIcon:UIImage?{
         if gennerateType == .photo{
@@ -35,6 +42,13 @@ extension TSGeneralPicVC {
         return "Download".localized
     }
     
+    var shadowColor:UIColor{
+        if gennerateType == .photo{
+            return "#67B4F1".uiColor
+        }
+        return "#5FE4B5".uiColor
+    }
+    
     func getSuccessImage()->UIImage?{
         if let image = netWorkImageView.image {
             return image.pngImage

+ 3 - 0
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGeneralPicVC.swift

@@ -75,6 +75,9 @@ class TSGeneralPicVC: TSBottomAlertVC {
         saveBtn.setTitle(saveBtnText, for: .normal)
         resultIconImageView.image = resultIcon
         bottomViewH = 540.0
+        bgImageView.addShadow(shadowColor: shadowColor.cgColor, shadowOffset: .zero, shadowRadius: 20, shadowOpacity: 0.8)
+        
+        netWorkImageView.cornerRadius = netWorkImageCorner
     }
     
     @objc override func closePage() {

+ 5 - 7
AIRingtone/Business/TSAIPhotoVC/TSGeneralPicVC/TSGenneralPicVM.swift

@@ -8,10 +8,8 @@
 import Combine
 import Alamofire
 
-private let kTextPicW = 800.0
-private let kTextPicH = 1440.0
-//let kTextWHScale = kTextPicW/kTextPicH
-
+let kTextPicW:Int = 800
+let kTextPicH:Int = 1440
 
 class TSGenneralPicVM {
     
@@ -121,14 +119,14 @@ class TSGenneralPicVM {
 extension TSGenneralPicVM {
     
     var textPicW:Int{
-        return 800
+        return kTextPicW
     }
     
     var textPicH:Int{
         if gennerateType == .photo {
-            return 800
+            return kTextPicW
         }
-        return 1440
+        return kTextPicH
     }
 }
 

+ 4 - 3
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSCreatBtnView.swift

@@ -39,9 +39,9 @@ class TSCreatBtnView: TSBaseView {
         let shadowView = UIView()
         shadowView.frame = creatBtn.frame
         shadowView.layer.shadowColor = UIColor.themeColor.cgColor
-        shadowView.layer.shadowOffset = .zero
+        shadowView.layer.shadowOffset = CGSize(width: 0, height: 4)
         shadowView.layer.shadowOpacity = 0.5
-        shadowView.layer.shadowRadius = 24
+        shadowView.layer.shadowRadius = 5
         return shadowView
     }()
 
@@ -50,7 +50,8 @@ class TSCreatBtnView: TSBaseView {
         contentView.addSubview(shadowView)
         shadowView.snp.makeConstraints { make in
             make.center.equalToSuperview()
-            make.width.equalTo(creatBtn.width)
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
             make.height.equalTo(creatBtn.height)
         }
 

+ 15 - 12
AIRingtone/Business/TSAIPhotoVC/TSTextGeneralPicVC/View/TSPromptTextView.swift

@@ -23,7 +23,7 @@ class TSPromptTextView : TSBaseView{
     
     lazy var titleView: TSTGPTitleView = {
         let titleView = TSTGPTitleView()
-        titleView.titleLab.text = "Enter A Prompt".localized
+        titleView.titleLab.text = "Enter a prompt".localized
         return titleView
     }()
   
@@ -36,10 +36,10 @@ class TSPromptTextView : TSBaseView{
         let textBgView = UIView()
 
         let bgImageView = UIImageView.createImageView(imageName: "textView_bg",contentMode: .scaleToFill)
-        let lbImageView = UIImageView.createImageView(imageName: "textView_lb",contentMode: .scaleToFill)
+//        let lbImageView = UIImageView.createImageView(imageName: "textView_lb",contentMode: .scaleToFill)
         
         textBgView.addSubview(bgImageView)
-        textBgView.addSubview(lbImageView)
+//        textBgView.addSubview(lbImageView)
         
         bgImageView.snp.makeConstraints { make in
             make.top.equalTo(0)
@@ -48,13 +48,13 @@ class TSPromptTextView : TSBaseView{
             make.height.equalTo(160*kDesignScale)
         }
         
-        lbImageView.snp.makeConstraints { make in
-            make.bottom.equalTo(0)
-            make.leading.equalTo(0)
-            make.width.equalTo(206*kDesignScale)
-            make.height.equalTo(32*kDesignScale)
-        }
-        
+//        lbImageView.snp.makeConstraints { make in
+//            make.bottom.equalTo(0)
+//            make.leading.equalTo(0)
+//            make.width.equalTo(206*kDesignScale)
+//            make.height.equalTo(32*kDesignScale)
+//        }
+//        lbImageView.isHidden = true
         return textBgView
     }()
     
@@ -97,6 +97,8 @@ class TSPromptTextView : TSBaseView{
             customTextView.text = ""
             textViewDidChange(customTextView)
         }
+        clearBtn.setImage(UIImage(named: "clear_gary_text"), for: .disabled)
+        clearBtn.isEnabled = false
         return clearBtn
     }()
     
@@ -116,7 +118,7 @@ class TSPromptTextView : TSBaseView{
         
         numView.addSubview(currenMunLab)
         
-        let numLab = UILabel.createLabel(text: "/\(maxNum))",font: .font(name: .PingFangSC,size: 12),textColor: .white.withAlphaComponent(0.4))
+        let numLab = UILabel.createLabel(text: "/\(maxNum)",font: .font(name: .PingFangSC,size: 12),textColor: .white.withAlphaComponent(0.4))
         numView.addSubview(numLab)
         
         let lineView = UIView()
@@ -164,7 +166,7 @@ class TSPromptTextView : TSBaseView{
             make.leading.equalTo(16)
             make.trailing.equalTo(-16)
             make.height.equalTo(160.0*kDesignScale)
-            make.bottom.equalTo(0)
+            make.bottom.equalTo(-10)
         }
    
         textBgView.addSubview(customTextView)
@@ -215,6 +217,7 @@ extension TSPromptTextView: UITextViewDelegate{
     
     func textViewDidChange(_ textView: UITextView) {
         currenMun = textView.text.count
+        clearBtn.isEnabled = currenMun > 0
         textChangedBlock(textView.text)
     }
     

+ 37 - 39
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/TSAIRintoneVC.swift

@@ -13,6 +13,10 @@ class TSAIRintoneVC: TSBaseVC {
         return viewModel
     }()
     
+    lazy var ringTool: TSBandRingTool = {
+        let ringTool = TSBandRingTool(targetVC: self)
+        return ringTool
+    }()
     
     lazy var navBarView: TSBaseNavContentBarView = {
         let navBarView = TSBaseNavContentBarView()
@@ -25,8 +29,7 @@ class TSAIRintoneVC: TSBaseVC {
 
         return navBarView
     }()
-    
-    var stickyHeaders: [Int: TSAIRintoneHistorySectionHeaderView] = [:] // 存储悬浮的区间头
+
     lazy var layout: UICollectionViewFlowLayout = {
         let layout = UICollectionViewFlowLayout()
         layout.scrollDirection = .vertical
@@ -34,7 +37,6 @@ class TSAIRintoneVC: TSBaseVC {
         layout.minimumInteritemSpacing = 10.0
         layout.minimumLineSpacing = 18.0
         layout.headerReferenceSize = CGSizeMake(k_ScreenWidth, 48)
-//        layout.sectionHeadersPinToVisibleBounds = true
         return layout
     }()
     
@@ -58,7 +60,7 @@ class TSAIRintoneVC: TSBaseVC {
         let generalRintoneVC = TSTextGeneralRintoneVC()
         generalRintoneVC.reloadUIBlock = { [weak self]  in
             guard let self = self else { return }
-            viewModel.setRecentData()
+            viewModel.updateRecentData()
             updateListView()
         }
         return generalRintoneVC
@@ -88,12 +90,17 @@ class TSAIRintoneVC: TSBaseVC {
             make.height.equalTo(vcViewH)
         }
         
-        collectionView.contentInset = UIEdgeInsets(top: vcViewH, left: 0, bottom: 0, right: 0)
+        collectionView.contentInset = UIEdgeInsets(top: vcViewH, left: 0, bottom: 20, right: 0)
 
     }
 
     override func viewWillAppear(_ animated: Bool) {
-        //
+        super.viewWillAppear(animated)
+    }
+    
+    override func viewDidDisappear(_ animated: Bool) {
+        super.viewDidDisappear(animated)
+        TSBusinessAudioPlayer.shared.stop()
     }
     
     override func dealThings() {
@@ -130,31 +137,27 @@ extension TSAIRintoneVC: UICollectionViewDataSource ,UICollectionViewDelegate {
         {
             cell.delegate = self
             cell.model = itemModel
+            cell.setRingBtn.indexPath = indexPath
+            cell.setRingBtn.addTarget(self, action: #selector(clickSetRingBtn(_ :)), for: .touchUpInside)
         }
         
         return cell
     }
 
-    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        if let sectionModel = viewModel.historyModelList.safeObj(At: indexPath.section),
-           let itemModel = sectionModel.list.safeObj(At: indexPath.item)
-        {
-            
-//            let chatVC = TSChatViewController()
-//            chatVC.viewModel.uiStyle = .history
-//            chatVC.viewModel.dbAIChatList = itemModel
-//            chatVC.deleteBlock = { [weak self]  in
-//                guard let self = self else { return }
-//                //删除 UI 层的 cell
-//                sectionModel.list.remove(at: indexPath.item)
-//                if sectionModel.list.count == 0 {
-//                    self.viewModel.historyModelList.remove(at: indexPath.section)
-//                }
-//                updateListView()
-//                
-//            }
-//            self.navigationController?.pushViewController(chatVC, animated: true)
+    @objc func clickSetRingBtn(_ btn:TSUIExpandedTouchButton){
+        let indexPath = btn.indexPath
+        if let sectionModel = self.viewModel.historyModelList.safeObj(At: indexPath.section),
+        let model = sectionModel.list.safeObj(At: indexPath.item){
+            ringTool.shareBand(with: model.response.musicUrl, fileName: model.response.title) { success in
+                
+            }
         }
+        
+        collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .top)
+        TSBusinessAudioPlayer.shared.stop()
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
     }
     
     
@@ -163,18 +166,12 @@ extension TSAIRintoneVC: UICollectionViewDataSource ,UICollectionViewDelegate {
             if kind == UICollectionView.elementKindSectionHeader {
                 if let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TSAIRintoneHistorySectionHeaderView.reuseIdentifier, for: indexPath) as? TSAIRintoneHistorySectionHeaderView {
                     header.titleView.titleLab.text = sectionModel.title
-                    
-                    stickyHeaders[indexPath.section] = header // 存储区间头
                     return header
                 }
-                
-                
             }
         }
         return TSAIRintoneHistorySectionHeaderView()
     }
-    
-
 }
 
 extension TSAIRintoneVC: SwipeCollectionViewCellDelegate {
@@ -187,14 +184,15 @@ extension TSAIRintoneVC: SwipeCollectionViewCellDelegate {
             guard let self = self else { return }
             showCustomAlert(message: "Are you sure to delete".localized, deleteHandler:  {
                 if let sectionModel = self.viewModel.historyModelList.safeObj(At: indexPath.section),
-                let itemModel = sectionModel.list.safeObj(At: indexPath.item){
-                    sectionModel.list.remove(at: indexPath.item)
-              
-                    if sectionModel.list.count == 0 {
-                        self.viewModel.historyModelList.remove(at: indexPath.section)
-                    }
-                    
-                    self.updateListView()
+                let model = sectionModel.list.safeObj(At: indexPath.item){
+                    collectionView.performBatchUpdates({
+                        self.viewModel.removeModel(model: model)
+                        if sectionModel.list.count == 0 {
+                            collectionView.deleteSections([indexPath.section])
+                        }else{
+                            collectionView.deleteItems(at: [indexPath])
+                        }
+                    })
                 }
             })
         }

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

@@ -36,19 +36,18 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell {
             guard let model = model else { return }
             ringView.timeLab.text = Float(model.request.duration).floatToMinuteSecond()
             ringView.nameLab.text = model.response.title
-            ringView.coverImageView.setAsyncImage(urlString: model.response.coverUrl,contentMode: .scaleAspectFill)
+            ringView.setCoverImageView(urlString: model.response.coverUrl)
         }
     }
     
     override var isSelected: Bool{
         didSet{
-            backgroundColor = isSelected ? "#3C213F".uiColor :.cardColor
             ringView.isloading = isSelected
-
             if isSelected, self.ringView.isPlay == false{
                 TSBusinessAudioPlayer.shared.playRingtone(ringtone: model?.response.musicUrl)
             }else{
                 TSBusinessAudioPlayer.shared.stop()
+                backgroundColor = .cardColor
             }
         }
     }
@@ -70,30 +69,40 @@ class TSAIRintoneHistoryCell: SwipeCollectionViewCell {
             make.width.height.equalTo(20)
         }
         
-        NotificationCenter.default.addObserver(forName: .kReloadUIData, object: nil, queue: nil) { notification in
+        NotificationCenter.default.addObserver(forName: .kBusinessAudioStateChange, object: nil, queue: nil) { notification in
             if let userInfo = notification.userInfo as? [String: TSBusinessAudioPlayer.PlayerState], let state = userInfo["PlayerState"] {
-                if self.isSelected == false {
-                    self.ringView.isPlay = false
-                    return
+                kExecuteOnMainThread {
+                    self.changePlayerState(state: state)
                 }
                 
-                switch state {
-                case .loading(let progress):
-                    if progress == 0.0 {
-                        self.ringView.isloading = true
-                    }else if progress == 1.0 {
-                        self.ringView.isloading = false
-                    }
-                case .play:
-                    self.ringView.isPlay = true
-                case .stop:
-                    self.ringView.isPlay = false
-                default:
-                    break
-                }
             }
         }
     }
+    
+    
+    func changePlayerState(state:TSBusinessAudioPlayer.PlayerState){
+        if self.isSelected == false {
+            self.ringView.isPlay = false
+            return
+        }
+        
+        switch state {
+        case .loading(let progress):
+            if progress == 0.0 {
+                self.ringView.isloading = true
+            }else if progress == 1.0 {
+                self.ringView.isloading = false
+            }
+        case .play:
+            self.ringView.isPlay = true
+            backgroundColor = "#3C213F".uiColor
+        case .stop:
+            self.ringView.isPlay = false
+            backgroundColor = .cardColor
+        default:
+            break
+        }
+    }
 
     deinit {
         NotificationCenter.default.removeObserver(self)

+ 12 - 2
AIRingtone/Business/TSAIRintoneVC/TSAIRintoneVC/ViewModel/TSAIRintoneVM.swift

@@ -12,14 +12,24 @@ class TSAIRintoneVM {
     }()
     
     lazy var historyModelList: [TSAIRintoneHistoryModel] = {
+        gethistoryModelList()
+    }()
+    
+    private func gethistoryModelList()->[TSAIRintoneHistoryModel]{
         if aiRintoneHistoryModel.list.count > 0 {
             return [aiRintoneHistoryModel]
         }
         return []
-    }()
+    }
     
-    func setRecentData() {
+    func updateRecentData() {
         aiRintoneHistoryModel.list = TSAIRintoneHistory.listModelArray
+        historyModelList = gethistoryModelList()
+    }
+    
+    func removeModel(model:TSActionInfoModel){
+        TSAIRintoneHistory.removeModel(model: model)
+        updateRecentData()
     }
 }
 

+ 0 - 6
AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVC+Event.swift

@@ -86,12 +86,6 @@ extension TSGeneralRintoneVC {
         ringView.isHidden = false
         regenerateBtn.isHidden = false
         
-        
-//        TSCommonTool.downloadAndCacheFile(from: "") { [weak self] path, error in
-//            guard let self = self else { return }
-//        
-//        }
-        
 //        kPurchaseDefault.useOnceForFree(type: .generatePic)
         
         if let model = infoModel {

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

@@ -45,6 +45,10 @@ class TSGeneralRintoneVC: TSBottomAlertVC {
         return generateInView
     }()
 
+    lazy var ringTool: TSBandRingTool = {
+        let ringTool = TSBandRingTool(targetVC: self)
+        return ringTool
+    }()
     
     override func createView() {
         super.createView()
@@ -70,7 +74,7 @@ class TSGeneralRintoneVC: TSBottomAlertVC {
         saveBtn.setTitle("Set As Ringtone".localized, for: .normal)
         resultIconImageView.image = resultIcon
         bottomViewH = 340.0
-        
+        bgImageView.addShadow(shadowColor: "#E6E229".uiColor.cgColor, shadowOffset: .zero, shadowRadius: 20, shadowOpacity: 0.8)
         
         diyView.addSubview(failView)
         failView.snp.updateConstraints { make in
@@ -88,8 +92,15 @@ class TSGeneralRintoneVC: TSBottomAlertVC {
     }
     
     @objc override func clickSubmitBtn(){
-
         
+        guard let model = infoModel else {
+            kShowToastDataMissing()
+            return
+        }
+
+        ringTool.shareBand(with: model.response.musicUrl, fileName: model.response.title) { success in
+            
+        }
     }
     
     @objc func clickPlay(){
@@ -113,7 +124,7 @@ extension TSGeneralRintoneVC{
     func setRingViewData(model:TSActionInfoModel) {
         ringView.timeLab.text = Float(model.request.duration).floatToMinuteSecond()
         ringView.nameLab.text = model.response.title
-        ringView.coverImageView.setAsyncImage(urlString: model.response.coverUrl,contentMode: .scaleAspectFill)
+        ringView.setCoverImageView(urlString: model.response.coverUrl)
     }
     
     func audioPlayerStateChange(state:TSBusinessAudioPlayer.PlayerState){

+ 24 - 22
AIRingtone/Business/TSAIRintoneVC/TSGeneralRintoneVC/TSGeneralRintoneVM.swift

@@ -7,21 +7,6 @@
 
 import Combine
 import Alamofire
-//let actionInfoDict:[String:Any] = [
-//    "code":200,
-//    "message": "Success",
-//    "result": [
-//        "actionType":"music_create",
-//        "comments": "Success",
-//        "costTime":15,
-//        "createdTimestamp":1741338454,
-//        "id":1536,
-//        "percent":1,
-//        "request":"{\"prompt\": \"Create a Techno ringtone with a repetitive bassline, crisp hi-hats, and subtle synth textures. Use a BPM of 125-130 for a sleek, modern sound., Create a uplifting and modern music track blending Pop, Electronic, and Ambient elements. Use a BPM of 100-120, a catchy melody with synth or piano, warm harmonies, and a mix of electronic and organic sounds. Ensure a clear structure (Intro, Verse, Chorus, Outro) and a light, positive vibe suitable for background or casual listening\", \"duration\": 5}",
-//        "response":"{\"coverUrl\": \"https://be-aigc.s3-accelerate.amazonaws.com/f0fb7739-a5cc-4805-9b68-b4a5890eb285.png\", \"title\": \"Neon Pulse\\\"  \\n\\\"Horizon Glow\", \"musicUrl\": \"https://be-aigc.s3-accelerate.amazonaws.com/c47d40dd-d07c-4edc-a6d9-8382438149d1.wav\"}",
-//        "status":"success"
-//    ]
-//]
 
 let actionInfoDict:[String:Any] = [
     "actionType":"music_create",
@@ -49,13 +34,30 @@ class TSGeneralRintoneVM {
 
         stateDatauPblished = (.start,nil)
         stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)
-//        kDelayOnMainThread(2.0) {
-//            self.stateDatauPblished = (.failed("error?.localizedDescription" ?? ""),nil)
-//        }
-     
+
+        kDelayOnMainThread(0.2) {
+            self.stateDatauPblished = (.progressString(self.generating(progress: 0.2)),nil)
+        }
+        
+        kDelayOnMainThread(0.4) {
+            self.stateDatauPblished = (.progressString(self.generating(progress: 0.4)),nil)
+        }
+        
+        kDelayOnMainThread(0.6) {
+            self.stateDatauPblished = (.progressString(self.generating(progress: 0.6)),nil)
+        }
+        
+        kDelayOnMainThread(0.8) {
+            self.stateDatauPblished = (.progressString(self.generating(progress: 0.8)),nil)
+        }
+        
         kDelayOnMainThread(1.0) {
-            let infoModel = TSActionInfoModel(JSON: actionInfoDict)
-            self.stateDatauPblished = (.success(nil),infoModel)
+            if Bool.random() {
+                let infoModel = TSActionInfoModel(JSON: actionInfoDict)
+                self.stateDatauPblished = (.success(nil),infoModel)
+            }else{
+                self.stateDatauPblished = (.failed("error?.localizedDescription"),nil)
+            }
         }
     }
     
@@ -65,7 +67,7 @@ class TSGeneralRintoneVM {
         aiText = text
         let postDict:[String : Any] = [
             "prompt":text,
-            "duration":5
+            "duration":10
         ]
         stateDatauPblished = (.start,nil)
         stateDatauPblished = (.progressString(generating(progress: 0.0)),nil)

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

@@ -12,7 +12,7 @@ class TSSetingViewModel: ObservableObject {
     @Published var settingTypes: [SettingType] = SettingType.allCases
 //    @Published var isViper: Bool = PurchaseManager.default.isVip
     
-    var appid = "6740220736"
+    var appid = "6741563341"
     // todo.kailen-privacy
     func showPrivacy(parent: UIViewController) {
         let vc = TSBusinessWebVC(urlType: .privacy)
@@ -71,7 +71,7 @@ class TSSetingViewModel: ObservableObject {
     
     // todo.kailen-logo
     func pushTutorials(parent: UIViewController) {
-        let vc = TSTutorialsVC(pageTitle: "TSTutorialsVC".localized, tutorialNamed: "")
+        let vc = TSThemeTutorialsVC()
         vc.hidesBottomBarWhenPushed = true
         parent.navigationController?.pushViewController(vc, animated: true)
     }

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

@@ -14,7 +14,7 @@ struct TSSettingListView: View {
         ZStack {
             Color.clear
             VStack(spacing: 0) {
-                Spacer().frame(height: 16)
+                Spacer().frame(height: 12)
                 
                 Image("theme_banner").resizable()
                     .frame(height: 109*kDesignScale)

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

@@ -25,7 +25,7 @@ class TSTabBarController: UITabBarController {
 
     @objc private func setUpData() {
         viewControllerArray = ["TSThemeVC", "TSAIRintoneVC","TSAIPhotoVC","TSSetingVC"]
-        titleArray = ["Theme","Ai Rintone","Ai Avatar","Setting"]
+        titleArray = ["Theme","Ringtone","Poster","Setting"]
         
         selectedImageArray = [
             "tabbar_select_theme",

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

@@ -91,6 +91,7 @@ class TSThemeBrowseVC: TSBaseVC {
         collectionView.showsVerticalScrollIndicator = false
         collectionView.showsHorizontalScrollIndicator = false
         collectionView.backgroundColor = .clear
+        collectionView.scrollsToTop = false
         if #available(iOS 11.0, *) {
             collectionView.contentInsetAdjustmentBehavior = .never
         }
@@ -161,6 +162,8 @@ extension TSThemeBrowseVC {
             }
         case .volume(let volume):
             btnView.soundVolume = volume
+        case .stop,.play,.pause:
+            btnView.isSoundloadling = false
         default:
             break
         }
@@ -198,7 +201,7 @@ extension TSThemeBrowseVC {
     }
     
     @objc func clickNavCopyright(){
-        TSToastShared.showToast(text: "clickNavCopyright")
+        navigationController?.pushViewController(TSThemeCopyrightVC(), animated: true)
     }
     
     @objc func clickLock(){
@@ -210,6 +213,7 @@ extension TSThemeBrowseVC {
     @objc func clickCall(){
         btnView.isHidden = true
         desktopPreview.urlString = currentModel?.photo
+        desktopPreview.islandView.nameLab.text = currentModel?.name
         desktopPreview.isHidden = false
     }
     
@@ -255,6 +259,7 @@ extension TSThemeBrowseVC:UICollectionViewDataSource,UICollectionViewDelegate {
         if let model = themeViewModel.listModelArray.safeObj(At: indexPath.item){
             cell.netWorkImageView.setAsyncImage(urlString: model.poster,placeholder:kPlaceholderImage,contentMode: .scaleAspectFill)
             cell.islandView.showImageView.setAsyncImage(urlString: model.photo,placeholder:kPlaceholderImage,contentMode: .scaleAspectFill)
+            cell.islandView.nameLab.text = model.name
         }
         return cell
     }
@@ -274,7 +279,7 @@ class TSThemeBrowseCell : TSBaseCollectionCell{
     }()
     
     override func creatUI() {
-
+     
         bgContentView.addSubview(netWorkImageView)
         netWorkImageView.snp.makeConstraints { make in
             make.center.equalToSuperview()
@@ -286,8 +291,8 @@ class TSThemeBrowseCell : TSBaseCollectionCell{
         islandView.snp.makeConstraints { make in
             make.top.equalTo(k_Nav_Height+10)
             make.centerX.equalToSuperview()
-            make.width.equalTo(351)
-            make.height.equalTo(80)
+            make.width.equalTo(islandView.width)
+            make.height.equalTo(islandView.height)
         }
     }
 }

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

@@ -14,6 +14,7 @@ class TSThemeBrowseVM {
     func setFinallyIndex(_ currentIndex:Int,ringtone:String?){
         if finallyIndex != currentIndex{
             finallyIndex = currentIndex
+            audioPlayer?.stop()
             audioPlayer?.playRingtone(ringtone: ringtone)
         }
     }

+ 3 - 2
AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTBBtnView.swift

@@ -98,7 +98,7 @@ class TSTBBtnView: TSBaseView {
         setDone()
         
         kDelayMainShort {
-            self.doneBtn.addCornerRadiusShadow(cornerRadius: 24, shadowColor: UIColor.themeColor.cgColor, shadowOffset: .zero, shadowRadius: 24, shadowOpacity: 1.0)
+            self.doneBtn.addCornerRadiusShadow(cornerRadius: 24, shadowColor: UIColor.themeColor.cgColor, shadowOffset: .zero, shadowRadius: 5, shadowOpacity: 0.5)
         }
     }
         
@@ -148,7 +148,8 @@ class TSTBBtnView: TSBaseView {
         doneBtn.snp.makeConstraints { make in
             make.bottom.equalTo(-k_Height_safeAreaInsetsBottom()-10)
             make.centerX.equalToSuperview()
-            make.width.equalTo(doneBtn.width)
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
             make.height.equalTo(doneBtn.height)
         }
     }

+ 3 - 3
AIRingtone/Business/TSThemeVC/TSThemeBrowseVC/View/TSTBDesktopPreviewView.swift

@@ -48,10 +48,10 @@ class TSTBDesktopPreviewView: TSBaseView {
         
         contentView.addSubview(islandView)
         islandView.snp.makeConstraints { make in
-            make.top.equalTo(10)
+            make.top.equalTo(10+k_Height_statusBar())
             make.centerX.equalToSuperview()
-            make.width.equalTo(351)
-            make.height.equalTo(80)
+            make.width.equalTo(islandView.width)
+            make.height.equalTo(islandView.height)
         }
     }
     

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

@@ -20,8 +20,13 @@ class TSTSIslandView: TSBaseView {
         return islandImageView
     }()
     
+    
+    lazy var nameLab: UILabel = {
+        let nameLab = UILabel.createLabel(text: "--",font: .font(size: 16),textColor: .white)
+        return nameLab
+    }()
     override func creatUI() {
-        
+        self.frame = CGRectMake(0, 0, 351*kDesignScale, 80*kDesignScale)
         contentView.addSubview(islandImageView)
         islandImageView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
@@ -33,5 +38,20 @@ class TSTSIslandView: TSBaseView {
             make.leading.equalTo(24)
             make.width.height.equalTo(56)
         }
+        
+        let mobileLab = UILabel.createLabel(text: "Mobile",font: .font(size: 13),textColor: "#A4A4A9".uiColor)
+        islandImageView.addSubview(mobileLab)
+        mobileLab.snp.makeConstraints { make in
+            make.top.equalTo(26)
+            make.leading.equalTo(showImageView.snp.trailing).offset(8)
+            make.height.equalTo(13)
+        }
+        
+        islandImageView.addSubview(nameLab)
+        nameLab.snp.makeConstraints { make in
+            make.top.equalTo(43)
+            make.leading.equalTo(showImageView.snp.trailing).offset(8)
+            make.height.equalTo(16)
+        }
     }
 }

Някои файлове не бяха показани, защото твърде много файлове са промени