|
@@ -0,0 +1,410 @@
|
|
|
|
+//
|
|
|
|
+// TSAIPhotoGeneratorVC.swift
|
|
|
|
+// TSLiveWallpaper
|
|
|
|
+//
|
|
|
|
+// Created by 100Years on 2025/6/11.
|
|
|
|
+//
|
|
|
|
+
|
|
|
|
+import Kingfisher
|
|
|
|
+struct TSAIListPhotoGeneratorModel {
|
|
|
|
+ var upLoadImage:UIImage
|
|
|
|
+ var generatorStyle:TSGeneratorImageStyle
|
|
|
|
+ var expandEdge:UIEdgeInsets
|
|
|
|
+ var expandViewSizes:(CGSize,CGSize)?
|
|
|
|
+ var additionalPrompt:String//追加的提示词
|
|
|
|
+
|
|
|
|
+ //预测宝宝
|
|
|
|
+ var upLoadImages:[UIImage]?
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ init(upLoadImage: UIImage,
|
|
|
|
+ generatorStyle: TSGeneratorImageStyle,
|
|
|
|
+ expandEdge:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0),
|
|
|
|
+ expandViewSizes:(CGSize,CGSize)? = nil,
|
|
|
|
+ additionalPrompt:String = "",
|
|
|
|
+ upLoadImages:[UIImage]? = nil
|
|
|
|
+ ) {
|
|
|
|
+ self.upLoadImage = upLoadImage
|
|
|
|
+ self.generatorStyle = generatorStyle
|
|
|
|
+ self.expandEdge = expandEdge
|
|
|
|
+ self.expandViewSizes = expandViewSizes
|
|
|
|
+ self.additionalPrompt = additionalPrompt
|
|
|
|
+ self.upLoadImages = upLoadImages
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class TSAIListPhotoGeneratorVC: TSBaseVC {
|
|
|
|
+
|
|
|
|
+ init(generatorModel:TSAIListPhotoGeneratorModel,complete:@escaping ((TSActionInfoModel)->Void)) {
|
|
|
|
+ self.complete = complete
|
|
|
|
+ self.viewModel = TSAIListPhotoGeneratorBaseVM(generatorModel: generatorModel)
|
|
|
|
+ super.init()
|
|
|
|
+ }
|
|
|
|
+ @MainActor required init?(coder: NSCoder) {
|
|
|
|
+ fatalError("init(coder:) has not been implemented")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var imageModel:TSActionInfoModel?
|
|
|
|
+ var complete:((TSActionInfoModel)->Void)
|
|
|
|
+ var progressState = TSProgressState.none
|
|
|
|
+
|
|
|
|
+ var isSavePhotoMark:Bool = false
|
|
|
|
+ var isNeedSavePhoto:Bool {
|
|
|
|
+ if isSavePhotoMark == false,let _ = imageModel {
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var viewModel: TSAIListPhotoGeneratorBaseVM!
|
|
|
|
+// var videoPlayerVC: TSAIListVideoPlayerVC = TSAIListVideoPlayerVC(videoURL: URL(string: "www.baidu.com")!)
|
|
|
|
+ lazy var bottomViewH = 60+k_Height_safeAreaInsetsBottom()
|
|
|
|
+ lazy var netWorkImageView: UIImageView = {
|
|
|
|
+ let netWorkImageView = UIImageView(frame: CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight-bottomViewH))
|
|
|
|
+ netWorkImageView.backgroundColor = "#111111".uiColor
|
|
|
|
+ netWorkImageView.contentMode = .scaleAspectFit
|
|
|
|
+ netWorkImageView.isUserInteractionEnabled = true
|
|
|
|
+ return netWorkImageView
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ lazy var generateInView : TSGeneratorView = {
|
|
|
|
+ let generateInView = TSGeneratorView()
|
|
|
|
+ generateInView.isUploadImage = false
|
|
|
|
+ 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.clickErrorBlock = { [weak self] style in
|
|
|
|
+ guard let self = self else { return }
|
|
|
|
+
|
|
|
|
+ switch style {
|
|
|
|
+ case .netWorkError:
|
|
|
|
+ clickRegenerateBtn()
|
|
|
|
+ default:
|
|
|
|
+ self.dismiss(animated: false, completion: nil)
|
|
|
|
+ break
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ return generateInView
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ lazy var expandAreaView: TSAIExpandChangeView = {
|
|
|
|
+ let view = TSAIExpandChangeView()
|
|
|
|
+ return view
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ lazy var switchOriginalPictureBtn: TSUIExpandedTouchButton = {
|
|
|
|
+ let switchOriginalPictureBtn = TSUIExpandedTouchButton()
|
|
|
|
+ switchOriginalPictureBtn.setUpButton(image:UIImage(named: "switch_original_picture"))
|
|
|
|
+ switchOriginalPictureBtn.addTarget(self, action: #selector(switchOriginalPictureTouchDown), for: .touchDown)
|
|
|
|
+ switchOriginalPictureBtn.addTarget(self, action: #selector(switchOriginalPictureTouchUp), for: [.touchUpInside, .touchUpOutside, .touchCancel])
|
|
|
|
+ switchOriginalPictureBtn.isHidden = true
|
|
|
|
+ return switchOriginalPictureBtn
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+// lazy var rotatingPictureBtn: TSUIExpandedTouchButton = {
|
|
|
|
+// let rotatingPictureBtn = TSUIExpandedTouchButton()
|
|
|
|
+// rotatingPictureBtn.setUpButton(image:UIImage(named: "rotating_picture")){ [weak self] in
|
|
|
|
+// guard let self = self else { return }
|
|
|
|
+// //旋转图片并储存
|
|
|
|
+// if let image = netWorkImageView.image?.rotated(by: .degrees90) {
|
|
|
|
+// netWorkImageView.image = image
|
|
|
|
+// if let resultUrl = self.imageModel?.response.resultUrl,
|
|
|
|
+// let url = URL(string: resultUrl){
|
|
|
|
+// ImageCache.default.store(image, forKey: url.cacheKey)
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// rotatingPictureBtn.isHidden = true
|
|
|
|
+// return rotatingPictureBtn
|
|
|
|
+// }()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ lazy var saveBtn: UIButton = {
|
|
|
|
+ let saveBtn = kCreateNormalSubmitBtn(title: "Save".localized) { [weak self] in
|
|
|
|
+ guard let self = self else { return }
|
|
|
|
+ clickSaveBtn()
|
|
|
|
+ }
|
|
|
|
+ return saveBtn
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ override func createView() {
|
|
|
|
+
|
|
|
|
+ contentView.addSubview(generateInView)
|
|
|
|
+ generateInView.snp.makeConstraints { make in
|
|
|
|
+ make.edges.equalToSuperview()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ super.createView()
|
|
|
|
+
|
|
|
|
+ contentView.addSubview(switchOriginalPictureBtn)
|
|
|
|
+ switchOriginalPictureBtn.snp.makeConstraints { make in
|
|
|
|
+ make.bottom.equalTo(-k_Height_safeAreaInsetsBottom() - 76)
|
|
|
|
+ make.trailing.equalTo(-16)
|
|
|
|
+ make.width.equalTo(40)
|
|
|
|
+ make.height.equalTo(40)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// contentView.addSubview(rotatingPictureBtn)
|
|
|
|
+// rotatingPictureBtn.snp.makeConstraints { make in
|
|
|
|
+// make.bottom.equalTo(-k_Height_safeAreaInsetsBottom() - 76)
|
|
|
|
+// make.trailing.equalTo(-16)
|
|
|
|
+// make.width.equalTo(40)
|
|
|
|
+// make.height.equalTo(40)
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ saveBtn.setTitleImageSpace(spacing: 0)
|
|
|
|
+
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoExpand {
|
|
|
|
+// setUpExpandAreaView()
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// func setUpExpandAreaView(){
|
|
|
|
+// netWorkImageView.addSubview(expandAreaView)
|
|
|
|
+// expandAreaView.snp.makeConstraints { make in
|
|
|
|
+// make.top.leading.trailing.bottom.equalTo(0)
|
|
|
|
+// }
|
|
|
|
+//
|
|
|
|
+// expandAreaView.showImageView.isHidden = true
|
|
|
|
+// expandAreaView.boardView.isHidden = true
|
|
|
|
+//
|
|
|
|
+// if let sizes = self.viewModel.generatorModel.expandViewSizes {
|
|
|
|
+// expandAreaView.updateExpandAreaView(width: sizes.0.width, height: sizes.0.height)
|
|
|
|
+// expandAreaView.updateImageView(width: sizes.1.width, height: sizes.1.height)
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ func closePage() {
|
|
|
|
+
|
|
|
|
+ if progressState.isResult {
|
|
|
|
+ if isNeedSavePhoto{
|
|
|
|
+ TSCustomAlertController.show(in: self, config: TSCustomAlertController.AlertConfig(
|
|
|
|
+ message: "You haven't saved the photo yet. Are you sure to quit?".localized,
|
|
|
|
+ messageColor: .white,
|
|
|
|
+ messageFont: .systemFont(ofSize: 16),
|
|
|
|
+
|
|
|
|
+ cancelTitle: "Quit".localized,
|
|
|
|
+ cancelColor: .white,
|
|
|
|
+
|
|
|
|
+ confirmTitle: "Save".localized,
|
|
|
|
+ confirmColor: .themeColor,
|
|
|
|
+
|
|
|
|
+ cancelAction: { [weak self] in
|
|
|
|
+ guard let self = self else { return }
|
|
|
|
+ print("用户点击了Leave")
|
|
|
|
+ viewModel.cancelAllRequest()
|
|
|
|
+ self.dismiss(animated: true, completion: nil)
|
|
|
|
+ },
|
|
|
|
+ confirmAction: { [weak self] in
|
|
|
|
+ guard let self = self else { return }
|
|
|
|
+ print("用户点击了Stay")
|
|
|
|
+ clickSaveBtn()
|
|
|
|
+ }
|
|
|
|
+ ))
|
|
|
|
+ }else{
|
|
|
|
+ viewModel.cancelAllRequest()
|
|
|
|
+ self.dismiss(animated: true, completion: nil)
|
|
|
|
+ }
|
|
|
|
+ }else{
|
|
|
|
+ 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")
|
|
|
|
+ }
|
|
|
|
+ ))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //重新生成
|
|
|
|
+ @objc func clickRegenerateBtn(){
|
|
|
|
+ //判断 vip
|
|
|
|
+ if kJudgeVip(externalBool: kPurchaseBusiness.isVip , vc: self){ return }
|
|
|
|
+
|
|
|
|
+ viewModel.uploadAndCreatImage()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //保存功能
|
|
|
|
+ @objc func clickSaveBtn(){
|
|
|
|
+ guard let imageModel = imageModel else { return }
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoLive{
|
|
|
|
+// TSDownloadManager.getDownLoadVideo(urlString: imageModel.response.resultUrl) { url, success in
|
|
|
|
+// if let url = url {
|
|
|
|
+// PhotoManagerShared.saveVideoToAlbum(videoURL: url) { [weak self] success, error in
|
|
|
|
+// guard let self = self else { return }
|
|
|
|
+// if success {
|
|
|
|
+// isSavePhotoMark = true
|
|
|
|
+// kSaveSuccesswShared.show(atView:self.view)
|
|
|
|
+// }else{
|
|
|
|
+// debugPrint(error)
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// }else{
|
|
|
|
+ UIImageView.downloadImageWithProgress(urlString: imageModel.response.resultUrl) { image in
|
|
|
|
+ if let image = image {
|
|
|
|
+ PhotoManagerShared.saveImageToAlbum(image) { [weak self] success, error in
|
|
|
|
+ guard let self = self else { return }
|
|
|
|
+ if success {
|
|
|
|
+ isSavePhotoMark = true
|
|
|
|
+ kSaveSuccesswShared.show(atView:self.view)
|
|
|
|
+ }else{
|
|
|
|
+ debugPrint(error)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ override func dealThings() {
|
|
|
|
+ viewModel.uploadAndCreatImage()
|
|
|
|
+ viewModel.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self] (state,model) in
|
|
|
|
+ guard let self = self else { return }
|
|
|
|
+ self.upDateView(state: state, model: model)
|
|
|
|
+ }.store(in: &cancellable)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+extension TSAIListPhotoGeneratorVC {
|
|
|
|
+
|
|
|
|
+ func getSuccessImage()->UIImage?{
|
|
|
|
+ if let image = netWorkImageView.image {
|
|
|
|
+ return image.pngImage
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+extension TSAIListPhotoGeneratorVC {
|
|
|
|
+
|
|
|
|
+ func upDateView(state:TSProgressState,model:TSActionInfoModel?){
|
|
|
|
+ progressState = state
|
|
|
|
+ switch state {
|
|
|
|
+ case .failed(let errorStr,let code):
|
|
|
|
+ showError(text: errorStr,code:code)
|
|
|
|
+ case .success:
|
|
|
|
+ if let model = model {
|
|
|
|
+ showSuccess(model: model)
|
|
|
|
+ }else{
|
|
|
|
+ showError(text: "")
|
|
|
|
+ }
|
|
|
|
+ case .progressString(let string):
|
|
|
|
+ showProgress(text: string)
|
|
|
|
+ default:
|
|
|
|
+ showLoading()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ func showProgress(text:String) {
|
|
|
|
+ generateInView.updateShowProgress(text: text)
|
|
|
|
+
|
|
|
|
+ netWorkImageView.isHidden = true
|
|
|
|
+ switchOriginalPictureBtn.isHidden = true
|
|
|
|
+
|
|
|
|
+ setVideoHidden()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ func showLoading(){
|
|
|
|
+ generateInView.updateShowLoading(text: "Generating".localized + " ...".localized)
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ func showError(text:String,code:Int = 0){
|
|
|
|
+ generateInView.updateShowError(text: text,code: code)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ func showSuccess(model:TSActionInfoModel){
|
|
|
|
+ generateInView.updateShowSuccess()
|
|
|
|
+
|
|
|
|
+ imageModel = model
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ netWorkImageView.isHidden = false
|
|
|
|
+
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .futureBaby {
|
|
|
|
+// rotatingPictureBtn.isHidden = false
|
|
|
|
+// }else{
|
|
|
|
+ switchOriginalPictureBtn.isHidden = false
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+ isSavePhotoMark = false
|
|
|
|
+ self.netWorkImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!)
|
|
|
|
+
|
|
|
|
+ if let model = imageModel {
|
|
|
|
+ complete(model)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+// setVideoURL()
|
|
|
|
+ setExpandAreaImage()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @objc func switchOriginalPictureTouchDown() {
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoExpand {
|
|
|
|
+// expandAreaView.onlyBgImage(only: false)
|
|
|
|
+// }else{
|
|
|
|
+ self.netWorkImageView.image = self.viewModel.generatorModel.upLoadImage
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @objc func switchOriginalPictureTouchUp() {
|
|
|
|
+ guard let imageModel = imageModel else { return }
|
|
|
|
+
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoExpand {
|
|
|
|
+// expandAreaView.onlyBgImage(only: true)
|
|
|
|
+// }else{
|
|
|
|
+ self.netWorkImageView.setAsyncImage(urlString: imageModel.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!)
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+extension TSAIListPhotoGeneratorVC {
|
|
|
|
+ func setVideoHidden(){
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoLive {
|
|
|
|
+// videoPlayerVC.removeFromParent()
|
|
|
|
+// videoPlayerVC.view.removeFromSuperview()
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ func setVideoURL(){
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoLive {
|
|
|
|
+// if let model = imageModel {
|
|
|
|
+// switchOriginalPictureBtn.isHidden = true
|
|
|
|
+// self.videoPlayerVC = TSAIListVideoPlayerVC(videoURL: model.videoURL)
|
|
|
|
+// self.addChild(self.videoPlayerVC)
|
|
|
|
+// self.videoPlayerVC.view.frame = self.netWorkImageView.bounds
|
|
|
|
+// self.netWorkImageView.addSubview(self.videoPlayerVC.view)
|
|
|
|
+// self.videoPlayerVC.setControlsBottom(bottem: -20)
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+extension TSAIListPhotoGeneratorVC {
|
|
|
|
+
|
|
|
|
+ func setExpandAreaImage(){
|
|
|
|
+// if viewModel.generatorModel.generatorStyle == .photoExpand {
|
|
|
|
+// netWorkImageView.image = nil
|
|
|
|
+// expandAreaView.bgImageView.setAsyncImage(urlString: imageModel?.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!)
|
|
|
|
+// expandAreaView.showImageView.image = self.viewModel.generatorModel.upLoadImage
|
|
|
|
+// }
|
|
|
|
+ }
|
|
|
|
+}
|