Visual_Novel_iOS/crush/Crush/Src/Components/Photo/PhotoBrowser/PhotoBrowserControllerExtRo...

438 lines
17 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.

//
// PhotoBrowserControllerExtRole.swift
// Crush
//
// Created by Leon on 2025/7/27.
//
extension PhotoBrowserController {
// MARK: - 🚩My Role
func createOperateViewOfRoleMine() {
bottomGradientContainer?.isHidden = false
rolePhotoUnlockEntry = {
let v = RolePhotoUnlockEntryView()
bottomGradientOperateStackV.addArrangedSubview(v)
return v
}()
setDefaultEntry = {
let v = RolePhotoSetDefaultEntryView()
bottomGradientOperateStackV.addArrangedSubview(v)
return v
}()
moreButton = {
let v = EPIconGhostButton(radius: .none, iconSize: .medium, iconCode: .more)
v.addTarget(self, action: #selector(tapNaviMoreInMyAIAlbum(sender:)), for: .touchUpInside)
titleView.rightStackH.addArrangedSubview(v)
titleView.paddingRightForRightStack = 16
v.snp.makeConstraints { make in
make.size.equalTo(v.bgImageSize())
}
return v
}()
setupRoleEvents()
}
func setupRoleEvents() {
rolePhotoUnlockEntry.editUnlockWayAction = { [weak self] in
self?.tapToSetupUnlockWay()
}
setDefaultEntry.setButton.addTarget(self, action: #selector(tapSetRoleDefaultButton), for: .touchUpInside)
}
// MARK: Action
func tapToSetupUnlockWay() {
let vc = RolePhotoUnlockWaySetController()
// item
let imageModel = imageModels[currentIndex]
vc.browseModel = imageModel
vc.priceUpdateAction = { [weak self] price in
let unlockPrice = price ?? 0
imageModel.aiAlbum.unlockPrice = unlockPrice
if unlockPrice > 0 {
imageModel.aiAlbum.isDefault = false
}
self?.reloadStatesByModel(model: imageModel)
}
navigationController?.pushViewController(vc, animated: true)
}
@objc func tapNaviMoreInMyAIAlbum(sender: UIButton) {
let pop = CLPopoverListView()
let rect = view.convert(sender.frame, from: sender.superview)
pop.setupDeletePopover(rect.insetBy(dx: 0.0, dy: -6.0), inView: view) { [weak self] in
self?.deleteAlbumOfMyAIRoleTapAction()
}
}
@objc private func tapSetRoleDefaultButton() {
let imageModel = imageModels[currentIndex]
let unlockPrice = imageModel.aiAlbum.unlockPrice
if unlockPrice > 0{
let alert = Alert(title: "默认图片", text: "设置为默认图片后,图片的解锁方式只能为“免费”")
let action1 = AlertAction(title: "Confirm", actionStyle: .confirm) {[weak self] in
self?.doRequestSetRoleDefaultAlbum()
}
let action2 = AlertAction(title: "Cancel", actionStyle: .cancel)
alert.addAction(action1)
alert.addAction(action2)
alert.show()
}else{
doRequestSetRoleDefaultAlbum()
}
}
// MARK: Functions
private func doRequestSetRoleDefaultAlbum(){
let imageModel = imageModels[currentIndex]
let aiUid = imageModel.aiId
let albumId = imageModel.aiAlbum.albumId
Hud.showIndicator()
AIRoleProvider.request(.aiRolePhotoDefaultSet(aiUid: aiUid, albumId: albumId), modelType: AnyCodable.self) { [weak self] result in
Hud.hideIndicator()
switch result {
case .success:
// dlog("set default results")
imageModel.aiAlbum.isDefault = true
self?.reloadStatesByModel(model: imageModel)
self?.setDefaultEntry.setupIsDefault(true)
NotificationCenter.post(name: .aiRoleAlbumPhotoInfoChanged)
NotificationCenter.post(name: .aiRoleInfoChanged) //
case .failure:
break
}
}
}
@objc func deleteAlbumOfMyAIRoleTapAction() {
guard currentIndex >= 0, currentIndex < imageModels.count else { return }
let model = imageModels[currentIndex]
if model.aiAlbum.isDefault.boolValue{
let alert = Alert(title: "删除图片", text: "不可删除封面默认图片,该图片会作为在个人主页头图,卡片主图,聊天背景")
let action1 = AlertAction(title: "Got it", actionStyle: .confirm)
alert .addAction(action1)
alert.show()
return
}
let alert = Alert(title: "删除图片", text: "图片删除后不可恢复。已经付费解锁过该图片的用户依然可以在角色的相册中看到该图片。")
let action1 = AlertAction(title: "Delete", actionStyle: .destructive) {[weak self] in
self?.deleteTapActionDone()
}
let action2 = AlertAction(title: "Cancel", actionStyle: .cancel)
alert.addAction(action1)
alert.addAction(action2)
alert.show()
}
private func deleteTapActionDone() {
let model = imageModels[currentIndex]
model.deleteTapBlock?(model) { [weak self] isSuccess in
guard let self = self else { return }
if isSuccess {
self.imageModels.remove(at: self.currentIndex)
if self.imageModels.isEmpty {
PhotoBrowserManager.shared.hidePhotoBrowser()
} else {
if self.currentIndex >= self.imageModels.count {
self.currentIndex -= 1
}
self.setupViews()
self.reloadCountLabel(hidden: false)
}
}
}
}
// MARK: - 🚩Other's Role
func createOperateViewOfOthers() {
roleOthersContainer = {
let v = SelectiveDeliveryEventsView()
v.backgroundColor = .clear
view.insertSubview(v, belowSubview: titleView)
v.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
return v
}()
// roleOthersContainer?.isUserInteractionEnabled = false
roleOthersCenterLock = {
let v = UIImageView()
v.image = MWIconFont.image(fromIcon: .iconPrivate, size: CGSize(width: 40, height: 40), color: .white)
roleOthersContainer?.addSubview(v)
v.snp.makeConstraints { make in
make.center.equalToSuperview()
}
return v
}()
let bottomStackH = {
let v = UIStackView()
v.spacing = 48
v.alignment = .center
roleOthersContainer?.addSubview(v)
v.snp.makeConstraints { make in
make.height.equalTo(48)
make.bottom.equalToSuperview().offset(-16 - UIWindow.safeAreaBottom * 0.5)
make.trailing.equalToSuperview().offset(-24)
}
return v
}()
iconUnlockButton = {
let v = StyleButton()
v.setContentHuggingPriority(UILayoutPriority(rawValue: 246), for: .horizontal)
v.primary(size: .large)
v.addTarget(self, action: #selector(tapUnlockPhoto), for: .touchUpInside)
bottomStackH.addArrangedSubview(v)
return v
}()
iconLabel = {
let v = CLIconLabel()
v.iconImageView.image = UIImage.icon32Diamond
v.iconSize = CGSize(width: 20, height: 20)
roleOthersContainer?.addSubview(v)
v.snp.makeConstraints { make in
make.centerY.equalTo(bottomStackH)
make.leading.equalToSuperview().offset(24)
make.trailing.lessThanOrEqualTo(bottomStackH.snp.leading).offset(-8)
}
return v
}()
iconLabel?.contentLabel.text = "1234"
let attributeString = StyleButton.getUnlockAttributeTitleByCoin(coin: 123, string: "unlock")
iconUnlockButton?.setAttributedTitle(attributeString, for: .normal)
}
@objc func tapUnlockPhoto() {
guard UserCore.shared.checkUserLoginIfNotPushUserToLogin() else{
PhotoBrowserManager.shared.hidePhotoBrowser()
return
}
let photoModel = imageModels[currentIndex]
var params = [String: Any]()
if let album = photoModel.aiAlbum {
if let aiId = photoModel.aiId {
params.updateValue(aiId, forKey: "aiId")
}
let albumId = album.albumId
params.updateValue(albumId, forKey: "albumId")
} else if let model = photoModel.sessionModel {
if let aiId = photoModel.aiId {
params.updateValue(aiId, forKey: "aiId")
}
if let albumId = model.baseRemoteInfo?.customAttachment?.albumId {
params.updateValue(albumId, forKey: "albumId")
}
if let messageServerId = model.v2msg?.messageServerId {
params.updateValue(messageServerId, forKey: "messageServerId")
}
} else {
return
}
//
let imgTest = "https://hhb.crushlevel.ai/dev/role/17581021489486439.jpg"
// if var album = photoModel.aiAlbum{
//
// album.lockStatus = .unlock
// album.imgUrl = nil
// album.img1 = "https://sub.crushlevel.ai/files/b/test/439076604280833/0aec65fdd92c404a9e3f8acac8e2c1ba.jpg?x-oss-process=image/resize,w_468,h_600&v=1&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9zdWIuY3J1c2hsZXZlbC5haS9maWxlcy9iL3Rlc3QvNDM5MDc2NjA0MjgwODMzLzBhZWM2NWZkZDkyYzQwNGE5ZTNmOGFjYWM4ZTJjMWJhLmpwZz94LW9zcy1wcm9jZXNzPWltYWdlL3Jlc2l6ZSx3XzQ2OCxoXzYwMCZ2PTEiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3NTgyMjgzNjd9fX1dfQ__&Signature=Jv5jE4d072OkFyYq5dxa3unXVaLWSNRddJEIIm42j4zmg36Yq8HGxVXz4X954ERmujm8zCluiVGMbIx-EH9JlQ1s~zbhgOo-lliaDGl977EsCVLBPsf639WFpdCXqnf3QAM7LwhuCbmdi~PBybJhKS31nEKoS53idOB4JyEXXp9wv3RpVjDoL4JF8C22H8k5gJ0hpt3NhfZiTSbsSRJBApNHfCKAFm6PEKQ8dAQ6f7rRxHwPTkbhHi~fRUahuJI10Ti-8t2Hem4akTV4plmgz9chsLCfHBNh5WDrwzoCZRDDljpaNcwpkZ5Mew23seKphb5iLxHgVP3WGAwXb0BoRA__&Key-Pair-Id=K35ZQ246Y37QV8"
// photoModel.imageUrl = album.img1
// album.unlockPrice = 0
// photoModel.aiAlbum = album
// self.reloadStates(index: self.currentIndex)
// self.reloadCurrentZoomImage()
// }
// return
// #warning("test")
// if let model = photoModel.sessionModel {
// Hud.hideInidcator()
// model.baseRemoteInfo?.customAttachment?.unlockPrice = 0
// model.baseRemoteInfo?.customAttachment?.url = imgTest
//
// photoModel.imageUrl = imgTest
// photoModel.sessionModel = model
//
// // Reload
// self.reloadStates(index: self.currentIndex)
// self.reloadCurrentZoomImage()
// }
// return
Hud.showIndicator()
ChatProvider.request(.aiUnlockAlbumImg(params: params), modelType: AIAlbumUnlockImages.self) { [weak self] result in
Hud.hideIndicator()
switch result {
case let .success(unlockData):
guard let img1 = unlockData?.img1 else {
PhotoBrowserManager.shared.hidePhotoBrowser()
return
}
// 🚩"1.2.UI"
//
guard let self = self else { return }
if let album = photoModel.aiAlbum {
album.lockStatus = .unlock
album.img1 = img1
album.imgUrl = img1
album.unlockPrice = 0
photoModel.imageUrl = album.img1
photoModel.aiAlbum = album
// Reload
self.reloadStates(index: self.currentIndex)
self.reloadCurrentZoomImage()
NotificationCenter.post(name: .aiRoleAlbumPhotoInfoChanged, object: album)
}else if let model = photoModel.sessionModel {
model.baseRemoteInfo?.customAttachment?.unlockPrice = 0
model.baseRemoteInfo?.customAttachment?.url = img1
photoModel.imageUrl = img1
photoModel.sessionModel = model
// Reload
self.reloadStates(index: self.currentIndex)
self.reloadCurrentZoomImage()
NotificationCenter.post(name: .aiRoleAlbumPhotoInfoChanged, object: model)
}else{
assert(false, "need update")
}
WalletCore.shared.refreshWallet()
case .failure:
break
}
}
}
@objc func tapOperateChipButton(_ sender: EPChipContrastButton) {
guard UserCore.shared.checkUserLoginIfNotPushUserToLogin() else{
PhotoBrowserManager.shared.hidePhotoBrowser()
return
}
}
@objc func tapLikeButton() {
guard UserCore.shared.checkUserLoginIfNotPushUserToLogin() else{
PhotoBrowserManager.shared.hidePhotoBrowser()
return
}
let photoModel = imageModels[currentIndex]
guard let likeView = likeView else { return }
// IM
if let album = photoModel.aiAlbum {
let albumId = album.albumId
if album.likedStatus == .liked {
//
album.likedStatus = .cancel
album.likedCount = max((album.likedCount ?? 0) - 1, 0)
PhotosViewModel.shared.album = album
likeView.bind(aiAlbum: album)
AIRoleProvider.request(.aiRolePhotoLikeOrNo(albumId: albumId, likedStatus: .cancel), modelType: EmptyModel.self) { [weak self] result in
self?.handleLikeRequestResult(result: result, albumId: albumId, isLike: false)
}
} else {
//
likeView.playLotteLike { _ in
guard var album = photoModel.aiAlbum else { return }
album.likedStatus = .liked
album.likedCount = (album.likedCount ?? 0) + 1
PhotosViewModel.shared.album = album
likeView.bind(aiAlbum: album)
}
AIRoleProvider.request(.aiRolePhotoLikeOrNo(albumId: albumId, likedStatus: .liked), modelType: EmptyModel.self) { [weak self] result in
self?.handleLikeRequestResult(result: result, albumId: albumId, isLike: true)
}
}
}
}
//
private func handleLikeRequestResult(result: Result<EmptyModel?, ResponseError>, albumId: Int, isLike: Bool) {
isRequesting = false
let photoModel = imageModels[currentIndex]
guard let likeView = likeView, let album = photoModel.aiAlbum else { return }
likeView.likeButton.isEnabled = true
switch result {
case .success:
//
break
case .failure:
//
if isLike {
//
album.likedStatus = .cancel
album.likedCount = max((album.likedCount ?? 0) - 1, 0)
} else {
//
album.likedStatus = .liked
album.likedCount = (album.likedCount ?? 0) + 1
}
PhotosViewModel.shared.album = album
likeView.bind(aiAlbum: album)
}
}
// MARK: - Helper
/// like : 💎 20 unlock
func getUnlockAttributeTitleByCoin(coin: Int) -> NSAttributedString {
let text = " \(coin) unlock"
let attributedString = NSMutableAttributedString()
if let iconImage = UIImage(named: "icon_32_diamond") { //
let attachment = NSTextAttachment()
attachment.image = iconImage
let iconSize = CGSize(width: 24, height: 24) //
attachment.bounds = CGRect(origin: .init(x: 0, y: -4), size: iconSize)
let iconAttributedString = NSAttributedString(attachment: attachment)
attributedString.append(iconAttributedString)
}
//
let textAttributedString = text.withAttributes([
.font(.t.tll), //
.textColor(.white),
])
attributedString.append(textAttributedString)
return attributedString
}
}