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

407 lines
15 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// 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)
}
}