Răsfoiți Sursa

2.7(1)打包

100Years 1 săptămână în urmă
părinte
comite
479c754820
42 a modificat fișierele cu 751 adăugiri și 70 ștergeri
  1. 8 4
      AIEmoji.xcodeproj/project.pbxproj
  2. 71 10
      AIEmoji/AppDelegate.swift
  3. 21 0
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-1.imageset/Contents.json
  4. BIN
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-1.imageset/img-premium-photos-1@2x.png
  5. 21 0
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-2.imageset/Contents.json
  6. BIN
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-2.imageset/img-premium-photos-2@2x.png
  7. 21 0
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-3.imageset/Contents.json
  8. BIN
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-3.imageset/img-premium-photos-3@2x.png
  9. 21 0
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-4.imageset/Contents.json
  10. BIN
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-4.imageset/img-premium-photos-4@2x.png
  11. 21 0
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-5.imageset/Contents.json
  12. BIN
      AIEmoji/Assets.xcassets/VIP/img-premium-photos-5.imageset/img-premium-photos-5@2x.png
  13. BIN
      AIEmoji/Assets.xcassets/VIP/purchase_bj.imageset/purchase_bj@2x.png
  14. BIN
      AIEmoji/Assets.xcassets/VIP/purchase_bj.imageset/purchase_bj@3x.png
  15. 2 1
      AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/Contents.json
  16. BIN
      AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/bootPage_0.png
  17. BIN
      AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/bootPage_0@2x.png
  18. BIN
      AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/bootPage_0@3x.png
  19. 2 1
      AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/Contents.json
  20. BIN
      AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/bootPage_2.png
  21. BIN
      AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/bootPage_2@2x.png
  22. BIN
      AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/bootPage_2@3x.png
  23. 22 0
      AIEmoji/Assets.xcassets/boot/boot_deepseek.imageset/Contents.json
  24. BIN
      AIEmoji/Assets.xcassets/boot/boot_deepseek.imageset/boot_deepseek@2x.png
  25. BIN
      AIEmoji/Assets.xcassets/boot/boot_deepseek.imageset/boot_deepseek@3x.png
  26. 22 0
      AIEmoji/Assets.xcassets/boot/boot_overlay.imageset/Contents.json
  27. BIN
      AIEmoji/Assets.xcassets/boot/boot_overlay.imageset/boot_overlay@2x.png
  28. BIN
      AIEmoji/Assets.xcassets/boot/boot_overlay.imageset/boot_overlay@3x.png
  29. 22 0
      AIEmoji/Assets.xcassets/boot/launch_rightArrow.imageset/Contents.json
  30. BIN
      AIEmoji/Assets.xcassets/boot/launch_rightArrow.imageset/launch_rightArrow@2x.png
  31. BIN
      AIEmoji/Assets.xcassets/boot/launch_rightArrow.imageset/launch_rightArrow@3x.png
  32. 190 36
      AIEmoji/Business/LaunchVC/TSBootPageVC.swift
  33. 11 2
      AIEmoji/Business/LaunchVC/TSLaunchVC.swift
  34. 21 2
      AIEmoji/Business/TSGenmojiVC/TSGenmojiGennerateVC/TSGenmojiGennerateVC.swift
  35. 14 2
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/View/TSGenmojiColSectionView.swift
  36. 2 1
      AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiCollectionViewModel.swift
  37. 23 2
      AIEmoji/Business/TSPTPGeneratorVC/TSPTPGeneratorVC/TSPTPGeneratorVC.swift
  38. 7 4
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/TSPhotoToPhotoVC.swift
  39. 2 2
      AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/VM/TSPhotoToPhotoVM.swift
  40. 92 1
      AIEmoji/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift
  41. 21 2
      AIEmoji/Business/TSTextGeneralPictureVC/TSTextPicGennerateVC/TSTextPicGennerateVC.swift
  42. 114 0
      AIEmoji/Business/VIewTool/ImagesAnimateScrollView.swift

+ 8 - 4
AIEmoji.xcodeproj/project.pbxproj

@@ -98,6 +98,7 @@
 		A83404D82D9D34ED00C140E4 /* Kelsi-fill.otf in Resources */ = {isa = PBXBuildFile; fileRef = A83404D62D9D34ED00C140E4 /* Kelsi-fill.otf */; };
 		A83404D92D9D34ED00C140E4 /* Kelsi-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = A83404D72D9D34ED00C140E4 /* Kelsi-Regular.otf */; };
 		A83404DB2D9D382200C140E4 /* AccentURW-Reg.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A83404DA2D9D382200C140E4 /* AccentURW-Reg.ttf */; };
+		A83404DD2D9E1D8C00C140E4 /* ImagesAnimateScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A83404DC2D9E1D8C00C140E4 /* ImagesAnimateScrollView.swift */; };
 		A85E478F2D67115A0018D62D /* TSTextGeneralPictureVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85E478E2D6711590018D62D /* TSTextGeneralPictureVC.swift */; };
 		A85E47922D6728A00018D62D /* TSTextGeneralPictureVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85E47912D67289F0018D62D /* TSTextGeneralPictureVM.swift */; };
 		A85E47962D672ADA0018D62D /* TSTextPicGennerateVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A85E47952D672AD90018D62D /* TSTextPicGennerateVC.swift */; };
