TSGenerateBasePhotoOperation.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. //
  2. // TSGenerateBasePhotoOperation.swift
  3. // AIRingtone
  4. //
  5. // Created by 100Years on 2025/3/24.
  6. //
  7. import Combine
  8. import Alamofire
  9. import ObjectMapper
  10. import Kingfisher
  11. class TSGenerateBasePhotoOperationQueue: TSGenerateBaseOperationQueue {
  12. static let shared:TSGenerateBasePhotoOperationQueue = TSGenerateBasePhotoOperationQueue()
  13. func creatOperation(uuid: String) -> TSGenerateBasePhotoOperation {
  14. let operation = super.creatOperation(uuid: uuid, type: TSGenerateBasePhotoOperation.self)
  15. handleStateDatauPblished(uuid: uuid, generateOperation: operation as! TSGenerateBaseOperation, notificationName: .kGenerateBasePhotoOperation)
  16. return operation as! TSGenerateBasePhotoOperation
  17. }
  18. override func getUUIDData(uuid:String)->(TSProgressState,TSActionInfoModel?){
  19. if let PosterOperation = TSGenerateBasePhotoOperationQueue.shared.findOperation(uuid: uuid) as? TSGenerateBasePhotoOperation {
  20. dePrint("TSBaseOperation stateDatauPblished 发送 = \(PosterOperation.stateDatauPblished)")
  21. return (PosterOperation.stateDatauPblished.0,PosterOperation.currentActionInfoModel)
  22. }
  23. return (.none,TSActionInfoModel())
  24. }
  25. }
  26. class TSGenerateBasePhotoOperation: TSGenerateBaseOperation , @unchecked Sendable{
  27. //是否展示成功后的 View 提醒
  28. public var isShowSuccessView:Bool = false
  29. override var actionInfoDict:[String:Any]{
  30. return [
  31. "actionType":"image_create",
  32. "comments": "Success",
  33. "costTime":9,
  34. "createdTimestamp":1742183242,
  35. "id":2449,
  36. "percent":1,
  37. "request":"{\"prompt\": \"Traditional Chinese ink painting style phoenix soaring through misty mountain peaks, dynamic black brushstrokes with crimson accents on rice paper texture, Googie architecture space station, 1950s atomic age aesthetic, curved aluminum panels, starburst patterns, glass dome observatory --edge_threshold 0.5 --atomic_age_style 0.8 --chrome_reflection 1.2\", \"width\": 800, \"height\": 1440, \"countryCode\": \"FR\"}",
  38. "response": "{\"resultUrl\": \"https://be-aigc.s3-accelerate.amazonaws.com/4c946f78-b1e7-4ffe-ba18-fff26b10178c.png\"}",
  39. "status":"success"
  40. ]
  41. }
  42. override func replaceSaveInfoModel(model:TSActionInfoModel){
  43. model.uuid = uuid
  44. model.request.imageUrlTimestamp = currentActionInfoModel.request.imageUrlTimestamp
  45. if isSaveDB {
  46. TSRMShared.aiListDB.updateData(model,id: currentActionInfoModel.id)
  47. }
  48. currentActionInfoModel = model
  49. dePrint("model actionStatus 发出=\(model.actionStatus)")
  50. currentActionInfoModelChanged?(currentActionInfoModel)
  51. }
  52. override func handleGenerateSuccess() {
  53. // kPurchaseBusiness.useOnceForFree(type: .general)
  54. TSRMShared.aiListDB.updateData(currentActionInfoModel,id: currentActionInfoModel.id)
  55. if isShowSuccessView == false {
  56. return
  57. }
  58. guard let window = WindowHelper.getKeyWindow() else {
  59. debugPrint("getKeyWindow nil")
  60. return
  61. }
  62. guard let rootVC = WindowHelper.topViewController() else {
  63. debugPrint("handleGenerateSuccess topViewController nil")
  64. return
  65. }
  66. let copyModel = self.currentActionInfoModel.copy()
  67. if let cyModel = copyModel as? TSActionInfoModel {
  68. let topY = k_Nav_Height+10
  69. debugPrint("topY=\(topY)")
  70. kSaveSuccesswShared.show(atView: window,text: "Successfully generated".localized,deadline: 5.0,bottom: kSaveSuccesswShared.getBottom(topY: topY)) {
  71. // let gennerateVC = TSPTPGeneratorVC(generateStyleModel: TSAIListPhotoGeneratorModel(),infoModel: cyModel) { model in }
  72. // gennerateVC.modalPresentationStyle = .overFullScreen
  73. // gennerateVC.modalTransitionStyle = .crossDissolve
  74. // rootVC.present(gennerateVC, animated: true)
  75. }
  76. }else{
  77. debugPrint("copyModel as? TSActionInfoModel error")
  78. }
  79. }
  80. /**
  81. 1.用户上传图片
  82. 2.调用生成接口
  83. 3.后台返回查询 id,根据 id 不断查询进度和结果.(此时才允许进度后台)
  84. 利用3后台返回的TSActionRequestModel中存着关键的请求接口数据,请求数据
  85. */
  86. private var uploadRequest:Request?
  87. private var creatRequest:Request?
  88. private func createActionInfoModel(generateStyleModel:TSAIListPhotoGeneratorModel) -> TSActionInfoModel? {
  89. guard let upLoadImageUrl = generateStyleModel.upLoadImageUrl else { return nil }
  90. let infoModel = TSActionInfoModel()
  91. infoModel.id = Date.timestampInt
  92. infoModel.request = TSActionRequestModel()
  93. infoModel.request.imageUrl = upLoadImageUrl
  94. infoModel.request.imageUrlTimestamp = Date.timestampInt
  95. infoModel.request.prompt = generateStyleModel.prompt
  96. infoModel.request.inputText = generateStyleModel.inputText
  97. infoModel.request.generatorStyle = generateStyleModel.generatorStyle
  98. return infoModel
  99. }
  100. func uploadImage(generateStyleModel:TSAIListPhotoGeneratorModel,complete:@escaping (TSActionInfoModel?)->Void) {
  101. let upLoadImage = generateStyleModel.upLoadImage
  102. if let imageUrl = generateStyleModel.upLoadImageUrl,imageUrl.contains("http") {
  103. complete(createActionInfoModel(generateStyleModel: generateStyleModel))
  104. return
  105. }
  106. stopNetwork = false
  107. stateDatauPblished = (.start,nil)
  108. stateDatauPblished = (.progressString(uploadingPhoto(progress: 0.0)),currentActionInfoModel)
  109. uploadRequest = TSNetworkShared.uploadImage(upLoadImage: upLoadImage, maxKb: imageMaxKb) { [weak self] progress in
  110. guard let self = self else { return }
  111. if generatingProgress == 0 {
  112. stateDatauPblished = (.progressString(uploadingPhoto(progress: progress)),currentActionInfoModel)
  113. }
  114. } completion: { [weak self] data, error in
  115. guard let self = self else { return }
  116. if stopNetwork == true { return }
  117. if let error = error {
  118. generateStyleModel.upLoadImageUrl = nil
  119. self.stateDatauPblished = (TSProgressState.getFailed(error.tsDesc,error.tsCode),nil)
  120. complete(nil)
  121. }else{
  122. if let string = data as? String {
  123. generateStyleModel.upLoadImageUrl = string
  124. if let url = URL(string: string){//上传成功后,就将图片缓存到本地
  125. ImageCache.default.store(upLoadImage, forKey: url.cacheKey)
  126. }
  127. complete(createActionInfoModel(generateStyleModel: generateStyleModel))
  128. }else{
  129. complete(nil)
  130. }
  131. }
  132. }
  133. }
  134. func creatImage(oldModel:TSActionInfoModel) {
  135. initializeActionInfoModel(oldModel: oldModel)
  136. if oldModel.upImageURLExpired { return }
  137. generatingProgress = 0
  138. stopNetwork = false
  139. stateDatauPblished = (.start,nil)
  140. currentActionInfoModel.status = "running"
  141. currentActionInfoModel.actionStatus = .running
  142. currentActionInfoModel.percent = 0
  143. replaceSaveInfoModel(model: currentActionInfoModel)
  144. stateDatauPblished = (.progressString(generating(progress: 0.0)),currentActionInfoModel)
  145. let request = currentActionInfoModel.request
  146. var urlType:TSNeURLType = .imageRewrite
  147. var postDict:[String:Any] = [
  148. "device":getUserInfoJsonString(),
  149. "imageUrl":request.imageUrl,
  150. "model":request.generatorStyle.aiModel
  151. ]
  152. switch request.generatorStyle {
  153. case .enhance:
  154. urlType = .imageRewrite
  155. postDict["prompt"] = "把图片变清晰"
  156. case .colorize:
  157. urlType = .imageRewrite
  158. postDict["prompt"] = "Add suitable colors to photos"
  159. case .descratch:
  160. urlType = .imageRewrite
  161. postDict["prompt"] = "Remove the photo's scratches and dirt"
  162. case .enlighten:
  163. urlType = .imageRewrite
  164. postDict["prompt"] = "Adjust the light and darkness of the photo to make the overall look coordinated"
  165. case .recreate:
  166. urlType = .imageRewrite
  167. postDict["prompt"] = "Recreate damaged portraits and added suitable color for photo"
  168. }
  169. creatRequest = TSNetworkShared.post(urlType: urlType,parameters: postDict) { [weak self] data,error in
  170. guard let self = self else { return }
  171. if stopNetwork == true { return }
  172. if let error = error {
  173. handleFailInfoModel(errorString: error.tsDesc,code: error.tsCode)
  174. }else{
  175. if let dataDict = kNetWorkCodeSuccess(data: data),
  176. let actionId = dataDict["actionId"] as? Int{
  177. if stopNetwork == false {
  178. self.stateDatauPblished = (.pending,nil) //通知首页进行更新
  179. self.getActionInfo(action_id:actionId)
  180. }
  181. }else{
  182. handleFailInfoModel(errorString: "",code: 0)
  183. }
  184. }
  185. }
  186. }
  187. override func generating(progress: Float) -> String {
  188. let progress = Float(progress)*(0.9) // 预留 10% 进度给图片下载
  189. //Generating 0%-100%
  190. var progressInt = Int(progress*100)
  191. if progressInt > 99 {
  192. progressInt = 99
  193. }
  194. generatingProgress = progressInt
  195. return "Generating".localized + " \(progressInt)%"
  196. }
  197. var imageMaxKb:Int{
  198. return 10*1024
  199. }
  200. func uploadingPhoto(progress:Float) -> String {
  201. //Uploading Photo 0%-100%
  202. var progressInt = Int(progress*100)
  203. if progressInt > 99 {
  204. progressInt = 99
  205. }
  206. return "Uploading Photo".localized + " \(progressInt)%"
  207. }
  208. override func cancelCleanContent() {
  209. super.cancelCleanContent()
  210. debugPrint("cancelCleanContent")
  211. uploadRequest?.cancel()
  212. creatRequest?.cancel()
  213. }
  214. }