kailen 2 tygodni temu
rodzic
commit
549be2aaa5
30 zmienionych plików z 284 dodań i 132 usunięć
  1. 4 0
      AIEmoji.xcodeproj/project.pbxproj
  2. 23 0
      AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/Contents.json
  3. BIN
      AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/ic_diy_video_tip@1x.png
  4. BIN
      AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/ic_diy_video_tip@2x.png
  5. BIN
      AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/ic_diy_video_tip@3x.png
  6. 1 1
      AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSAIChatVM.swift
  7. 1 1
      AIEmoji/Business/TSPurchaseMembershipVC/View/PurchaseView.swift
  8. 1 0
      AIEmoji/Business2/DIYVideo/Elements/TSAIModelElementView.swift
  9. 24 3
      AIEmoji/Business2/DIYVideo/Elements/TSBaseSegementElementView.swift
  10. 17 19
      AIEmoji/Business2/DIYVideo/Elements/TSDiyVideoPromptElementView.swift
  11. 30 0
      AIEmoji/Business2/DIYVideo/Elements/TSDiyVideoUploadImageView.swift
  12. 8 0
      AIEmoji/Business2/DIYVideo/Elements/TSSegementElements.swift
  13. 1 1
      AIEmoji/Business2/DIYVideo/Model/TSDiyVideoElementType.swift
  14. 45 32
      AIEmoji/Business2/DIYVideo/TSAIDiyVideoPTVVC/TSAIDiyVideoPTVVC.swift
  15. 56 35
      AIEmoji/Business2/DIYVideo/TSAIDiyVideoTTVVC/TSAIDiyVideoTTVVC.swift
  16. 14 21
      AIEmoji/Business2/DIYVideo/TSAIDiyVideoVC.swift
  17. 1 1
      AIEmoji/Business2/DIYVideo/ViewModel/TSAIDiyVideoTTBaseViewModel.swift
  18. 4 3
      AIEmoji/Business2/DisCover/Data/TSDiscoverViewModel+Data.swift
  19. 8 1
      AIEmoji/Business2/DisCover/TSAIGenerateVC/TSAIGenerateVC.swift
  20. 3 3
      AIEmoji/Business2/DisCover/TSDiscoverVC/Cell/TSDiscoverBannerCell.swift
  21. 7 2
      AIEmoji/Business2/DisCover/TSPTPUploadImageVC/View/TSUploadImageView.swift
  22. 4 1
      AIEmoji/de.lproj/Localizable.strings
  23. 4 1
      AIEmoji/en.lproj/Localizable.strings
  24. 4 1
      AIEmoji/es.lproj/Localizable.strings
  25. 4 1
      AIEmoji/ja.lproj/Localizable.strings
  26. 4 1
      AIEmoji/ko.lproj/Localizable.strings
  27. 4 1
      AIEmoji/pt-BR.lproj/Localizable.strings
  28. 4 1
      AIEmoji/pt-PT.lproj/Localizable.strings
  29. 4 1
      AIEmoji/zh-Hans.lproj/Localizable.strings
  30. 4 1
      AIEmoji/zh-Hant.lproj/Localizable.strings

+ 4 - 0
AIEmoji.xcodeproj/project.pbxproj

@@ -15,6 +15,7 @@
 		60B384612E39C33200D77E20 /* TSDiyVideoPopoverViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60B384602E39C33200D77E20 /* TSDiyVideoPopoverViewController.swift */; };
 		60C377F92E3A408B0098A601 /* TSDiscoverBannerItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C377F82E3A408B0098A601 /* TSDiscoverBannerItemCell.swift */; };
 		60C805B32E3B1CCB0051164F /* TSDiyStyleElementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C805B22E3B1CCB0051164F /* TSDiyStyleElementView.swift */; };
+		60C807852E3C8EAF0051164F /* TSDiyVideoUploadImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C807842E3C8EAF0051164F /* TSDiyVideoUploadImageView.swift */; };
 		60EE9A782E386EB200565900 /* TSAIModelElementView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60EE9A772E386EB200565900 /* TSAIModelElementView.swift */; };
 		60EE9A7D2E38720700565900 /* TSAIDiyVideoTTBaseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60EE9A7C2E38720700565900 /* TSAIDiyVideoTTBaseViewModel.swift */; };
 		60EE9A7F2E38727100565900 /* TSDiyVideoElementType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60EE9A7E2E38727100565900 /* TSDiyVideoElementType.swift */; };
@@ -381,6 +382,7 @@
 		60B384602E39C33200D77E20 /* TSDiyVideoPopoverViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSDiyVideoPopoverViewController.swift; sourceTree = "<group>"; };
 		60C377F82E3A408B0098A601 /* TSDiscoverBannerItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSDiscoverBannerItemCell.swift; sourceTree = "<group>"; };
 		60C805B22E3B1CCB0051164F /* TSDiyStyleElementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSDiyStyleElementView.swift; sourceTree = "<group>"; };
+		60C807842E3C8EAF0051164F /* TSDiyVideoUploadImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSDiyVideoUploadImageView.swift; sourceTree = "<group>"; };
 		60EE9A772E386EB200565900 /* TSAIModelElementView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIModelElementView.swift; sourceTree = "<group>"; };
 		60EE9A7C2E38720700565900 /* TSAIDiyVideoTTBaseViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAIDiyVideoTTBaseViewModel.swift; sourceTree = "<group>"; };
 		60EE9A7E2E38727100565900 /* TSDiyVideoElementType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSDiyVideoElementType.swift; sourceTree = "<group>"; };
@@ -809,6 +811,7 @@
 				60EE9A772E386EB200565900 /* TSAIModelElementView.swift */,
 				60C805B22E3B1CCB0051164F /* TSDiyStyleElementView.swift */,
 				60EE9A842E38A7C200565900 /* TSDiyVideoPromptElementView.swift */,
+				60C807842E3C8EAF0051164F /* TSDiyVideoUploadImageView.swift */,
 				60EE9A802E3898A600565900 /* TSBaseSegementElementView.swift */,
 				60EE9A822E38A1ED00565900 /* TSSegementElements.swift */,
 			);
@@ -2940,6 +2943,7 @@
 				A80327C32D81581D00AF7878 /* TSTTPStyleView.swift in Sources */,
 				A85E47922D6728A00018D62D /* TSTextGeneralPictureVM.swift in Sources */,
 				A89EA6B82D5D7EE9000EB181 /* TSAIChatHistoryModel.swift in Sources */,
+				60C807852E3C8EAF0051164F /* TSDiyVideoUploadImageView.swift in Sources */,
 				A80E72722D40F86000C64288 /* TSLaunchVC.swift in Sources */,
 				A82D609B2DB9D83600596190 /* TSBaseHistoryManager.swift in Sources */,
 				A8F775352D38FC9A00AA6E93 /* TSViewTool.swift in Sources */,

+ 23 - 0
AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/Contents.json

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

BIN
AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/ic_diy_video_tip@1x.png