@@ -297,6 +298,7 @@
 		A83404D62D9D34ED00C140E4 /* Kelsi-fill.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Kelsi-fill.otf"; sourceTree = "<group>"; };
 		A83404D72D9D34ED00C140E4 /* Kelsi-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Kelsi-Regular.otf"; sourceTree = "<group>"; };
 		A83404DA2D9D382200C140E4 /* AccentURW-Reg.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "AccentURW-Reg.ttf"; sourceTree = "<group>"; };
+		A83404DC2D9E1D8C00C140E4 /* ImagesAnimateScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagesAnimateScrollView.swift; sourceTree = "<group>"; };
 		A85E478E2D6711590018D62D /* TSTextGeneralPictureVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralPictureVC.swift; sourceTree = "<group>"; };
 		A85E47912D67289F0018D62D /* TSTextGeneralPictureVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextGeneralPictureVM.swift; sourceTree = "<group>"; };
 		A85E47952D672AD90018D62D /* TSTextPicGennerateVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSTextPicGennerateVC.swift; sourceTree = "<group>"; };
@@ -1392,6 +1394,7 @@
 		A8F775332D38FC8E00AA6E93 /* VIewTool */ = {
 			isa = PBXGroup;
 			children = (
+				A83404DC2D9E1D8C00C140E4 /* ImagesAnimateScrollView.swift */,
 				A89EA6B92D5DDE4E000EB181 /* TSPageNullView.swift */,
 				A8F7763B2D3B429A00AA6E93 /* TSCommonloadingView.swift */,
 				A83404D22D9D23CA00C140E4 /* TSGeneratorloadingView.swift */,
@@ -1765,6 +1768,7 @@
 				A89EA6562D59A9F4000EB181 /* TSChatUser.swift in Sources */,
 				A80327C12D8157CB00AF7878 /* TSTitleView.swift in Sources */,
 				A89EA6582D59A9F4000EB181 /* TSLayoutSizeCalculator.swift in Sources */,
+				A83404DD2D9E1D8C00C140E4 /* ImagesAnimateScrollView.swift in Sources */,
 				A89EA6592D59A9F4000EB181 /* CustomMessageFlowLayout.swift in Sources */,
 				A80E72792D42285500C64288 /* TSBootPageVC.swift in Sources */,
 				A80E726A2D409E5400C64288 /* TSDiyTLYFlowersView.swift in Sources */,
@@ -1940,7 +1944,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 3;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -1956,7 +1960,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 2.6;
+				MARKETING_VERSION = 2.7;
 				PRODUCT_BUNDLE_IDENTIFIER = com.girl.music.wallpaper;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -1979,7 +1983,7 @@
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 3;
+				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_TEAM = 65UD255J84;
 				ENABLE_USER_SCRIPT_SANDBOXING = NO;
 				GENERATE_INFOPLIST_FILE = YES;
@@ -1995,7 +1999,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 2.6;
+				MARKETING_VERSION = 2.7;
 				PRODUCT_BUNDLE_IDENTIFIER = com.girl.music.wallpaper;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";

+ 71 - 10
AIEmoji/AppDelegate.swift

@@ -37,17 +37,18 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
     
 
     func JudgmentSkipPage() {
-        //去掉引导页
-//        if UserDefaults.standard.string(forKey: "isFirstInstallApp") == nil {
-//            window?.rootViewController = TSBootPageVC { [weak self]  in
-//                guard let self = self else { return }
-//                UserDefaults.standard.set("1", forKey: "isFirstInstallApp")
-//                UserDefaults.standard.synchronize()
-//                goToTab()
-//            }
-//        }else{
+        if UserDefaults.standard.string(forKey: "isFirstInstallApp") == nil {
+            let bootPageVC  = TSBootPageVC { [weak self]  in
+                guard let self = self else { return }
+                UserDefaults.standard.set("1", forKey: "isFirstInstallApp")
+                UserDefaults.standard.synchronize()
+                goToTab()
+            }
+            let navi = TSBaseNavigationC(rootViewController: bootPageVC)
+            window?.rootViewController = navi
+        }else{
             goToTab()
-//        }
+        }
     }
     
 
@@ -67,6 +68,11 @@ extension AppDelegate {
     
     func applicationDidEnterBackground(_ application: UIApplication) {
         beginBackgroundTask()
+        
+//        ///添加测试数据
+//        let userDefaults = UserDefaults.standard
+//        let lastGreetingDateString = userDefaults.string(forKey: "kEveryDayPopPurchase")
+//        userDefaults.set(String(Int(lastGreetingDateString!)!+1), forKey: "kEveryDayPopPurchase")//测试用的
     }
     
     func beginBackgroundTask() {
@@ -83,6 +89,7 @@ extension AppDelegate {
     }
     
     func applicationWillEnterForeground(_ application: UIApplication) {
+        handleShowEveryDayPopPurchase()
         checkAppConfig()
     }
 }
@@ -90,6 +97,60 @@ extension AppDelegate {
 
 extension AppDelegate {
     
+    func handleShowEveryDayPopPurchase() {
+        AppDelegate.showEveryDayPopPurchase { vc in
+            if let vc = vc ,let rootvc = self.window?.rootViewController {
+                vc.modalPresentationStyle = .fullScreen
+                rootvc.present(vc, animated: true)
+            }
+        }
+    }
+    
+    static func showEveryDayPopPurchase(showVCHandle:@escaping (UIViewController?)->Void) {
+        
+        if UserDefaults.standard.string(forKey: "isFirstInstallApp") == nil || kPurchaseDefault.isVip {
+            //启动页->引导图->会员购买
+            showVCHandle(nil)
+            return
+        }
+        
+        //启动页->会员购买
+        // 1. 获取当前日期
+        let currentDate = Date()
+        let dateFormatter = DateFormatter()
+        dateFormatter.dateFormat = "yyyyMMdd"
+        let currentDateString = dateFormatter.string(from: currentDate)
+        
+        // 2. 获取上次弹窗的日期
+        let userDefaults = UserDefaults.standard
+        let lastGreetingDateString = userDefaults.string(forKey: "kEveryDayPopPurchase")
+        
+        // 3. 检查是否需要显示弹窗 "20250319"
+        if lastGreetingDateString != currentDateString {
+            
+            // 4. 弹窗付费引导
+            let vc = TSPurchaseVC()
+            vc.closePageBlock = {
+                showVCHandle(nil)
+            }
+
+            showVCHandle(vc)
+            // 5. 更新上次弹窗的日期
+            userDefaults.set(currentDateString, forKey: "kEveryDayPopPurchase")
+        }else{
+            showVCHandle(nil)
+        }
+    }
+    
+    
+    static func setsTopDayPopPurchase() {
+        let currentDate = Date()
+        let dateFormatter = DateFormatter()
+        dateFormatter.dateFormat = "yyyyMMdd"
+        let currentDateString = dateFormatter.string(from: currentDate)
+        UserDefaults.standard.set(currentDateString, forKey: "kEveryDayPopPurchase")
+    }
+    
     func checkAppConfig(){
         _ = TSNetworkShared.get(urlType: .config) { data,error in
             

+ 21 - 0
AIEmoji/Assets.xcassets/VIP/img-premium-photos-1.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/VIP/img-premium-photos-1.imageset/img-premium-photos-1@2x.png


+ 21 - 0
AIEmoji/Assets.xcassets/VIP/img-premium-photos-2.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/VIP/img-premium-photos-2.imageset/img-premium-photos-2@2x.png


+ 21 - 0
AIEmoji/Assets.xcassets/VIP/img-premium-photos-3.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/VIP/img-premium-photos-3.imageset/img-premium-photos-3@2x.png


+ 21 - 0
AIEmoji/Assets.xcassets/VIP/img-premium-photos-4.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/VIP/img-premium-photos-4.imageset/img-premium-photos-4@2x.png


+ 21 - 0
AIEmoji/Assets.xcassets/VIP/img-premium-photos-5.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/VIP/img-premium-photos-5.imageset/img-premium-photos-5@2x.png


BIN
AIEmoji/Assets.xcassets/VIP/purchase_bj.imageset/purchase_bj@2x.png


BIN
AIEmoji/Assets.xcassets/VIP/purchase_bj.imageset/purchase_bj@3x.png


+ 2 - 1
AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/Contents.json

@@ -5,11 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "bootPage_0.png",
+      "filename" : "bootPage_0@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
+      "filename" : "bootPage_0@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/bootPage_0.png


BIN
AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/bootPage_0@2x.png


BIN
AIEmoji/Assets.xcassets/boot/bootPage_0.imageset/bootPage_0@3x.png


+ 2 - 1
AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/Contents.json

@@ -5,11 +5,12 @@
       "scale" : "1x"
     },
     {
-      "filename" : "bootPage_2.png",
+      "filename" : "bootPage_2@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
+      "filename" : "bootPage_2@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/bootPage_2.png


BIN
AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/bootPage_2@2x.png


BIN
AIEmoji/Assets.xcassets/boot/bootPage_2.imageset/bootPage_2@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/boot/boot_deepseek.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/boot/boot_deepseek.imageset/boot_deepseek@2x.png


BIN
AIEmoji/Assets.xcassets/boot/boot_deepseek.imageset/boot_deepseek@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/boot/boot_overlay.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/boot/boot_overlay.imageset/boot_overlay@2x.png


BIN
AIEmoji/Assets.xcassets/boot/boot_overlay.imageset/boot_overlay@3x.png


+ 22 - 0
AIEmoji/Assets.xcassets/boot/launch_rightArrow.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/boot/launch_rightArrow.imageset/launch_rightArrow@2x.png


BIN
AIEmoji/Assets.xcassets/boot/launch_rightArrow.imageset/launch_rightArrow@3x.png


+ 190 - 36
AIEmoji/Business/LaunchVC/TSBootPageVC.swift

@@ -17,59 +17,213 @@ class TSBootPageVC: TSBaseVC {
     @MainActor required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
+    var index:Int = 0
+    let titleStrings = ["Change image Styles".localized,"AI image generation".localized,"Ask AI anything".localized]
+    let imageStrings = ["bootPage_0","bootPage_1","bootPage_2"]
+
+    lazy var titleLabel: UILabel = {
+        let titleLabel = UILabel.createLabel(text: titleStrings.safeString(At: index),font: .font(size: 20,weight: .semibold),textColor: .themeColor,textAlignment:.center,numberOfLines: 0)
+        return titleLabel
+    }()
+         
+    lazy var continueBtn: UIButton = {
+        let continueBtn = kCreateNormalSubmitBtn(title: "Continue".localized) { [weak self]  in
+            guard let self = self else { return }
+            clickContinue()
+        }
+        continueBtn.frame = CGRect(x: 0, y: 0, width: 343, height: 50)
+        continueBtn.titleLabel?.font = .font(size: 18,weight: .medium)
+        continueBtn.cornerRadius = 25.0
+        let imageView = UIImageView.createImageView(imageName: "launch_rightArrow",contentMode: .scaleToFill)
+        continueBtn.addSubview(imageView)
+        imageView.snp.makeConstraints { make in
+            make.width.height.equalTo(24)
+            make.centerY.equalToSuperview()
+            make.trailing.equalTo(-24)
+        }
+        
+        return continueBtn
+    }()
+    
+    @objc func clickBtn(_ btn:UIButton){
+        if btn.tag <= 2{
+            scrollView.contentOffset = CGPointMake(k_ScreenWidth*CGFloat(btn.tag), 0)
+        }else{
+            let vc = TSPurchaseVC()
+            vc.closePageBlock = { [weak self]  in
+                guard let self = self else { return }
+                onComplete()
+            }
+            self.navigationController?.pushViewController(vc, animated: true)
+        }
+    }
+    
+    
+    let boatAnimateScrollView:TSBootImagesAnimateScrollView = TSBootImagesAnimateScrollView()
     
     lazy var scrollView: UIScrollView = {
         let scrollView = UIScrollView()
         scrollView.isScrollEnabled = false
         scrollView.frame = self.view.bounds
 
-        let imageView0 = UIImageView.createImageView(imageName: "bootPage_0")
-        imageView0.frame = CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight)// 813*kDesignScale)
-        scrollView.addSubview(imageView0)
+
+        for (idx ,string) in imageStrings.enumerated() {
+            if idx == 1 {
+                boatAnimateScrollView.frame = CGRectMake(k_ScreenWidth * CGFloat(idx), -40.0, k_ScreenWidth, k_ScreenHeight)
+                scrollView.addSubview(boatAnimateScrollView)
+            }else{
+                let imageView = UIImageView.createImageView(imageName: string,contentMode: .scaleAspectFill)
+                imageView.frame = CGRectMake(k_ScreenWidth * CGFloat(idx), 0, k_ScreenWidth, k_ScreenHeight)
+                scrollView.addSubview(imageView)
+            }
+   
+        }
+
+        return scrollView
+    }()
+    
+    lazy var deepseek: UIImageView = {
+        let deepseek = UIImageView.createImageView(imageName: "boot_deepseek")
+        deepseek.isHidden = true
+        return deepseek
+    }()
+    
+    override func createView() {
+        setNavBarViewHidden(true)
+        self.view.backgroundColor = .black
+        self.view.addSubview(scrollView)
         
-        let imageView1 = UIImageView.createImageView(imageName: "bootPage_1")
-        imageView1.frame = CGRectMake(k_ScreenWidth, 0, k_ScreenWidth, 813*kDesignScale)
-        scrollView.addSubview(imageView1)
+        let overlayImageView = UIImageView.createImageView(imageName: "boot_overlay",contentMode: .scaleToFill)
+        overlayImageView.frame = CGRectMake(0, k_ScreenHeight-407*kDesignScale, k_ScreenWidth, 407*kDesignScale)
+        view.addSubview(overlayImageView)
+
+        deepseek.frame = CGRectMake((k_ScreenWidth-220)/2 , k_ScreenHeight-183-48, 220, 48)
+        view.addSubview(deepseek)
         
-        let imageView2 = UIImageView.createImageView(imageName: "bootPage_2")
-        imageView2.frame = CGRectMake(k_ScreenWidth*2, 0, k_ScreenWidth, 813*kDesignScale)
-        scrollView.addSubview(imageView2)
+        view.addSubview(titleLabel)
+        view.addSubview(continueBtn)
+        continueBtn.snp.makeConstraints { make in
+            make.width.equalTo(continueBtn.width)
+            make.height.equalTo(continueBtn.height)
+            make.bottom.equalTo(-26-k_Height_safeAreaInsetsBottom())
+            make.centerX.equalToSuperview()
+        }
         
-        let btnH = k_ScreenHeight/5
-        let btnTop = btnH*4
+        titleLabel.snp.makeConstraints { make in
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-16)
+            make.bottom.equalTo(continueBtn.snp.top).offset(-36)
+        }
         
-        let button0 = UIButton(frame: CGRectMake(0, btnTop, k_ScreenWidth, btnH))
-        button0.tag = 1
-        button0.addTarget(self, action: #selector(clickBtn(_:)), for: .touchUpInside)
-        scrollView.addSubview(button0)
+        boatAnimateScrollView.startAnimation()
+    }
+    
+    func clickContinue(){
+        index+=1
+        dePrint("clickContinue index=\(index)")
+        titleLabel.text = titleStrings.safeString(At: index)
         
-        let button1 = UIButton(frame: CGRectMake(k_ScreenWidth, btnTop, k_ScreenWidth, btnH))
-        button1.tag = 2
-        button1.addTarget(self, action: #selector(clickBtn(_:)), for: .touchUpInside)
-        scrollView.addSubview(button1)
+        deepseek.isHidden = !(index == 2)//第二页
         
-        let button2 = UIButton(frame: CGRectMake(k_ScreenWidth*2, btnTop, k_ScreenWidth, btnH))
-        button2.tag = 3
-        button2.addTarget(self, action: #selector(clickBtn(_:)), for: .touchUpInside)
-        scrollView.addSubview(button2)
+        if index <= 2{
+            scrollView.contentOffset = CGPointMake(k_ScreenWidth*CGFloat(index), 0)
+        }else{
+            let vc = TSPurchaseVC()
+            vc.closePageBlock = { [weak self]  in
+                guard let self = self else { return }
+                onComplete()
+            }
+            self.navigationController?.pushViewController(vc, animated: true)
+            AppDelegate.setsTopDayPopPurchase()
+        }
         
-        return scrollView
-    }()
+    }
     
+    func indexAdd(){
+        index+=1
+        if index > 2 {
+            index = 2
+        }
+    }
+}
+
+
+class TSBootImagesAnimateScrollView: TSBaseView {
     
-    @objc func clickBtn(_ btn:UIButton){
-        if btn.tag <= 2{
-            scrollView.contentOffset = CGPointMake(k_ScreenWidth*CGFloat(btn.tag), 0)
-        }else{
-            onComplete()
-            self.navBarClickLeftAction()
+    lazy var imageScroll1 = createImageScroll(imageName: "img-premium-photos-1", direction: .topToBottom)
+    lazy var imageScroll2 = createImageScroll(imageName: "img-premium-photos-2", direction: .bottomToTop)
+    lazy var imageScroll3 = createImageScroll(imageName: "img-premium-photos-3", direction: .topToBottom)
+    lazy var imageScroll4 = createImageScroll(imageName: "img-premium-photos-4", direction: .bottomToTop)
+    lazy var imageScroll5 = createImageScroll(imageName: "img-premium-photos-5", direction: .topToBottom)
+    
+    
+    override func creatUI() {
+        contentView.clipsToBounds = true
+        contentView.addSubview(imageScroll1)
+        contentView.addSubview(imageScroll2)
+        contentView.addSubview(imageScroll3)
+        contentView.addSubview(imageScroll4)
+        contentView.addSubview(imageScroll5)
+        
+        
+        let top = 0
+        let w = 110.0
+        let h = k_ScreenHeight
+        
+        //中间
+        imageScroll3.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(w)
+            make.height.equalTo(h)
         }
+        //左边
+        imageScroll2.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.trailing.equalTo(imageScroll3.snp.leading).offset(-12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        imageScroll1.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.trailing.equalTo(imageScroll2.snp.leading).offset(-12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        //右边
+        imageScroll4.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.leading.equalTo(imageScroll3.snp.trailing).offset(12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        imageScroll5.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.leading.equalTo(imageScroll4.snp.trailing).offset(12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
     }
     
-    override func createView() {
-        setNavBarViewHidden(true)
-        self.view.backgroundColor = .black
-        self.view.addSubview(scrollView)
+    func startAnimation(){
+        kDelayMainShort {//0.1 秒后开启动画
+            self.imageScroll1.startAnimation()
+            self.imageScroll2.startAnimation()
+            self.imageScroll3.startAnimation()
+            self.imageScroll4.startAnimation()
+            self.imageScroll5.startAnimation()
+        }
+    }
+    
+    func createImageScroll(imageName:String,direction:ImagesAnimateScrollView.`Direction`)->ImagesAnimateScrollView{
+        let imageScroll1: ImagesAnimateScrollView = ImagesAnimateScrollView()
+        imageScroll1.direction = direction
+        imageScroll1.animationImageName = imageName
+        imageScroll1.transform = CGAffineTransform(rotationAngle: CGFloat.pi/12)
+        return imageScroll1
     }
-
 }

+ 11 - 2
AIEmoji/Business/LaunchVC/TSLaunchVC.swift

@@ -58,9 +58,18 @@ class TSLaunchVC: UIViewController {
     }
 
     func enterApp() {
-        DispatchQueue.main.async {
-            self.dismissHandler?()
+        AppDelegate.showEveryDayPopPurchase { vc in
+            if let vc = vc {
+                self.navigationController?.pushViewController(vc, animated: true)
+            }else{
+                self.dismissHandler?()
+                
+            }
         }
+        
+//        DispatchQueue.main.async {
+//            self.dismissHandler?()
+//        }
     }
 
 

+ 21 - 2
AIEmoji/Business/TSGenmojiVC/TSGenmojiGennerateVC/TSGenmojiGennerateVC.swift

@@ -52,8 +52,27 @@ class TSGenmojiGennerateVC: TSBottomAlertVC {
     }
     
     override func closePage() {
-        viewModel.cancelAllRequest()
-        self.dismiss(animated: true, completion: nil)
+        TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
+            message: "As you leave, your generation will be interrupted and no result.".localized,
+            messageColor: .white,
+            messageFont: .systemFont(ofSize: 16),
+            
+            cancelTitle: "Leave".localized,
+            cancelColor: .white,
+            
+            confirmTitle: "Wait".localized,
+            confirmColor: .themeColor,
+            
+            cancelAction: { [weak self]  in
+                guard let self = self else { return }
+                print("用户点击了Leave")
+                viewModel.cancelAllRequest()
+                self.dismiss(animated: true, completion: nil)
+            },
+            confirmAction: {
+                print("用户点击了Stay")
+            }
+        ))
     }
     
     

+ 14 - 2
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/View/TSGenmojiColSectionView.swift

@@ -13,6 +13,10 @@ class TSGenmojiColSectionView: TSBaseCollectionnReusableView {
     }()
     
     
+    lazy var leftSubLab: UILabel = {
+        return UILabel.createLabel(font: .font(size: 12,weight: .medium),textColor: .fromHex("#A7A7A7"))
+    }()
+    
     lazy var delBtn: UIButton = {
         let delBtn = UIButton.createButton(image: UIImage(named: "delete")){ [weak self]  in
             guard let self = self else { return }
@@ -22,14 +26,22 @@ class TSGenmojiColSectionView: TSBaseCollectionnReusableView {
     }()
     
     override func creatUI() {
+        
+        bgContentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
+        
         let centerYOffset = 8.0
         bgContentView.addSubview(leftLab)
-        bgContentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)))
         leftLab.snp.makeConstraints { make in
             make.leading.equalTo(16)
             make.centerY.equalToSuperview().offset(centerYOffset)
         }
         
+        bgContentView.addSubview(leftSubLab)
+        leftSubLab.snp.makeConstraints { make in
+            make.leading.equalTo(leftLab.snp.trailing).offset(8)
+            make.centerY.equalTo(leftLab)
+        }
+        
         bgContentView.addSubview(delBtn)
         delBtn.snp.makeConstraints { make in
             make.trailing.equalTo(-6)
@@ -42,7 +54,7 @@ class TSGenmojiColSectionView: TSBaseCollectionnReusableView {
         super.renderView(with: object, component: component, attributes: attributes)
         if let componentReuseViewModel = object as? TSGenmojiColComponentReuseViewModel {
             leftLab.text = componentReuseViewModel.sectionModel.name
-            
+            leftSubLab.text = componentReuseViewModel.sectionModel.subText
             switch componentReuseViewModel.sectionModel.style {
             case .history,.textPicHistory,.ptpPicHistory:
                 delBtn.isHidden = false

+ 2 - 1
AIEmoji/Business/TSGenmojiVC/TSGenmojiVC/ViewModel/TSGenmojiCollectionViewModel.swift

@@ -97,7 +97,6 @@ enum TSGenmojiCoLStyple : Int {
         case .ptpEntrance:
             return CGSize(width: k_ScreenWidth-32, height: 117)
         case .ptpUpload:
-//            return CGSize(width: k_ScreenWidth, height: 248)
             return CGSize(width: k_ScreenWidth, height: 232)
         case .ptpSelectStyle:
             return CGSize(width: k_ScreenWidth, height: 110)
@@ -144,10 +143,12 @@ class TSGenmojiCoLSectionModel: TSBaseModel {
     }
     
     var name:String = "History"
+    var subText:String = ""
     var items:[TSGenmojiCoLItemModel] = [TSGenmojiCoLItemModel]()
     override func mapping(map: ObjectMapper.Map) {
         style    <- map["style"]
         name    <- map["name"]
+        subText    <- map["subText"]
         items   <- map["items"]
     }
 

+ 23 - 2
AIEmoji/Business/TSPTPGeneratorVC/TSPTPGeneratorVC/TSPTPGeneratorVC.swift

@@ -50,8 +50,29 @@ class TSPTPGeneratorVC: TSAIPhotoGeneratorBaseVC {
     }
     
     override func closePage() {
-        viewModel.cancelAllRequest()
-        self.dismiss(animated: true, completion: nil)
+        
+        TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
+            message: "As you leave, your generation will be interrupted and no result.".localized,
+            messageColor: .white,
+            messageFont: .systemFont(ofSize: 16),
+            
+            cancelTitle: "Leave".localized,
+            cancelColor: .white,
+            
+            confirmTitle: "Wait".localized,
+            confirmColor: .themeColor,
+            
+            cancelAction: { [weak self]  in
+                guard let self = self else { return }
+                print("用户点击了Leave")
+                viewModel.cancelAllRequest()
+                self.dismiss(animated: true, completion: nil)
+            },
+            confirmAction: {
+                print("用户点击了Stay")
+            }
+        ))
+   
     }
     
     //重试

+ 7 - 4
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/TSPhotoToPhotoVC.swift

@@ -100,10 +100,13 @@ class TSPhotoToPhotoVC: TSBaseVC {
                         photoPickerManager.pickSinglePhoto { [weak self] image in
                             guard let self = self else { return }
                             if let image = image {
-                                viewModel.upLoadImage = image
-                                UIView.performWithoutAnimation {
-                                    cp.collectionView.reloadSections(IndexSet(integer: 0))
-                                    //                                viewModel.uploadImage()
+                                if image.isLargerThan(byteSize: 10 * 1024 * 1024) {
+                                    TSToastShared.showToast(text: "Photo must be smaller than 10MB.".localized)
+                                }else{
+                                    viewModel.upLoadImage = image
+                                    UIView.performWithoutAnimation {
+                                        cp.collectionView.reloadSections(IndexSet(integer: 0))
+                                    }
                                 }
                             }
                         }

+ 2 - 2
AIEmoji/Business/TSPTPGeneratorVC/TSPhotoToPhotoVC/VM/TSPhotoToPhotoVM.swift

@@ -63,8 +63,8 @@ class TSPhotoToPhotoVM {
     lazy var uploadSectionModel: TSGenmojiCoLSectionModel = {
         let uploadSectionModel = TSGenmojiCoLSectionModel()
         uploadSectionModel.style = .ptpUpload
-        uploadSectionModel.name = "Upload Image".localized
-        
+        uploadSectionModel.name = "Upload Photo".localized
+        uploadSectionModel.subText = "(Size ≤ 10Mb)".localized
         let itemModel = TSGenmojiCoLItemModel()
         itemModel.style = .ptpUpload
         itemModel.ptpStyleModels = [updateImageModel]

+ 92 - 1
AIEmoji/Business/TSPurchaseMembershipVC/TSPurchaseVC.swift

@@ -35,6 +35,91 @@ class TSPurchaseVC: TSBaseVC {
         return purchaseManager
     }()
     
+    
+    func createImageScroll(imageName:String,direction:ImagesAnimateScrollView.`Direction`)->ImagesAnimateScrollView{
+        let imageScroll1: ImagesAnimateScrollView = ImagesAnimateScrollView()
+        imageScroll1.direction = direction
+        imageScroll1.animationImageName = imageName
+        imageScroll1.transform = CGAffineTransform(rotationAngle: CGFloat.pi/12)
+        return imageScroll1
+    }
+    
+    lazy var bgView: UIView = {
+        let bgView = UIView()
+        bgView.backgroundColor = .clear
+        
+        let imageScroll1 = createImageScroll(imageName: "img-premium-photos-1", direction: .topToBottom)
+        let imageScroll2 = createImageScroll(imageName: "img-premium-photos-2", direction: .bottomToTop)
+        let imageScroll3 = createImageScroll(imageName: "img-premium-photos-3", direction: .topToBottom)
+        let imageScroll4 = createImageScroll(imageName: "img-premium-photos-4", direction: .bottomToTop)
+        let imageScroll5 = createImageScroll(imageName: "img-premium-photos-5", direction: .topToBottom)
+        
+        bgView.addSubview(imageScroll1)
+        bgView.addSubview(imageScroll2)
+        bgView.addSubview(imageScroll3)
+        bgView.addSubview(imageScroll4)
+        bgView.addSubview(imageScroll5)
+        
+        let top = -40.0
+        let w = 110.0
+        let h = 600//554.0
+        
+        //中间
+        imageScroll3.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        //左边
+        imageScroll2.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.trailing.equalTo(imageScroll3.snp.leading).offset(-12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        imageScroll1.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.trailing.equalTo(imageScroll2.snp.leading).offset(-12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        //右边
+        imageScroll4.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.leading.equalTo(imageScroll3.snp.trailing).offset(12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        imageScroll5.snp.makeConstraints { make in
+            make.top.equalTo(top)
+            make.leading.equalTo(imageScroll4.snp.trailing).offset(12)
+            make.width.equalTo(w)
+            make.height.equalTo(h)
+        }
+        
+        
+        kDelayMainShort {//0.1 秒后开启动画
+            imageScroll1.startAnimation()
+            imageScroll2.startAnimation()
+            imageScroll3.startAnimation()
+            imageScroll4.startAnimation()
+            imageScroll5.startAnimation()
+        }
+        
+        let imageView = UIImageView.createImageView(imageName: "purchase_bj",contentMode: .scaleAspectFill)
+        bgView.addSubview(imageView)
+        
+        imageView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        return bgView
+    }()
+    
     lazy var hostVc: UIHostingController<PurchaseView> = {
         let vc = UIHostingController(rootView: PurchaseView(viewModel: viewModel))
         vc.view.backgroundColor = .clear
@@ -44,7 +129,13 @@ class TSPurchaseVC: TSBaseVC {
     override func createView() {
         addNormalNavBarView()
         _ = setNavigationItem("", imageName: "close_gray", direction: .left, action: #selector(closePage))
-        setViewBgImageNamed(named: "purchase_bj")
+        
+        view.insertSubview(bgView, at: 0)
+        bgView.snp.makeConstraints { make in
+            make.leading.trailing.bottom.top.equalToSuperview()
+        }
+        
+//        setViewBgImageNamed(named: "purchase_bj")
 
         contentView.addSubview(hostVc.view)
         hostVc.view.snp.makeConstraints { make in

+ 21 - 2
AIEmoji/Business/TSTextGeneralPictureVC/TSTextPicGennerateVC/TSTextPicGennerateVC.swift

@@ -40,8 +40,27 @@ class TSTextPicGennerateVC: TSAIPhotoGeneratorBaseVC {
     }
     
     override func closePage() {
-        viewModel.cancelAllRequest()
-        self.dismiss(animated: true, completion: nil)
+        TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
+            message: "As you leave, your generation will be interrupted and no result.".localized,
+            messageColor: .white,
+            messageFont: .systemFont(ofSize: 16),
+            
+            cancelTitle: "Leave".localized,
+            cancelColor: .white,
+            
+            confirmTitle: "Wait".localized,
+            confirmColor: .themeColor,
+            
+            cancelAction: { [weak self]  in
+                guard let self = self else { return }
+                print("用户点击了Leave")
+                viewModel.cancelAllRequest()
+                self.dismiss(animated: true, completion: nil)
+            },
+            confirmAction: {
+                print("用户点击了Stay")
+            }
+        ))
     }
     
     

+ 114 - 0
AIEmoji/Business/VIewTool/ImagesAnimateScrollView.swift

@@ -0,0 +1,114 @@
+//
+//  ImagesAnimateScrollView.swift
+//  ContactPoster
+//
+//  Created by TSYH on 2024/3/4.
+//
+
+import UIKit
+
+class ImagesAnimateScrollView: UIView {
+    enum `Direction` {
+        case leftToRight
+        case rightToLeft
+        case topToBottom
+        case bottomToTop
+    }
+    
+    lazy var imageView1 = UIImageView()
+    lazy var imageView2 = UIImageView()
+    
+    var animationImageName: String? {
+        didSet {
+            if let imageName = animationImageName,
+               let image = UIImage(named: imageName) {
+                imageView1.image = image
+                imageView2.image = image
+                imageView1.frame.size = image.size
+                imageView2.frame.size = image.size
+                
+                imageView1.contentMode = .scaleAspectFill
+                imageView2.contentMode = .scaleAspectFill
+            }
+        }
+    }
+    
+    lazy var direction: `Direction` = .leftToRight
+    lazy var margin: CGFloat = 16.0
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setupObser()
+    }
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+        setupObser()
+    }
+    
+    func setupObser() {
+        clipsToBounds = true
+        NotificationCenter.default.addObserver(self, selector: #selector(onAppActiveNotify(_:)), name: UIApplication.didBecomeActiveNotification, object: nil)
+    }
+    
+    @objc func onAppActiveNotify(_ notify: Notification) {
+        DispatchQueue.main.async {
+            self.startAnimation()
+        }
+    }
+    
+    func setupSubviews() {
+        if imageView1.superview == nil {
+            addSubview(imageView1)
+            addSubview(imageView2)
+            switch direction {
+            case .leftToRight:
+                imageView1.x = width-imageView1.width
+                imageView1.y = 0
+                imageView2.y = 0
+                imageView2.x = imageView1.x-imageView2.width-margin
+            case .rightToLeft:
+                imageView1.x = 0
+                imageView1.y = 0
+                imageView2.y = 0
+                imageView2.x = imageView1.width+margin
+            case .topToBottom:
+                imageView1.x = 0
+                imageView1.y = height-imageView1.height
+                imageView2.x = 0
+                imageView2.y = imageView1.y-imageView2.height-margin
+            case .bottomToTop:
+                imageView1.x = 0
+                imageView1.y = 0
+                imageView2.x = 0
+                imageView2.y = imageView1.height+margin
+            }
+        }
+    }
+    
+    func startAnimation() {
+        setupSubviews()
+        
+        for iv in [imageView1, imageView2] {
+            iv.layer.removeAllAnimations()
+        }
+        
+        var moveAnim = CABasicAnimation(keyPath: "position.x")
+        switch direction {
+        case .leftToRight:
+            moveAnim.byValue = imageView1.width
+        case .rightToLeft:
+            moveAnim.byValue = -imageView1.width
+        case .topToBottom:
+            moveAnim = CABasicAnimation(keyPath: "position.y")
+            moveAnim.byValue = imageView1.height
+        case .bottomToTop:
+            moveAnim = CABasicAnimation(keyPath: "position.y")
+            moveAnim.byValue = -imageView1.height
+        }
+        moveAnim.duration = 36
+        moveAnim.repeatCount = .greatestFiniteMagnitude
+        imageView1.layer.add(moveAnim, forKey: "move")
+        imageView2.layer.add(moveAnim, forKey: "move")
+    }
+}