Visual_Novel_iOS/crush/Crush/Src/Modules/Role/Create/RolePublishController.swift

407 lines
15 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// RolePublishController.swift
// Crush
//
// Created by Leon on 2025/7/20.
//
import UIKit
import Combine
import TZImagePickerController
///
///
class RolePublishController: RoleCreateBaseController<RolePublishView> {
weak var viewModel: RoleCreateViewModel!
// @Published var image: UIImage?
private var cancellables = Set<AnyCancellable>()
var isAllImagesOK: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupViews()
setupDatas()
setupEvents()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
disabledFullScreenPan()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
enabledFullScreenPan()
}
private func setupViews() {
container.container.scrollView.delegate = self
}
private func setupDatas(){
// if let editAIInfo = viewModel.editAIInfo, let url = editAIInfo.imageUrl{
// var usingImage = AIUserImageQuery()
// usingImage.imageUrl = url
// usingImage.status = .completed
// container.appearanceResult.usingFigureImage = usingImage
// }
if let editAIInfo = viewModel.editAIInfo{
viewModel.requestParams.aiUserExt?.imageDesc = editAIInfo.aiUserExt?.imageDesc
viewModel.requestParams.aiUserExt?.imageStyleCode = editAIInfo.aiUserExt?.imageStyleCode
}
// --
var title = "Create"
var bottomButtonTitle = "Create"
if viewModel.editAIInfo != nil {
title = "Modify"
bottomButtonTitle = "Modify"
}
navigationView.alpha0Title = title
container.titleView.title = title
container.bottomButton.setTitle(bottomButtonTitle, for: .normal)
}
private func setupEvents(){
container.backButton.addTarget(self, action: #selector(tapBackButton), for: .touchUpInside)
container.bottomButton.addTarget(self, action: #selector(bottomButtonTapped), for: .touchUpInside)
container.generate1Button.addTarget(self, action: #selector(tapAIGeneratedIntroductionButton), for: .touchUpInside)
container.appearanceResult.generateButton.addTarget(self, action: #selector(tapRegenerateFigureButton), for: .touchUpInside)
container.uploadImageView.bgTapBlock = {[weak self] in
//self?.pickAppearance()
self?.goCreateAIGeneratePics()
}
viewModel.$batchNo.sink {[weak self] result in
self?.container.showQueryGeneratedImages(generating: !result.isEmpty)
self?.loadingGeneratingResults(batchNo: result)
}.store(in: &cancellables)
container.$introductionContent.sink {[weak self] string in
self?.viewModel.requestParams.introduction = string
}.store(in: &cancellables)
if viewModel.editAIInfo == nil{
doGenerate()
}else{
restoreEditInfo(aiInfo: viewModel.editAIInfo)
}
}
private func restoreEditInfo(aiInfo: AIUserModel?) {
guard let info = aiInfo else { return }
container.privacyPublic = (info.permission ?? 2) == 1
container.introductionContent = info.introduction ?? ""
container.showQueryGeneratedImages(generating: true)
//
let last = AIUserImageQuery()
last.imageUrl = info.imageUrl
last.status = .completed
container.appearanceResult.usingFigureImage = last
container.appearanceResult.selectImageUrl = info.imageUrl ?? ""
//
let photo = UploadPhotoM()
photo.setupValidImageUrl(url: info.headImg)
container.avatarModel = photo
}
// MARK: - Functions
func loadingGeneratingResults(batchNo : String?){
if isAllImagesOK {
return
}
guard let queryNo = batchNo, queryNo.isEmpty == false else{
dlog("❌batchNo is nil")
return
}
container.appearanceResult.setupLastGenerateProcessStart()
dlog("📖查询图片生成中...")
AICowProvider.request(.imageGeneratedQuery(batchNo: queryNo), modelType: [AIUserImageQuery].self) { [weak self] result in
switch result {
case .success(let success):
guard let queryDatas = success else{
return
}
self?.container.appearanceResult.config(success)
var ok = true
if(queryDatas.count < 6){
ok = false
}else{
for per in queryDatas {
if per.status == .pending{
ok = false
}
}
}
self?.isAllImagesOK = ok
if ok == false{
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {[weak self] in
self?.loadingGeneratingResults(batchNo: self?.viewModel.batchNo)
}
}else{
//
self?.container.appearanceResult.setupLastGenerateProcessEnd()
}
case .failure:
break
}
}
}
///
private func goCreateAIGeneratePics(){
let vc = RoleFigureGenerateController()
vc.viewModel = viewModel
navigationController?.pushViewController(vc, animated: true)
vc.generatedBatchNoAction = {[weak self] batchNo, imageStyleCode,description, referenceBase64 in
self?.viewModel.requestParams.aiUserExt?.imageStyleCode = imageStyleCode
self?.viewModel.requestParams.aiUserExt?.imageDesc = description
//
if batchNo.count > 0{
self?.isAllImagesOK = false
self?.container.appearanceResult.config([], reset: true) // loading
self?.container.showQueryGeneratedImages(generating: true)
self?.loadingGeneratingResults(batchNo: batchNo)
}
}
}
///
private func goEditAIRegeneratePics(){
let vc = RolePhotoGenerateController(type: .figure)
vc.aiId = viewModel.requestParams.aiId
vc.introduction = container.introductionContent
vc.sex = viewModel.requestParams.sex
vc.birthdayString = viewModel.requestParams.birthday
vc.preSelectstyleCode = viewModel.requestParams.aiUserExt?.imageStyleCode // "IS0020"//
vc.prePhotoDesc = viewModel.requestParams.aiUserExt?.imageDesc
presentNaviRootVc(vc: vc)
vc.confirmSelectAction = {[weak self] imageStyleCode, desc, imgs in
self?.viewModel.requestParams.aiUserExt?.imageStyleCode = imageStyleCode
self?.viewModel.requestParams.aiUserExt?.imageDesc = desc
guard let image = imgs?.first else {return}
self?.container.loadDataAndSelect(image)
}
}
private func judgeAlertToPublishNewAIRole(){
// Alert.showAIRoleCreateSuccessAlert {
// Hud.hideIndicator()
// } confirmAction: {[weak self] in
// self?.doPublishRole()
// }
if viewModel.editAIInfo != nil{
// AI
doPublishRole()
}else{
// AI Role
if UserCore.shared.user?.canCreateAIRole() ?? false{
//
Alert.showAIRoleCreateSuccessAlert {
Hud.hideIndicator()
} confirmAction: {[weak self] in
self?.doPublishRole()
}
} else {
if UserCore.shared.user?.isMember == false{ // VIP
Hud.hideIndicator()
let sheet = VIPSubscribeSheet()
sheet.show()
}else {
// #warning("Alert ")
Alert.showAIRoleCreateSuccessAlert {
Hud.hideIndicator()
} confirmAction: {[weak self] in
self?.doPublishRole()
}
}
}
}
}
private func doPublishRole(){
//#warning("test")
// guard let aiId = viewModel.requestParams.aiId else{
// return
// }
// AppRouter.goBackRootController(jumpIndex: .me)
// DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
// AppRouter.goChatVC(aiId: aiId)
// AppRouter.alertCreateAlbumsToRoleHome(aiId: aiId)
// }
// view.hideToastActivity()
// return
// close(dismissFirst: true)
// AppRouter.goBackRootController(jumpIndex: .me)
// close(dismissFirst: true) {
// let vc = UIWindow.getTopViewController()
// if let current = UIWindow.getTopViewController(), current.isKind(of: RoleHomePagerController.self){
// // Stay in RoleHomePagerController
// }else{
// AppRouter.goBackRootController(jumpIndex: .me)
// }
// dlog("🔥current vc: \(String(describing: vc))")
// }
// return
guard let avatar = container.avatarModel?.remoteFullPath else {
dlog("invalid ai role avatar")
return
}
viewModel.requestParams.headImg = avatar
viewModel.requestParams.introduction = container.introductionContent
viewModel.requestParams.permission = container.privacyPublic ? 1 : 2
var params = viewModel.requestParams.toNonNilDictionary()
let editAIInfo = viewModel.editAIInfo
params.updateValue(container.appearanceResult.selectImageUrl, forKey: "imageUrl")
//dlog("🔥params: \(params)")
//Hud.showIndicator()
AIRoleProvider.request(.aiUserCreateEdit(params: params), modelType: AICreateResponse.self) {[weak self] result in
Hud.hideIndicator()
switch result {
case let .success(success):
NotificationCenter.post(name: .aiRoleCreatedOrDelete)
NotificationCenter.post(name: .aiRoleInfoChanged)
if editAIInfo != nil{
dlog("编辑AI 退出")
//
self?.close(dismissFirst: true) {
// _ = UIWindow.getTopViewController()
if let current = UIWindow.getTopViewController(), current.isKind(of: RoleHomePagerController.self){
// Stay in RoleHomePagerController
}else{
AppRouter.goBackRootController(jumpIndex: .me)
}
}
}else{
//
dlog("新建AI 退出")
AppRouter.goBackRootController(jumpIndex: .me)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
AppRouter.goChatVC(aiId: success?.aiId)
AppRouter.alertCreateAlbumsToRoleHome(aiId: success?.aiId)
}
}
case .failure:
break
}
}
}
@objc private func tapAIGeneratedIntroductionButton(){
if container.introductionContent.count > 0{
let alert = Alert(title: "内容覆盖", text: "AI创建的内容会覆盖你已经填写的内容请确认是否继续")
let action1 = AlertAction(title: "继续", actionStyle: .confirm) {[weak self] in
self?.doGenerate()
}
let action2 = AlertAction(title: "Cancel", actionStyle: .cancel)
alert.addAction(action1)
alert.addAction(action2)
alert.show()
}else{
doGenerate()
}
}
private func doGenerate(){
var params = viewModel.requestParams.toPartialDictionary(keys: ["nickname", "sex", "birthday", "characterCode", "tagCode", "introduction"])
///
params.updateValue("GEN_INTRODUCTION", forKey: "ptType")
if container.introductionContent.count > 0{
params.updateValue(container.introductionContent, forKey: "content")
}
if let dialogue = viewModel.requestParams.aiUserExt?.dialogueStyle{
params.updateValue(dialogue, forKey: "dialogue")
}
if let figure = viewModel.requestParams.aiUserExt?.profile{
params.updateValue(figure, forKey: "figure")
}
Hud.showIndicator()
AICowProvider.request(.aiContentGenerate(params: params), modelType: AIUserContentGenResponse.self) {[weak self] result in
Hud.hideIndicator()
switch result {
case .success(let success):
if let content = success?.content{
self?.container.contentAIGenerated = content
}
case .failure:
return
}
}
}
@objc private func tapRegenerateFigureButton(){
//
if viewModel.requestParams.aiId != nil{
goEditAIRegeneratePics()
}else{
goCreateAIGeneratePics()
}
}
@objc private func bottomButtonTapped(){
//
if container.avatarModel?.remoteFullPath != nil{
Hud.showIndicator()
judgeAlertToPublishNewAIRole()
}else{
// ...
guard let photo = container.avatarModel else { return }
Hud.showIndicator()
CloudStorage.shared.s3BatchAddPhotos([photo], bucket: .ROLE) {[weak self] result in
if result{
//self?.doPublishRole()
self?.judgeAlertToPublishNewAIRole()
}else{
Hud.hideIndicator()
}
}
}
}
@objc private func tapBackButton() {
close()
}
}
extension RolePublishController: UIScrollViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
NaviAlphaHandle.changeNaviTitleAlpha(scrollView: scrollView, titleLabel: navigationView.titleLabel)
}
}