BIN
AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/ic_diy_video_tip@2x.png


BIN
AIEmoji/Assets.xcassets/DiyVideo/ic_diy_video_tip.imageset/ic_diy_video_tip@3x.png


+ 1 - 1
AIEmoji/Business/AIChat/TSChatViewController/ViewModel/TSAIChatVM.swift

@@ -191,7 +191,7 @@ extension TSAIChatVM {
             msg.appendUIDict = [.topView:TSChatMessageUIBaseModel.creat(viewClass: "TSMSGAIDefaultHeaderView", msgModel: msg)]
             return [msg]
         case .perfectHint :
-            let aiString = "Hello! I'm DeepSeek, ready to help you enrich your picture ideas.".localized
+            let aiString = "Hello! I'm DeepSeek, ready to help you enrich your ideas.".localized
             let msg = TSChatMessage(kind: .attributedText(kMDAttributedString(text: aiString)), user: kAIUser, messageId: "", date: Date())
             msg.messageType = .aiRobotWelcome
      

+ 1 - 1
AIEmoji/Business/TSPurchaseMembershipVC/View/PurchaseView.swift

@@ -22,7 +22,7 @@ struct PurchaseView :View {
             VStack(alignment: .leading, spacing: 12, content: {
                 TSFeatureItemView(image: .purchaseIconPhoto, text: "Unlimited Photo Filters & Styles".localized)
                 TSFeatureItemView(image: .purchaseIconUnlimited, text: "Unlimited AI Image Generation".localized)
-                TSFeatureItemView(image: .purchaseIconVideo, text: String(format: "%d Video Effect Generations".localized,viewModel.selectedType.creatVideoMaxNum))
+                TSFeatureItemView(image: .purchaseIconVideo, text: String(format: "%d Video Effects & Video Generations".localized,viewModel.selectedType.creatVideoMaxNum))
                 TSFeatureItemView(image: .purchaseIconAd, text: "No Ads or Watermarks".localized)
             }).multilineTextAlignment(.center).font(.font(size: 16,weight:.regular)).foregroundColor(.white)
             

+ 1 - 0
AIEmoji/Business2/DIYVideo/Elements/TSAIModelElementView.swift

@@ -46,6 +46,7 @@ class TSAIModelElementView: UIView, TSDiyVideoElement {
         bgView.cornerRadius = 16
         bgView.addSubview(modelView)
         bgView.addSubview(arrowIcon)
+        arrowIcon.isHidden = true
         addSubview(titleLabel)
         addSubview(bgView)
     }

+ 24 - 3
AIEmoji/Business2/DIYVideo/Elements/TSBaseSegementElementView.swift

@@ -17,9 +17,20 @@ class TSBaseSegementElementView: UIView, TSDiyVideoElement {
         .resolution
     }
 
+    var needTip: Bool {
+        false
+    }
+
+    var tipString: String {
+        ""
+    }
+
     var aiModelType: TSDiyAiModelType = .ViduQ1
 
     lazy var titleLabel: UILabel = UILabel.createLabel()
+    lazy var tipButton: UIButton = .createButton(image: .icDiyVideoTip) {
+        TSToastTool.shared.showToast(text: self.tipString)
+    }
 
     lazy var segmentedView: BetterSegmentedControl = {
         let segmentedView = BetterSegmentedControl(
@@ -36,7 +47,7 @@ class TSBaseSegementElementView: UIView, TSDiyVideoElement {
                       .indicatorViewBorderWidth(1),
                       .indicatorViewBorderColor(UIColor.themeColor),
                       .indicatorViewInset(2),
-                      .cornerRadius(18),
+                      .cornerRadius(20),
                       .animationSpringDamping(1.0)]
         )
         segmentedView.addTarget(self, action: #selector(segmentedControlValueChanged(_:)), for: .valueChanged)
@@ -76,9 +87,12 @@ class TSBaseSegementElementView: UIView, TSDiyVideoElement {
     func addChildren() {
         titleLabel.text = type.sectionTitle
         titleLabel.textColor = .white.withAlphaComponent(0.8)
-        titleLabel.font = .font(size: 14,weight: .medium)
+        titleLabel.font = .font(size: 14, weight: .medium)
         addSubview(titleLabel)
+        addSubview(tipButton)
         addSubview(segmentedView)
+
+        tipButton.isHidden = !needTip
     }
 
     func makeConstraints() {
@@ -86,10 +100,17 @@ class TSBaseSegementElementView: UIView, TSDiyVideoElement {
             make.leading.equalToSuperview().offset(16)
             make.top.equalToSuperview().offset(22)
         }
+
+        tipButton.snp.makeConstraints { make in
+            make.leading.equalTo(titleLabel.snp.trailing).offset(8)
+            make.centerY.equalTo(titleLabel)
+            make.width.height.equalTo(16)
+        }
+
         segmentedView.snp.makeConstraints { make in
             make.horizontalEdges.equalToSuperview().inset(10)
             make.top.equalTo(titleLabel.snp.bottom).offset(12)
-            make.height.equalTo(36)
+            make.height.equalTo(40)
             make.bottom.equalToSuperview()
         }
     }

+ 17 - 19
AIEmoji/Business2/DIYVideo/Elements/TSDiyVideoPromptElementView.swift

@@ -18,17 +18,12 @@ class TSDiyTextPromptElementView: TSPromptTextView, TSDiyVideoElement {
     
     override init(randomTextArray: [String], textChangedBlock: @escaping (String) -> Void) {
         super.init(randomTextArray: randomTextArray, textChangedBlock: textChangedBlock)
-        self.inspirationBtn.isHidden = true
+       
     }
     
     override func makeConstraints() {
         super.makeConstraints()
 
-        AIView.snp.remakeConstraints { make in
-            make.height.equalTo(28)
-            make.bottom.equalTo(-16)
-            make.leading.equalToSuperview().offset(16)
-        }
     }
     
     @MainActor required init?(coder: NSCoder) {
@@ -47,8 +42,8 @@ class TSDiyVideoPromptElementView: TSPromptTextView, TSDiyVideoElement {
     var uploadClickAction: (() -> Void)?
     var deleteClickAction: (() -> Void)?
 
-    lazy var uploadView: TSUploadImageView = {
-        let upload = TSUploadImageView()
+    lazy var uploadView: TSDiyVideoUploadImageView = {
+        let upload = TSDiyVideoUploadImageView()
         upload.clickBgViewBlock = { [weak self] in
             guard let self = self else { return }
             uploadClickAction?()
@@ -70,6 +65,7 @@ class TSDiyVideoPromptElementView: TSPromptTextView, TSDiyVideoElement {
 
     override init(randomTextArray: [String], textChangedBlock: @escaping (String) -> Void) {
         super.init(randomTextArray: randomTextArray, textChangedBlock: textChangedBlock)
+        self.inspirationBtn.isHidden = true
     }
 
     override func creatUI() {
@@ -100,11 +96,12 @@ class TSDiyVideoPromptElementView: TSPromptTextView, TSDiyVideoElement {
             make.horizontalEdges.equalToSuperview().inset(16)
             make.bottom.equalToSuperview()
         }
-
+        let itemWidth = k_ScreenWidth - 56
+        let itemHeight = itemWidth * (230.0 / 320.0)
         uploadView.snp.makeConstraints { make in
             make.horizontalEdges.equalToSuperview()
             make.top.equalToSuperview().offset(12)
-            make.height.equalTo(280 * kDesignScale)
+            make.height.equalTo(itemHeight)
         }
 
         customTextView.snp.makeConstraints { make in
@@ -114,17 +111,18 @@ class TSDiyVideoPromptElementView: TSPromptTextView, TSDiyVideoElement {
             make.height.equalTo(100)
         }
 
-        inspirationBtn.snp.makeConstraints { make in
-            make.height.equalTo(28)
-            make.leading.equalTo(16)
-            make.top.equalTo(customTextView.snp.bottom).offset(12)
-            make.bottom.equalTo(textBgView.snp.bottom).offset(-12)
-        }
+//        inspirationBtn.snp.makeConstraints { make in
+//            make.height.equalTo(28)
+//            make.leading.equalTo(16)
+//            make.top.equalTo(customTextView.snp.bottom).offset(12)
+//            make.bottom.equalTo(textBgView.snp.bottom).offset(-12)
+//        }
 
-        AIView.snp.makeConstraints { make in
+
+        AIView.snp.remakeConstraints { make in
             make.height.equalTo(28)
-            make.leading.equalTo(inspirationBtn.snp.trailing).offset(8)
-            make.centerY.equalTo(inspirationBtn)
+            make.bottom.equalTo(-16)
+            make.leading.equalToSuperview().offset(16)
         }
 
         clearBtn.snp.makeConstraints { make in

+ 30 - 0
AIEmoji/Business2/DIYVideo/Elements/TSDiyVideoUploadImageView.swift

@@ -0,0 +1,30 @@
+//
+//  TSDiyVideoUploadImageView.swift
+//  AIEmoji
+//
+//  Created by nkl on 2025/8/1.
+//
+
+import Foundation
+
+class TSDiyVideoUploadImageView: TSUploadImageView {
+    override func makeConstraints() {
+        let itemWidth = k_ScreenWidth - 56
+        let itemHeight = itemWidth * (230.0 / 320.0)
+        uploadImageBgView.snp.makeConstraints { make in
+            make.width.equalTo(itemWidth)
+            make.height.equalTo(itemHeight)
+            make.centerX.equalToSuperview()
+        }
+
+        deleteBtn.snp.makeConstraints { make in
+            make.top.equalTo(0)
+            make.trailing.equalTo(-32 * kDesignScale)
+            make.width.height.equalTo(32)
+        }
+
+        uploadVideoView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+    }
+}

+ 8 - 0
AIEmoji/Business2/DIYVideo/Elements/TSSegementElements.swift

@@ -24,6 +24,14 @@ class TSMovementElementView: TSBaseSegementElementView {
         .movementAmplitude
     }
     
+    override var needTip: Bool {
+        true
+    }
+    
+    override var tipString: String {
+        "Auto: Fits your prompt automatically Small / Medium / Large: Manual amplitude selection"
+    }
+    
     override var param: String {
         let raw = type.getModelConfigSegments(aiModel: aiModelType).safeString(At: segmentedView.index)
         let mType = TSDiyMovementType(rawValue: raw)

+ 1 - 1
AIEmoji/Business2/DIYVideo/Model/TSDiyVideoElementType.swift

@@ -59,7 +59,7 @@ enum TSDiyVideoElementType {
             }
         case .videoLength:
             aiModel.lengthTypes.map {
-                $0.rawValue
+                $0.showText
             }
         case .style:
             aiModel.stypeTypes.map {

+ 45 - 32
AIEmoji/Business2/DIYVideo/TSAIDiyVideoPTVVC/TSAIDiyVideoPTVVC.swift

@@ -17,30 +17,28 @@ class TSAIDiyVideoPTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
             TSDiscoverVC.enterSelectPhotos(target: self, style: .pictureToVideo, hintType: 0) { [weak self] image in
                 guard let self = self else { return }
                 self.viewModel.uploadImage = image
+                viewModel.judgeWasFinishedEdit()
             }
         }
         promptTextView.deleteClickAction = { [weak self] in
             guard let self = self else { return }
             self.viewModel.uploadImage = nil
+            viewModel.judgeWasFinishedEdit()
         }
         promptTextView.textChangedBlock = { [weak self] text in
             guard let self = self else { return }
             self.viewModel.prompt = text
+            viewModel.judgeWasFinishedEdit()
         }
         promptTextView.sendBolck = { [weak self] text in
             guard let self = self else { return }
             self.viewModel.prompt = text
+            promptTextView.customTextView.resignFirstResponder()
+            viewModel.judgeWasFinishedEdit()
         }
         promptTextView.AIBolck = { [weak self] in
             guard let self = self else { return }
-            let vc = TSChatViewController()
-            vc.viewModel.uiStyle = .perfectHint
-
-            vc.textBlock = { [weak self] text, _ in
-                guard let self = self else { return }
-                promptTextView.setText(text: text)
-            }
-            kPushVC(target: self, modelVC: vc)
+            kPushVC(target: self, modelVC: aiVc)
         }
         return promptTextView
     }()
@@ -48,7 +46,17 @@ class TSAIDiyVideoPTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
     lazy var resolution = TSResolutionElementView(aiType: viewModel.selectedAiModelType)
     lazy var length = TSVideoLengthElementView(aiType: viewModel.selectedAiModelType)
     lazy var movement = TSMovementElementView(aiType: viewModel.selectedAiModelType)
+    lazy var aiVc : TSChatViewController = {
+        let vc = TSChatViewController()
+        vc.viewModel.uiStyle = .perfectHint
+        vc.textBlock = { [weak self] text, _ in
+            guard let self = self else { return }
+            promptTextView.setText(text: text)
+        }
+        return vc
+    }()
 
+    
     var viewModel: TSAIDiyVideoPTVViewModel = .init()
 
     override var videoGenerateModel: TSAIDiyVideoGenerateModel {
@@ -91,34 +99,39 @@ class TSAIDiyVideoPTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
     }
 
     func addActions() {
-        aiModelView.addTapAction { [weak self] in
-            guard let self = self else { return }
-            // 初始化内容控制器
-            let contentVC = TSDiyVideoPopoverViewController()
-            contentVC.currentType = self.viewModel.selectedAiModelType
-            contentVC.onSelected = { [weak self] type in
-                guard let self = self else { return }
-                viewModel.selectedAiModelType = type
-            }
-            // 设置模态呈现样式为Popover
-            contentVC.modalPresentationStyle = .popover
-
-            // 配置Popover属性
-            if let popoverPresentationController = contentVC.popoverPresentationController {
-                popoverPresentationController.delegate = self
-                popoverPresentationController.sourceView = self.aiModelView
-                popoverPresentationController.sourceRect = .init(origin: .init(x: self.aiModelView.bounds.origin.x, y: self.aiModelView.bounds.origin.y + 100), size: self.aiModelView.bounds.size)
-                popoverPresentationController.permittedArrowDirections = []
-                popoverPresentationController.backgroundColor = .fromHex("#222222")
-            }
-
-            // 呈现Popover
-            self.present(contentVC, animated: true, completion: nil)
-        }
+//        aiModelView.addTapAction { [weak self] in
+//            guard let self = self else { return }
+//            // 初始化内容控制器
+//            let contentVC = TSDiyVideoPopoverViewController()
+//            contentVC.currentType = self.viewModel.selectedAiModelType
+//            contentVC.onSelected = { [weak self] type in
+//                guard let self = self else { return }
+//                viewModel.selectedAiModelType = type
+//            }
+//            // 设置模态呈现样式为Popover
+//            contentVC.modalPresentationStyle = .popover
+//
+//            // 配置Popover属性
+//            if let popoverPresentationController = contentVC.popoverPresentationController {
+//                popoverPresentationController.delegate = self
+//                popoverPresentationController.sourceView = self.aiModelView
+//                popoverPresentationController.sourceRect = .init(origin: .init(x: self.aiModelView.bounds.origin.x, y: self.aiModelView.bounds.origin.y + 100), size: self.aiModelView.bounds.size)
+//                popoverPresentationController.permittedArrowDirections = []
+//                popoverPresentationController.backgroundColor = .fromHex("#222222")
+//            }
+//
+//            // 呈现Popover
+//            self.present(contentVC, animated: true, completion: nil)
+//        }
     }
 
     // 关键: 确保在iPhone上以Popover形式显示而非全屏
     func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
         return .none
     }
+    
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        self.promptTextView.customTextView.resignFirstResponder()
+    }
 }

+ 56 - 35
AIEmoji/Business2/DIYVideo/TSAIDiyVideoTTVVC/TSAIDiyVideoTTVVC.swift

@@ -9,7 +9,7 @@ class TSAIDiyVideoTTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
     lazy var aiModelView = TSAIModelElementView(frame: .zero)
 
     lazy var promptTextView: TSDiyTextPromptElementView = {
-        let promptTextView = TSDiyTextPromptElementView(randomTextArray: kRandomTextArray) { [weak self] _ in
+        let promptTextView = TSDiyTextPromptElementView(randomTextArray: kRandomImageToVideoArray) { [weak self] _ in
             guard let self = self else { return }
         }
         promptTextView.textChangedBlock = { [weak self] text in
@@ -20,26 +20,39 @@ class TSAIDiyVideoTTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
         promptTextView.sendBolck = { [weak self] text in
             guard let self = self else { return }
             self.viewModel.prompt = text
+            promptTextView.resignFirstResponder()
         }
         promptTextView.AIBolck = { [weak self] in
             guard let self = self else { return }
-            let vc = TSChatViewController()
-            vc.viewModel.uiStyle = .perfectHint
-
-            vc.textBlock = { [weak self] text, _ in
-                guard let self = self else { return }
-                promptTextView.setText(text: text)
-            }
-            kPushVC(target: self, modelVC: vc)
+//            let vc = TSChatViewController()
+//            vc.viewModel.uiStyle = .perfectHint
+//
+//            vc.textBlock = { [weak self] text, _ in
+//                guard let self = self else { return }
+//                promptTextView.setText(text: text)
+//            }
+//            kPushVC(target: self, modelVC: vc)
+            kPushVC(target: self, modelVC: aiVc)
         }
         return promptTextView
     }()
+    
+    lazy var aiVc : TSChatViewController = {
+        let vc = TSChatViewController()
+        vc.viewModel.uiStyle = .perfectHint
+        vc.textBlock = { [weak self] text, _ in
+            guard let self = self else { return }
+            promptTextView.setText(text: text)
+        }
+        return vc
+    }()
+
     lazy var style = TSDiyStyleElementView()
     lazy var resolution = TSResolutionElementView(aiType: viewModel.selectedAiModelType)
     lazy var length = TSVideoLengthElementView(aiType: viewModel.selectedAiModelType)
     lazy var movement = TSMovementElementView(aiType: viewModel.selectedAiModelType)
     lazy var aspectRadio = TSAspectRatioElementView(aiType: viewModel.selectedAiModelType)
-    
+
     var viewModel: TSAIDiyVideoTTVViewModel = .init()
 
     override var videoGenerateModel: TSAIDiyVideoGenerateModel {
@@ -62,7 +75,7 @@ class TSAIDiyVideoTTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
             resolution,
             length,
             movement,
-            aspectRadio
+            aspectRadio,
         ]
     }
 
@@ -72,6 +85,9 @@ class TSAIDiyVideoTTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
         addActions()
     }
 
+   
+    
+
     func addObservers() {
         viewModel.$selectedAiModelType.receive(on: DispatchQueue.main).sink { [weak self] type in
             self?.aiModelView.updateType(type: type)
@@ -81,34 +97,39 @@ class TSAIDiyVideoTTVVC: TSAIDiyVideoTTBaseVC, UIPopoverPresentationControllerDe
     }
 
     func addActions() {
-        aiModelView.addTapAction { [weak self] in
-            guard let self = self else { return }
-            // 初始化内容控制器
-            let contentVC = TSDiyVideoPopoverViewController()
-            contentVC.currentType = self.viewModel.selectedAiModelType
-            contentVC.onSelected = { [weak self] type in
-                guard let self = self else { return }
-                viewModel.selectedAiModelType = type
-            }
-            // 设置模态呈现样式为Popover
-            contentVC.modalPresentationStyle = .popover
-
-            // 配置Popover属性
-            if let popoverPresentationController = contentVC.popoverPresentationController {
-                popoverPresentationController.delegate = self
-                popoverPresentationController.sourceView = self.aiModelView
-                popoverPresentationController.sourceRect = .init(origin: .init(x: self.aiModelView.bounds.origin.x, y: self.aiModelView.bounds.origin.y + 100), size: self.aiModelView.bounds.size)
-                popoverPresentationController.permittedArrowDirections = []
-                popoverPresentationController.backgroundColor = .fromHex("#222222")
-            }
-
-            // 呈现Popover
-            self.present(contentVC, animated: true, completion: nil)
-        }
+//        aiModelView.addTapAction { [weak self] in
+//            guard let self = self else { return }
+//            // 初始化内容控制器
+//            let contentVC = TSDiyVideoPopoverViewController()
+//            contentVC.currentType = self.viewModel.selectedAiModelType
+//            contentVC.onSelected = { [weak self] type in
+//                guard let self = self else { return }
+//                viewModel.selectedAiModelType = type
+//            }
+//            // 设置模态呈现样式为Popover
+//            contentVC.modalPresentationStyle = .popover
+//
+//            // 配置Popover属性
+//            if let popoverPresentationController = contentVC.popoverPresentationController {
+//                popoverPresentationController.delegate = self
+//                popoverPresentationController.sourceView = self.aiModelView
+//                popoverPresentationController.sourceRect = .init(origin: .init(x: self.aiModelView.bounds.origin.x, y: self.aiModelView.bounds.origin.y + 100), size: self.aiModelView.bounds.size)
+//                popoverPresentationController.permittedArrowDirections = []
+//                popoverPresentationController.backgroundColor = .fromHex("#222222")
+//            }
+//
+//            // 呈现Popover
+//            self.present(contentVC, animated: true, completion: nil)
+//        }
     }
 
     // 关键: 确保在iPhone上以Popover形式显示而非全屏
     func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
         return .none
     }
+
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        promptTextView.customTextView.resignFirstResponder()
+    }
 }

+ 14 - 21
AIEmoji/Business2/DIYVideo/TSAIDiyVideoVC.swift

@@ -5,24 +5,22 @@
 //  Created by 100Years on 2025/7/28.
 //
 
+import IQKeyboardCore
 import JXSegmentedView
 
 let segmentedBgColor: UIColor = "#292929".uiColor
 
 class TSAIDiyVideoVC: TSBaseVC {
-    
-    var diyVideoType:Int = 0 //0 图生视频,1 文生视频
-    
-    
-    //选择生成的视频参数模型
-    var selectedGenerateModel:TSAIDiyVideoGenerateModel?{
-        
-        if let vc = viewControllers[segmentedView.selectedIndex] as? TSAIDiyVideoTTBaseVC{
+    var diyVideoType: Int = 0 // 0 图生视频,1 文生视频
+
+    // 选择生成的视频参数模型
+    var selectedGenerateModel: TSAIDiyVideoGenerateModel? {
+        if let vc = viewControllers[segmentedView.selectedIndex] as? TSAIDiyVideoTTBaseVC {
             return vc.videoGenerateModel
         }
         return nil
     }
-    
+
     lazy var listContainerView: JXSegmentedListContainerView = {
         let listContainerView = JXSegmentedListContainerView(dataSource: self)
         listContainerView.frame = CGRect(x: 0, y: 48, width: UIScreen.main.bounds.size.width, height: k_ScreenHeight - k_Nav_Height - 48)
@@ -36,7 +34,7 @@ class TSAIDiyVideoVC: TSBaseVC {
         dataSource.itemSpacing = 0
         dataSource.itemWidth = itemWidth
         dataSource.itemWidthIncrement = 0
-        dataSource.titles = ["Image to Video".localized,"Text to Video".localized]
+        dataSource.titles = ["Image to Video".localized, "Text to Video".localized]
         dataSource.titleNormalColor = .white.withAlphaComponent(0.8)
         dataSource.titleSelectedColor = "#111111".uiColor
         dataSource.titleNormalFont = .font(size: 12.0)
@@ -44,10 +42,10 @@ class TSAIDiyVideoVC: TSBaseVC {
         return dataSource
     }()
 
-    lazy var itemWidth:CGFloat = (UIScreen.main.bounds.size.width-32)/2.0
+    lazy var itemWidth: CGFloat = (UIScreen.main.bounds.size.width - 32) / 2.0
     lazy var indicator: JXSegmentedIndicatorBackgroundView = {
         let indicator = JXSegmentedIndicatorBackgroundView()
-        indicator.indicatorWidth = itemWidth-4
+        indicator.indicatorWidth = itemWidth - 4
         indicator.indicatorWidthIncrement = 0
         indicator.indicatorHeight = 36
         indicator.indicatorColor = .themeColor
@@ -57,13 +55,14 @@ class TSAIDiyVideoVC: TSBaseVC {
     }()
 
     lazy var segmentedView: JXSegmentedView = {
-        let segmentedView = JXSegmentedView(frame: CGRect(x: 16, y:8, width: UIScreen.main.bounds.size.width-32, height: 40.0))
+        let segmentedView = JXSegmentedView(frame: CGRect(x: 16, y: 8, width: UIScreen.main.bounds.size.width - 32, height: 40.0))
         segmentedView.delegate = self
         segmentedView.indicators = [indicator]
         segmentedView.dataSource = segmentedDataSource
         segmentedView.backgroundColor = segmentedBgColor
         segmentedView.listContainer = listContainerView
         segmentedView.cornerRadius = 20
+        segmentedView.defaultSelectedIndex = diyVideoType
         return segmentedView
     }()
 
@@ -99,12 +98,7 @@ class TSAIDiyVideoVC: TSBaseVC {
     init(diyVideoType: Int) {
         self.diyVideoType = diyVideoType
         super.init()
-       
-        DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
-            self.segmentedView.selectItemAt(index: diyVideoType)
-        }
     }
-    
 
     @MainActor required init?(coder: NSCoder) {
         fatalError("init(coder:) has not been implemented")
@@ -140,7 +134,7 @@ class TSAIDiyVideoVC: TSBaseVC {
                 creatBtnView.setBtnEnabled(isEnabled: finish)
             }
         }.store(in: &cancellable)
-        
+
         ttvVc.viewModel.$didFinishEdit.receive(on: DispatchQueue.main).sink { [weak self] finish in
             guard let self = self else {
                 return
@@ -165,7 +159,7 @@ extension TSAIDiyVideoVC: JXSegmentedViewDelegate {
     func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
         if segmentedView.selectedIndex == 0 {
             creatBtnView.setBtnEnabled(isEnabled: ptvVc.viewModel.didFinishEdit)
-        }else{
+        } else {
             creatBtnView.setBtnEnabled(isEnabled: ttvVc.viewModel.didFinishEdit)
         }
         navigationController?.interactivePopGestureRecognizer?.isEnabled = (index == 0)
@@ -197,7 +191,6 @@ extension TSAIDiyVideoVC {
 
             kPresentModalVC(target: self, modelVC: gennerateVC, transitionStyle: .crossDissolve)
         } else {
-            
             let generatorModel = TSAIGeneratorModel(upLoadImage: .init(), generatorStyle: .textToVideo)
             generatorModel.diyVideoGenerateModel = selectedGenerateModel
             let gennerateVC = TSAIGenerateVC(generatorModel: generatorModel) { [weak self] _ in

+ 1 - 1
AIEmoji/Business2/DIYVideo/ViewModel/TSAIDiyVideoTTBaseViewModel.swift

@@ -16,7 +16,7 @@ class TSAIDiyVideoPTVViewModel {
     
     
     func judgeWasFinishedEdit() {
-        didFinishEdit = uploadImage != nil
+        didFinishEdit = (uploadImage != nil && !prompt.isEmpty)
     }
     
    

+ 4 - 3
AIEmoji/Business2/DisCover/Data/TSDiscoverViewModel+Data.swift

@@ -14,15 +14,16 @@ class TSDiscoverViewModel {
     
     lazy var bannerItems: [TSDiscoverItemModel] = {
         return [
-            TSDiscoverItemModel(style: .ptp,
-                                viewModel: TSDiscoverBaseItemVM(title: "", imageNamed:"discover_0_AnimeBanner"),
-                                generateModel: TSGenerateModel(json: ptp_Anime)),
+           
             TSDiscoverItemModel(style: .videoV2,
                                 viewModel: TSDiscoverAnimationItemVM(title: "", style: .video, imageNameds: ["Animal Diving Show.mp4"]),
                                 generateModel: TSGenerateModel(json: video_AnimalDivingShow)),
             TSDiscoverItemModel(style: .videoV2,
                                 viewModel: TSDiscoverAnimationItemVM(title: "", style: .video, imageNameds: ["Oscar Gala.mp4"]),
                                 generateModel: TSGenerateModel(json: video_OscarGala)),
+            TSDiscoverItemModel(style: .ptp,
+                                viewModel: TSDiscoverBaseItemVM(title: "", imageNamed:"discover_0_AnimeBanner"),
+                                generateModel: TSGenerateModel(json: ptp_Anime)),
         ]
     }()
     

+ 8 - 1
AIEmoji/Business2/DisCover/TSAIGenerateVC/TSAIGenerateVC.swift

@@ -29,10 +29,17 @@ class TSAIGenerateVC: TSAIGenerateBaseVC {
     lazy var generateInView: TSGeneratorView = {
         let generateInView = TSGeneratorView()
 //        if generatorModel.advance {
-        generateInView.animationView.setText(time: String(format: "~ %d min".localized, 2), info: "Lots of people are creating images right now, so this might take a bit.".localized)
+//        generateInView.animationView.setText(time: String(format: "~ %d min".localized, 2), info: "Lots of people are creating images right now, so this might take a bit.".localized)
 //        }else{
 //            generateInView.animationView.setText(time: String(format: "~ %d seconds".localized, 20), info: "")
 //        }
+        
+        let videoCategorys : [TSFuncStyle] = [.photoLive,.videoV2,.textToVideo,.pictureToVideo]
+        if videoCategorys.contains(generatorModel.generatorStyle) {
+            generateInView.animationView.setText(time: String(format: "~ %d min".localized, 2), info: "Lots of people are creating videos right now, so this might take a bit.".localized)
+        }else{
+            generateInView.animationView.setText(time: String(format: "~ %d min".localized, 2), info: "Lots of people are creating images right now, so this might take a bit.".localized)
+        }
 
         generateInView.clickBackstageBlock = { [weak self] in
             guard let self = self else { return }

+ 3 - 3
AIEmoji/Business2/DisCover/TSDiscoverVC/Cell/TSDiscoverBannerCell.swift

@@ -71,7 +71,7 @@ class TSDiscoverBannerCell: TSDiscoverBaseCell {
     lazy var imageToVideoView: TSDiscoverBannerItemCell = {
         let view = TSDiscoverBannerItemCell()
         view.cornerRadius = 12
-        view.backgroundColor = "#01396C".uiColor
+        view.backgroundColor = "#2B2937".uiColor
         view.addTapAction { [weak self] in
             guard let self = self else { return }
             clickSpecialBlock?("ptv", nil)
@@ -82,7 +82,7 @@ class TSDiscoverBannerCell: TSDiscoverBaseCell {
     lazy var textToVideoView: TSDiscoverBannerItemCell = {
         let view = TSDiscoverBannerItemCell()
         view.cornerRadius = 12
-        view.backgroundColor = "#01396C".uiColor
+        view.backgroundColor = "#2B2937".uiColor
         view.titleLabel.text = "Text to Video".localized
         view.iconView.image = .icText2Video
 
@@ -257,7 +257,7 @@ class TSDiscoverBannerViewImageCell: TSBaseCollectionCell {
         textLabel.snp.makeConstraints { make in
             make.leading.equalTo(16)
             make.trailing.equalTo(-111)
-            make.bottom.equalTo(-58)
+            make.bottom.equalTo(-78)
             make.height.equalTo(52)
         }
 

+ 7 - 2
AIEmoji/Business2/DisCover/TSPTPUploadImageVC/View/TSUploadImageView.swift

@@ -122,20 +122,25 @@ class TSUploadImageView: TSBaseView {
     
     override func creatUI() {
         contentView.addSubview(uploadImageBgView)
+        contentView.addSubview(deleteBtn)
+        uploadImageBgView.addSubview(uploadVideoView)
+        makeConstraints()
+    }
+    
+    func makeConstraints(){
+        
         uploadImageBgView.snp.makeConstraints { make in
             make.width.equalTo(280*kDesignScale)
             make.height.equalTo(280*kDesignScale)
             make.centerX.equalToSuperview()
         }
         
-        contentView.addSubview(deleteBtn)
         deleteBtn.snp.makeConstraints { make in
             make.top.equalTo(0)
             make.trailing.equalTo(-32*kDesignScale)
             make.width.height.equalTo(32)
         }
         
-        uploadImageBgView.addSubview(uploadVideoView)
         uploadVideoView.snp.makeConstraints { make in
             make.edges.equalToSuperview()
         }

+ 4 - 1
AIEmoji/de.lproj/Localizable.strings

@@ -343,7 +343,7 @@
 "Magazine" = "Zeitschrift";
 "Religious Medieval" = "Religiöses Mittelalter";
 "Tattoo" = "Tätowierung";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "Hallo! Ich bin DeepSeek, bereit, dir zu helfen, deine Bildideen zu bereichern.";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "Hallo! Ich bin DeepSeek und helfe Ihnen gerne, Ihre Ideen zu bereichern.";
 "Select pet photos with clear faces" = "Wählen Sie Haustierfotos mit klaren Gesichtern";
 "No clear faces or group shots" = "Keine klaren Gesichter oder Gruppenfotos";
 "Text" = "Text";
@@ -393,6 +393,7 @@
 "Anime" = "Anime";
 "Chibi Sticker" = "Aufkleber";
 "Lots of people are creating images right now, so this might take a bit." = "Viele Leute erstellen gerade Bilder, es könnte etwas dauern.";
+"Lots of people are creating videos right now, so this might take a bit." = "Viele Leute erstellen gerade Videos, daher kann dies etwas dauern.";
 "Upgrade Yearly Pro" = "Upgrade Jährlich Pro";
 "Congratulations on being VIP of the Year!" = "Herzlichen Glückwunsch zum VIP des Jahres!";
 "Upgrade to PRO" = "Upgrade auf PRO";
@@ -553,3 +554,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "Das Seitenverhältnis muss zwischen 1:2 und 1:1,2 liegen";
 "Front view, clear face, upper/full body" = "Vorderansicht, klares Gesicht, Oberkörper/Ganzkörper";
 "Invalid photo size, covered face, not a single person" = "Ungültige Fotogröße, verdecktes Gesicht, keine einzelne Person";
+
+"%d Video Effects & Video Generations" = "%d Videoeffekte und Videogenerationen";

+ 4 - 1
AIEmoji/en.lproj/Localizable.strings

@@ -340,7 +340,7 @@
 "Magazine" = "Magazine";
 "Religious Medieval" = "Religious Medieval";
 "Tattoo" = "Tattoo";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "Hello! I'm DeepSeek, ready to help you enrich your picture ideas.";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "Hello! I'm DeepSeek, ready to help you enrich your ideas.";
 "Select pet photos with clear faces" = "Select pet photos with clear faces";
 "No clear faces or group shots" = "No clear faces or group shots";
 "Text" = "Text";
@@ -390,6 +390,7 @@
 "Anime" = "Anime";
 "Chibi Sticker" = "Chibi Sticker";
 "Lots of people are creating images right now, so this might take a bit." = "Lots of people are creating images right now, so this might take a bit.";
+"Lots of people are creating videos right now, so this might take a bit." = "Lots of people are creating videos right now, so this might take a bit.";
 "Upgrade Yearly Pro" = "Upgrade Yearly Pro";
 "Congratulations on being VIP of the Year!" = "Congratulations on being VIP of the Year!";
 "Upgrade to PRO" = "Upgrade to PRO";
@@ -552,3 +553,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "Aspect ratio must be between 1:2 to 1:1.2";
 "Front view, clear face, upper/full body" = "Front view, clear face, upper/full body";
 "Invalid photo size, covered face, not a single person" = "Invalid photo size, covered face, not a single person";
+
+"%d Video Effects & Video Generations" = "%d Video Effects & Video Generations";

+ 4 - 1
AIEmoji/es.lproj/Localizable.strings

@@ -340,7 +340,7 @@
 "Magazine" = "Revista";
 "Religious Medieval" = "Religioso Medieval";
 "Tattoo" = "Tatuaje";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "¡Hola! Soy DeepSeek, listo para ayudarte a enriquecer tus ideas para fotos.";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "¡Hola! Soy DeepSeek y estoy listo para ayudarte a enriquecer tus ideas.";
 "Select pet photos with clear faces" = "Selecciona fotos de mascotas con caras claras";
 "No clear faces or group shots" = "Sin caras claras o fotos de grupo";
 "Text" = "Texto";
@@ -390,6 +390,7 @@
 "Anime" = "Anime";
 "Chibi Sticker" = "Pegatina";
 "Lots of people are creating images right now, so this might take a bit." = "Mucha gente está creando imágenes ahora, puede tardar un poco.";
+"Lots of people are creating videos right now, so this might take a bit." = "Mucha gente está creando vídeos en estos momentos, por lo que esto podría llevar un tiempo.";
 "Upgrade Yearly Pro" = "Actualizar Yearly Pro";
 "Congratulations on being VIP of the Year!" = "¡Felicitaciones por ser VIP del año!";
 "Upgrade to PRO" = "Actualízate a PRO";
@@ -551,3 +552,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "La relación de aspecto debe estar entre 1:2 y 1:1,2";
 "Front view, clear face, upper/full body" = "Vista frontal, cara despejada, parte superior/cuerpo completo";
 "Invalid photo size, covered face, not a single person" = "Tamaño de foto no válido, cara cubierta, ni una sola persona";
+
+"%d Video Effects & Video Generations" = "%d Efectos de vídeo y generaciones de vídeo";

+ 4 - 1
AIEmoji/ja.lproj/Localizable.strings

@@ -340,7 +340,7 @@
 "Magazine" = "雑誌";
 "Religious Medieval" = "中世宗教";
 "Tattoo" = "タトゥー";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "こんにちは! DeepSeekです。あなたの写真のアイデアを豊かにするお手伝いをします。";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "こんにちは!DeepSeekです。あなたのアイデアを豊かにするお手伝いをさせていただきます。";
 "Select pet photos with clear faces" = "顔がはっきりしたペットの写真を選ぶ";
 "No clear faces or group shots" = "はっきりとした顔や集合写真はありません";
 "Text" = "テキスト";
@@ -390,6 +390,7 @@
 "Anime" = "アニメ";
 "Chibi Sticker" = "ステッカー";
 "Lots of people are creating images right now, so this might take a bit." = "現在多くの人が画像生成中ですので、少し時間がかかる場合があります。";
+"Lots of people are creating videos right now, so this might take a bit." = "現在、多くの人がビデオを作成しているので、少し時間がかかるかもしれません。";
 "Upgrade Yearly Pro" = "年会費アップグレード";
 "Congratulations on being VIP of the Year!" = "VIP オブ ザ イヤー受賞おめでとうございます!";
 "Upgrade to PRO" = "PRO にアップグレード";
@@ -550,3 +551,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "アスペクト比は1:2~1:1.2の範囲でなければなりません";
 "Front view, clear face, upper/full body" = "正面、顔がはっきり、上半身/全身";
 "Invalid photo size, covered face, not a single person" = "写真のサイズが無効、顔が隠れている、人物が写っていない";
+
+"%d Video Effects & Video Generations" = "%d 個のビデオ効果とビデオ生成";

+ 4 - 1
AIEmoji/ko.lproj/Localizable.strings

@@ -345,7 +345,7 @@
 "Magazine" = "잡지";
 "Religious Medieval" = "종교 중세";
 "Tattoo" = "문신";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "안녕하세요! 여러분의 사진 아이디어를 더욱 풍성하게 만들어드릴 준비가 된 딥시크릿입니다.";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "안녕하세요! 저는 DeepSeek입니다. 여러분의 아이디어를 더욱 풍성하게 만들어 드릴 준비가 되었습니다..";
 "Select pet photos with clear faces" = "얼굴이 선명한 반려동물 사진 선택";
 "No clear faces or group shots" = "얼굴이 선명하지 않거나 단체 사진";
 "Text" = "텍스트";
@@ -395,6 +395,7 @@
 "Anime" = "애니메이션";
 "Chibi Sticker" = "스티커";
 "Lots of people are creating images right now, so this might take a bit." = "현재 많은 사람들이 이미지를 생성 중이라 시간이 조금 걸릴 수 있습니다.";
+"Lots of people are creating videos right now, so this might take a bit." = "지금 많은 사람들이 영상을 만들고 있어서 시간이 좀 걸릴 수 있습니다.";
 "Upgrade Yearly Pro" = "연간 프로 업그레이드";
 "Congratulations on being VIP of the Year!" = "올해의 VIP가 되신 것을 축하드립니다!";
 "Upgrade to PRO" = "PRO로 업그레이드";
@@ -554,3 +555,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "화면비는 1:2~1:1.2 사이여야 합니다.";
 "Front view, clear face, upper/full body" = "정면도, 깨끗한 얼굴, 상체/전신";
 "Invalid photo size, covered face, not a single person" = "잘못된 사진 크기, 얼굴 가려짐, 사람 한 명 없음";
+
+"%d Video Effects & Video Generations" = "%d 비디오 효과 및 비디오 생성";

+ 4 - 1
AIEmoji/pt-BR.lproj/Localizable.strings

@@ -340,7 +340,7 @@
 "Magazine" = "Revista";
 "Religious Medieval" = "Religioso Medieval";
 "Tattoo" = "Tatuagem";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "Olá! Eu sou o DeepSeek, pronto para ajudá-lo a enriquecer suas ideias de fotos.";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "Olá! Sou o DeepSeek e estou pronto para ajudar você a enriquecer suas ideias.";
 "Select pet photos with clear faces" = "Selecione fotos de animais de estimação com rostos nítidos";
 "No clear faces or group shots" = "Sem rostos nítidos ou fotos de grupo";
 "Text" = "Texto";
@@ -390,6 +390,7 @@
 "Anime" = "Anime";
 "Chibi Sticker" = "Adesivo";
 "Lots of people are creating images right now, so this might take a bit." = "Muita gente criando imagens agora, pode demorar um pouco.";
+"Lots of people are creating videos right now, so this might take a bit." = "Muitas pessoas estão criando vídeos agora, então isso pode demorar um pouco.";
 "Upgrade Yearly Pro" = "Atualização Pro Anual";
 "Congratulations on being VIP of the Year!" = "Parabéns por ser VIP do Ano!";
 "Upgrade to PRO" = "Atualize para PRO";
@@ -550,3 +551,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "A proporção da tela deve estar entre 1:2 e 1:1,2";
 "Front view, clear face, upper/full body" = "Vista frontal, rosto limpo, corpo superior/inteiro";
 "Invalid photo size, covered face, not a single person" = "Tamanho de foto inválido, rosto coberto, nenhuma pessoa";
+
+"%d Video Effects & Video Generations" = "%d Efeitos de Vídeo e Gerações de Vídeo";

+ 4 - 1
AIEmoji/pt-PT.lproj/Localizable.strings

@@ -340,7 +340,7 @@
 "Magazine" = "Revista";
 "Religious Medieval" = "Religioso Medieval";
 "Tattoo" = "Tatuagem";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "Olá! Eu sou o DeepSeek, pronto para ajudá-lo a enriquecer suas ideias de fotos.";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "Olá! Sou o DeepSeek e estou pronto para ajudar você a enriquecer suas ideias.";
 "Select pet photos with clear faces" = "Selecione fotos de animais de estimação com rostos nítidos";
 "No clear faces or group shots" = "Sem rostos nítidos ou fotos de grupo";
 "Text" = "Texto";
@@ -390,6 +390,7 @@
 "Anime" = "Anime";
 "Chibi Sticker" = "Adesivo";
 "Lots of people are creating images right now, so this might take a bit." = "Muita gente criando imagens agora, pode demorar um pouco.";
+"Lots of people are creating videos right now, so this might take a bit." = "Muitas pessoas estão criando vídeos agora, então isso pode demorar um pouco.";
 "Upgrade Yearly Pro" = "Atualização Pro Anual";
 "Congratulations on being VIP of the Year!" = "Parabéns por ser VIP do Ano!";
 "Upgrade to PRO" = "Atualize para PRO";
@@ -549,3 +550,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "A proporção da tela deve estar entre 1:2 e 1:1,2";
 "Front view, clear face, upper/full body" = "Vista frontal, rosto limpo, corpo superior/inteiro";
 "Invalid photo size, covered face, not a single person" = "Tamanho de foto inválido, rosto coberto, nenhuma pessoa";
+
+"%d Video Effects & Video Generations" = "%d Efeitos de Vídeo e Gerações de Vídeo";

+ 4 - 1
AIEmoji/zh-Hans.lproj/Localizable.strings

@@ -341,7 +341,7 @@
 "Magazine" = "杂志";
 "Religious Medieval" = "中世纪宗教";
 "Tattoo" = "纹身";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "你好!我是 DeepSeek,随时帮你丰富你的图片创意。";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "你好!我是 DeepSeek,随时准备帮助你丰富你的想法。";
 "Select pet photos with clear faces" = "选择有清晰面部的宠物照片";
 "No clear faces or group shots" = "没有清晰的面部或集体照";
 "Text" = "文生图";
@@ -391,6 +391,7 @@
 "Anime" = "动漫";
 "Chibi Sticker" = "Q版贴纸";
 "Lots of people are creating images right now, so this might take a bit." = "现在很多人都正在生成图像,所以可能需要一点时间。";
+"Lots of people are creating videos right now, so this might take a bit." = "很多人都正在制作视频,所以这可能需要一点时间。";
 "Upgrade Yearly Pro" = "升级年度会员";
 "Congratulations on being VIP of the Year!" = "恭喜你成为年度 VIP!";
 "Upgrade to PRO" = "升级成为会员";
@@ -551,3 +552,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "长宽比必须介于 1:2 到 1:1.2 之间";
 "Front view, clear face, upper/full body" = "正面图、清晰的脸部、上半身/全身";
 "Invalid photo size, covered face, not a single person" = "照片尺寸无效,脸部被遮住,不是单人照片";
+
+"%d Video Effects & Video Generations" = "%d 视频特效和视频生成";

+ 4 - 1
AIEmoji/zh-Hant.lproj/Localizable.strings

@@ -330,7 +330,7 @@
 "Magazine" = "雜誌";
 "Religious Medieval" = "中世紀宗教";
 "Tattoo" = "紋身";
-"Hello! I'm DeepSeek, ready to help you enrich your picture ideas." = "你好! 我是DeepSeek,隨時幫你豐富你的圖片創意。";
+"Hello! I'm DeepSeek, ready to help you enrich your ideas." = "你好!我是 DeepSeek,隨時準備幫助你豐富你的想法";
 "Select pet photos with clear faces" = "選擇有清晰面部的寵物照片";
 "No clear faces or group shots" = "沒有清晰的面部或集體照";
 "Text" = "文生圖";
@@ -380,6 +380,7 @@
 "Anime" = "動漫";
 "Chibi Sticker" = "Q版貼紙";
 "Lots of people are creating images right now, so this might take a bit." = "現在很多人都正在生成影像,所以可能需要一點時間。";
+"Lots of people are creating videos right now, so this might take a bit." = "很多人都正在製作視頻,所以這可能需要一點時間。";
 "Upgrade Yearly Pro" = "升級年度會員";
 "Congratulations on being VIP of the Year!" = "恭喜你成為年度 VIP!";
 "Upgrade to PRO" = "陞級成為會員";
@@ -540,3 +541,5 @@
 "Aspect ratio must be between 1:2 to 1:1.2" = "長寬比必須介於 1:2 到 1:1.2 之間";
 "Front view, clear face, upper/full body" = "正面圖、清晰的臉部、上半身/全身";
 "Invalid photo size, covered face, not a single person" = "照片尺寸無效,臉部被遮住,不是單人照片";
+
+"%d Video Effects & Video Generations" = "%d視頻特效和視頻生成";