// // MeRootPageController.swift // Crush // // Created by Leon on 2025/7/22. // import UIKit import TZImagePickerController class MeRootPageController: CLTabRootController { var settingButton: EPIconGhostButton! private var lastRequestDate: Date? var uploadingAvatar : UploadPhotoM? override func viewDidLoad() { super.viewDidLoad() setupViews() setupDats() setupEvents() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) controlRequestUserInfo() } private func controlRequestUserInfo() { let now = Date() if let lastDate = lastRequestDate { let interval = now.timeIntervalSince(lastDate) if interval < 30 { //30s return } } // 超过30秒或第一次出现,可以请求 loadUserInfo() loadAIRoleList() lastRequestDate = now } private func setupViews() { navigationView.bgView.alpha = 0 // title = nickname settingButton = { let v = EPIconGhostButton(radius: .none, iconSize: .medium, iconCode: .iconSetting) v.addTarget(self, action: #selector(settingAction), for: .touchUpInside) navigationView.rightStackH.addArrangedSubview(v) v.snp.makeConstraints { make in make.size.equalTo(CGSize(width: 44, height: 44)) } return v }() #if DEBUG if APIConfig.environment == .test{ let debugButton = { let v = UIButton() v.setTitle("Debug Entrances", for: .normal) v.titleLabel?.font = .t.tlm v.setTitleColor(.yellow, for: .normal) v.layer.borderColor = UIColor.yellow.cgColor v.layer.borderWidth = 1 v.addTarget(self, action: #selector(tapDebugButton), for: .touchUpInside) navigationView.addSubview(v) v.snp.makeConstraints { make in make.leading.equalToSuperview().offset(24) make.height.equalTo(30) make.centerY.equalTo(navigationView.backButton) } return v }() debugButton.isHidden = false } #endif } private func setupDats() { // See controlRequestUserInfo } private func setupEvents() { NotificationCenter.default.addObserver(self, selector: #selector(notiAIRoleAddOrDelete), name: AppNotificationName.aiRoleCreatedOrDelete.notificationName, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(notificationAIRoleInfoUpdated(noti:)), name: AppNotificationName.aiRoleInfoChanged.notificationName, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(logOut), name: AppNotificationName.userLogout.notificationName, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(login), name: AppNotificationName.userLoginSuccess.notificationName, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(notifyUserInfoChanged), name: AppNotificationName.userInfoUpdated.notificationName, object: nil) //container.headerView.avatarTopButton.addTarget(self, action: #selector(tapAvatarTopButton), for: .touchUpInside) container.tapAvatarAction = {[weak self] in self?.tapAvatarTopButton() } } private func loadUserInfo() { UserCore.shared.refreshUserInfo { _ in } } private func loadAIRoleList() { AIRoleProvider.request(.aiRoleListOfMine, modelType: [AIRoleInfo].self) { [weak self] result in switch result { case let .success(success): self?.container.config(datas: success) // self?.container.headerView.setupRoleCount(valid: success?.count ?? 0, total: 10) case let .failure(failure): dlog(failure) } } } // MARK: - Events @objc private func settingAction() { let vc = SettingListController() navigationController?.pushViewController(vc, animated: true) } @objc private func tapDebugButton() { UIWindow.getTopViewController()?.navigationController?.pushViewController(TestEntrancesController(), animated: true) } @objc private func tapAvatarTopButton(){ guard let picker = ImagePicker(maxImagesCount: 1, delegate: self) else { return } picker.allowPickingGif = false picker.showSelectBtn = false picker.needCircleCrop = true picker.cropRect = CGRect(origin: .init(x: 0, y: 0), size: CGSize(width: UIScreen.width, height: UIScreen.height)) picker.circleCropRadius = Int((UIScreen.width - 37*2) * 0.5) present(picker, animated: true, completion: nil) } // MARK: - Functions func updateHeadImage(headUrlString: String?, completion: ((Bool)->Void)? = nil){ guard let avatar = headUrlString else { return } var params = [String:Any]() params.updateValue(UserCore.shared.user!.userId, forKey: "userId") params.updateValue(avatar, forKey: "headImage") Hud.showIndicator() UserProvider.request(.userInfoEdit(params: params), modelType: String.self) {[weak self] result in Hud.hideIndicator() switch result { case .success: self?.uploadingAvatar = nil UserCore.shared.refreshUserInfo(block: nil) completion?(true) case .failure: completion?(false) } } } // MARK: - Notification @objc private func notiAIRoleAddOrDelete(){ loadAIRoleList() } @objc private func notificationAIRoleInfoUpdated(noti: Notification) { loadAIRoleList() } @objc private func notifyUserInfoChanged(){ } @objc private func logOut(){ container.config(datas: []) } @objc private func login(){ loadAIRoleList() } } extension MeRootPageController : TZImagePickerControllerDelegate{ func imagePickerController(_: TZImagePickerController!, didFinishPickingPhotos photos: [UIImage]!, sourceAssets _: [Any]!, isSelectOriginalPhoto _: Bool, infos _: [[AnyHashable: Any]]!) { guard let img = photos.first else { return } // Crop Avatar let cropViewController = CropViewController(image: img) { [unowned self] croppedImage in self.container.headerView.avatarView.bindImage(img: croppedImage, showUploading: true) // 裁剪后的图片 let photo = UploadPhotoM() photo.image = croppedImage photo.imageSize = croppedImage?.size ?? CGSizeZero photo.addThisItemTimeStamp = Date().timeStamp photo.delegate = self uploadingAvatar = photo CloudStorage.shared.s3AddPhotos([photo], bucket: .HEAD_IMAGE) } let navc = CLNavigationController(rootViewController: cropViewController) UIWindow.getTopViewController()?.present(navc, animated: true, completion: nil) // let model = UploadPhotoM() // model.image = img // model.imageSize = img.size // model.addThisItemTimeStamp = Date().timeStamp // model.delegate = self // uploadingAvatar = model // // self.container.headerView.avatarView.bindImage(img: img, showUploading: true) // // CloudStorage.shared.s3AddPhotos([model], bucket: .HEAD_IMAGE) } } extension MeRootPageController:UploadPhotoDelegate{ func uploadFailWith(_ photo: UploadPhotoM) { dlog("👮upload failed: \(photo)") self.container.headerView.avatarView.bindImage(img: nil) } func uploadProgress(_ progress: Float) { dlog("👮progress \(progress)") } func uploadDoneWith(_ photo: UploadPhotoM){ dlog("👮上传成功: \(photo.remoteFullPath ?? ""), remoteImageUrlString \(photo.remoteImageUrlString ?? "")") } func imageCheck(_ photoM: UploadPhotoM, result: Bool){ dlog("👮鉴黄结果:\(result)") if(result){ // self.headView.bindImageUrl(imgUrl: photoM.remoteFullPath) // 上传到s3... 并修改个人信息 self.updateHeadImage(headUrlString: photoM.remoteFullPath) {[weak self] result in if result{ self?.container.headerView.avatarView.bindImageUrl(imgUrl: photoM.remoteFullPath) } } }else{ self.container.headerView.avatarView.bindImageUrl(imgUrl: UserCore.shared.user?.headImage) } } }