TSDiscoverVC.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. //
  2. // TSDiscoverVC.swift
  3. // AIEmoji
  4. //
  5. // Created by 100Years on 2025/6/23.
  6. //
  7. class TSDiscoverVC: TSBaseVC {
  8. let viewModel = kTSDiscoverVM
  9. var hintBaseVC:TSAIListHintBaseVC = TSAIListHintBaseVC(config: .defaultConfig)
  10. lazy var photoPickerManager: TSPhotoPickerManager = TSPhotoPickerManager(viewController: self)
  11. // lazy var vipBtn: UIButton = {
  12. // let vipBtn = UIButton.createButton(image: UIImage(named: "nav_vip")) { [weak self] in
  13. // guard let self = self else { return }
  14. // if kPurchaseCountDownTime.isCountDown {
  15. // kPresentModalVC(target: self, modelVC: TSPurchasePromotionalVC(isAnimation: false))
  16. // }else{
  17. // TSPurchaseVC.show(target: self)
  18. // }
  19. // }
  20. // vipBtn.isHidden = true
  21. // return vipBtn
  22. // }()
  23. //
  24. // lazy var purchaseCountdownView : TSPurchaseCountdownView = {
  25. // let purchaseCountdownView = TSPurchaseCountdownView()
  26. // purchaseCountdownView.clickBlock = { [weak self] in
  27. // guard let self = self else { return }
  28. // kPresentModalVC(target: self, modelVC: TSPurchasePromotionalVC(isAnimation: false))
  29. // }
  30. // purchaseCountdownView.isHidden = true
  31. // return purchaseCountdownView
  32. // }()
  33. // lazy var navBarView: TSBaseNavContentBarView = {
  34. // let navBarView = TSBaseNavContentBarView()
  35. //
  36. // let label = UILabel.createLabel(text: "Discover".localized,font: .font(size: 22,weight: .semibold),textColor: .white)
  37. // label.addShadow(shadowColor: UIColor.black.cgColor, shadowOffset: CGSize(width: 2, height: 2), shadowRadius: 2, shadowOpacity: 0.3)
  38. // navBarView.barView.addSubview(label)
  39. // label.snp.makeConstraints { make in
  40. // make.centerY.equalToSuperview()
  41. // make.leading.equalTo(17.0)
  42. // }
  43. //
  44. //
  45. // let stackView:UIStackView = UIStackView()
  46. // stackView.spacing = 8
  47. // navBarView.barView.addSubview(stackView)
  48. // stackView.addArrangedSubview(vipBtn)
  49. // stackView.addArrangedSubview(purchaseCountdownView)
  50. // stackView.snp.makeConstraints { make in
  51. // make.centerY.equalToSuperview()
  52. // make.trailing.equalTo(-16)
  53. // }
  54. // vipBtn.snp.makeConstraints { make in
  55. // make.width.height.equalTo(24)
  56. // }
  57. //
  58. // purchaseCountdownView.snp.makeConstraints { make in
  59. // make.height.equalTo(24)
  60. // }
  61. //
  62. //
  63. // return navBarView
  64. // }()
  65. lazy var collectionView: TSBaseCollectionView = {
  66. let collectionViewLayout = UICollectionViewFlowLayout()
  67. let collectionView = TSBaseCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
  68. collectionView.delegate = self
  69. collectionView.dataSource = self
  70. for cases in TSDiscoverViewStyle.allCases {
  71. collectionView.register(cases.cell, forCellWithReuseIdentifier: String(describing: cases.cell))
  72. }
  73. collectionView.register(TSDiscoverHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "TSDiscoverHeaderView")
  74. return collectionView
  75. }()
  76. override func viewDidLoad() {
  77. super.viewDidLoad()
  78. ClickEvent.logEvent(type: .discoverTab)
  79. }
  80. override func createView() {
  81. addNormalNavBarView()
  82. // navBarContentView.addSubview(navBarView)
  83. // navBarView.snp.makeConstraints { make in
  84. // make.edges.equalToSuperview()
  85. // }
  86. contentView.snp.updateConstraints { make in
  87. make.top.equalTo(0)
  88. }
  89. contentView.addSubview(collectionView)
  90. collectionView.snp.makeConstraints { make in
  91. make.edges.equalToSuperview()
  92. }
  93. TSDiscoverStyleMoreBaseCell.collectionView = collectionView
  94. }
  95. override func dealThings() {
  96. // NotificationCenter.default.addObserver(self, selector: #selector(updateVipView), name: .kPurchaseDidChanged, object: nil)
  97. // updateVipView()
  98. // NotificationCenter.default.addObserver(self, selector: #selector(checkkPurchaseCountDownTime), name: .kCloseTSPurchasePromotionalVC, object: nil)
  99. // checkkPurchaseCountDownTime()
  100. }
  101. // @objc func updateVipView() {
  102. // kMainAsync{
  103. // self.vipBtn.isHidden = PurchaseManager.default.isVip
  104. // self.checkkPurchaseCountDownTime()
  105. // }
  106. // }
  107. //
  108. // @objc func checkkPurchaseCountDownTime(){
  109. // if kPurchaseCountDownTime.isCountDown {
  110. // self.purchaseCountdownView.isHidden = false
  111. // kPurchaseCountDownTime.complete = { [weak self] minutes, seconds, end in
  112. // guard let self = self else { return }
  113. // if end {
  114. // self.purchaseCountdownView.isHidden = true
  115. // }else{
  116. // self.purchaseCountdownView.minLabel.text = minutes
  117. // self.purchaseCountdownView.secLabel.text = seconds
  118. // }
  119. // }
  120. // }else{
  121. // self.purchaseCountdownView.isHidden = true
  122. // }
  123. // }
  124. override func viewWillAppear(_ animated: Bool) {
  125. super.viewWillAppear(animated)
  126. // checkkPurchaseCountDownTime()
  127. }
  128. }
  129. extension TSDiscoverVC: UICollectionViewDataSource ,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
  130. func numberOfSections(in collectionView: UICollectionView) -> Int {
  131. return viewModel.discoverDatas.count
  132. }
  133. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  134. if let secModel = viewModel.discoverDatas.safeObj(At:section){
  135. return secModel.items.count
  136. }
  137. return 0
  138. }
  139. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  140. if let secModel = viewModel.discoverDatas.safeObj(At:indexPath.section),let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing:secModel.style.cell), for: indexPath) as? TSDiscoverBaseCell, let item = secModel.items.safeObj(At:indexPath.row){
  141. cell.items = item
  142. cell.clickBlock = { [weak self] model in
  143. guard let self = self else { return }
  144. if let secModel = viewModel.discoverDatas.safeObj(At:indexPath.section) {
  145. TSDiscoverVC.clickCell(target: self,indexPath: indexPath, itemModel:model,secModel: secModel)
  146. }
  147. }
  148. cell.clickSpecialBlock = { [weak self] cmd,data in
  149. guard let self = self else { return }
  150. clickSpecialBlock(cmd: cmd, data: data)
  151. }
  152. return cell
  153. }
  154. return UICollectionViewCell()
  155. }
  156. func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
  157. if let secModel = viewModel.discoverDatas.safeObj(At:indexPath.section),
  158. kind == UICollectionView.elementKindSectionHeader,
  159. let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "TSDiscoverHeaderView", for: indexPath) as? TSDiscoverHeaderView{
  160. header.sectionModel = secModel
  161. header.clickBlock = { [weak self] model in
  162. guard let self = self else { return }
  163. clickHeader(indexPath: indexPath,model: model)
  164. }
  165. return header
  166. }
  167. return UICollectionReusableView()
  168. }
  169. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
  170. if let secModel = viewModel.discoverDatas.safeObj(At:indexPath.section) {
  171. return secModel.style.itemSize
  172. }
  173. return .zero
  174. }
  175. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets{
  176. if let secModel = viewModel.discoverDatas.safeObj(At:section) {
  177. var sectionEdge = UIEdgeInsets(top: 0, left: kDiscoverSection.left, bottom: 0, right: kDiscoverSection.right)
  178. if secModel.title.isEmpty,section != 0 {
  179. sectionEdge = UIEdgeInsets(top: 20, left: kDiscoverSection.left, bottom: 0, right: kDiscoverSection.right)
  180. }
  181. if section == viewModel.discoverDatas.count-1 {
  182. sectionEdge = UIEdgeInsets(top: sectionEdge.top, left: sectionEdge.left, bottom: sectionEdge.bottom+20, right: sectionEdge.right)
  183. }
  184. return sectionEdge
  185. }
  186. return .zero
  187. }
  188. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
  189. if let secModel = viewModel.discoverDatas.safeObj(At:section),secModel.title.count > 0 {
  190. return CGSize(width: k_ScreenWidth, height: kDiscoverSectionH)
  191. }
  192. return .zero
  193. }
  194. // 当cell即将显示时恢复播放
  195. func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
  196. if let cell = cell as? TSDiscoverBaseCell {
  197. cell.willDisplay(indexPath: indexPath)
  198. }
  199. }
  200. // 当cell结束显示时暂停播放
  201. func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
  202. if let cell = cell as? TSDiscoverBaseCell {
  203. cell.didEndDisplaying(indexPath: indexPath)
  204. }
  205. }
  206. }
  207. //extension TSDiscoverVC: UIScrollViewDelegate {
  208. // // 开始拖拽(用户开始滚动)
  209. // func scrollViewDidScroll(_ scrollView: UIScrollView) {
  210. //// dePrint("scrollView.contentOffset.y=\(scrollView.contentOffset.y)")
  211. //
  212. // let height:CGFloat = 50 + k_Nav_Height
  213. //
  214. //// let alpha = scrollView.contentOffset.y/height
  215. //// navBarView.backgroundColor = .mainBg.withAlphaComponent(alpha)
  216. //
  217. // navBarView.backgroundColor = scrollView.contentOffset.y >= height ? .mainBg : .clear
  218. // }
  219. //}
  220. //extension TSDiscoverVC: UIScrollViewDelegate {
  221. // // 开始拖拽(用户开始滚动)
  222. // func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
  223. // print("滚动开始")
  224. // NotificationCenter.default.post(name: .kDiscoverScrollViewWillBegin, object: nil)
  225. // }
  226. //
  227. // // 结束拖拽(用户手指离开屏幕)
  228. // func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
  229. // if !decelerate {
  230. // print("滚动完全停止(无减速动画)")
  231. // NotificationCenter.default.post(name: .kDiscoverScrollViewEndDecelerating, object: nil)
  232. // }
  233. // }
  234. //
  235. // // 结束减速(滚动完全停止)
  236. // func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
  237. // print("滚动完全停止")
  238. // NotificationCenter.default.post(name: .kDiscoverScrollViewEndDecelerating, object: nil)
  239. // }
  240. //
  241. // // 以下方法组合可以准确判断滚动是否真正结束
  242. // func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
  243. // print("编程触发的滚动动画结束")
  244. // NotificationCenter.default.post(name: .kDiscoverScrollViewEndDecelerating, object: nil)
  245. // }
  246. //}
  247. extension TSDiscoverVC {
  248. func clickHeader(indexPath:IndexPath,model:TSDiscoverSectionModel) {
  249. kPushVC(target: self, modelVC: TSDiscoverStyleMoreVC(sectionModel: model))
  250. }
  251. func clickSpecialBlock(cmd:String,data:Any?) {
  252. if TSGenerateBasePhotoOperationQueue.isAvailabilityHandle(view: self.view)
  253. { return }
  254. if cmd == "ptv" {
  255. kPushVC(target: self, modelVC:TSAIDiyVideoVC(diyVideoType: 0))
  256. }else if cmd == "ttv" {
  257. kPushVC(target: self, modelVC:TSAIDiyVideoVC(diyVideoType: 1))
  258. }
  259. }
  260. static func clickCell(target:UIViewController,indexPath:IndexPath,itemModel:TSDiscoverItemModel,secModel:TSDiscoverSectionModel) {
  261. if itemModel.style.isInterceptMultipleGenerations,
  262. TSGenerateBasePhotoOperationQueue.isAvailabilityHandle(view: target.view)
  263. { return }
  264. var style = itemModel.style
  265. if style == .photoLive,
  266. let animationModel = itemModel.viewModel as? TSDiscoverAnimationItemVM,
  267. animationModel.style == .video {
  268. style = .videoV2
  269. }
  270. dePrint("\(style)")
  271. switch style{
  272. case .ageOld, .ageChild, .oldPhoto, .eyeOpen, .pretty, .photoLive, .photoQuality, .catTohuman,.process:
  273. kPushVC(target: target, modelVC: TSAIUploadPhotoBaseVC(titleString: itemModel.name, generatorStyle: itemModel.style,disCoverItemModel: itemModel))
  274. case .photoExpand:
  275. kPushVC(target: target, modelVC: TSAIExpandImageVC(upLoadImage: nil))
  276. case .futureBaby:
  277. kPushVC(target: target, modelVC: TSFutureBabyVC())
  278. case .changeEmote:
  279. TSDiscoverVC.enterSelectPhotos(target: target,style: itemModel.style) { image in
  280. kPushVC(target: target, modelVC: TSAIChangeEmoteVC(upLoadImage: image, style: .changeEmote))
  281. }
  282. break
  283. case .changehairColor:
  284. TSDiscoverVC.enterSelectPhotos(target: target,style: itemModel.style) { image in
  285. kPushVC(target: target, modelVC: TSAIChangeEmoteVC(upLoadImage: image, style: .changehairColor))
  286. }
  287. break
  288. case .changehair:
  289. TSDiscoverVC.enterSelectPhotos(target: target,style: itemModel.style) { image in
  290. kPushVC(target: target, modelVC: TSAIChangeEmoteVC(upLoadImage: image, style: .changehair))
  291. }
  292. case .ttp:
  293. kPushVC(target: target, modelVC: TSTTPInputVC())
  294. case .chat:
  295. let vc = TSChatViewController()
  296. vc.viewModel.uiStyle = .chat
  297. kPushVC(target: target, modelVC: vc)
  298. case .ptp,.videoV2:
  299. if let generateModel = itemModel.generateModel{
  300. kPushVC(target: target, modelVC: TSPTPUploadImageVC(itemModel:itemModel,generateModel: generateModel, sectionModel: secModel))
  301. }
  302. default:
  303. break
  304. }
  305. }
  306. }
  307. extension TSDiscoverVC{
  308. static var hintBaseVC:TSAIListHintBaseVC?
  309. static var photoPickerManager:TSPhotoPickerManager?
  310. static func enterSelectPhotos(
  311. target:UIViewController,
  312. style:TSFuncStyle,
  313. hintType:Int = 0,
  314. interceptSelectedPictureBlock:((UIImage) -> Bool)? = nil,
  315. complete: @escaping (UIImage)->Void)
  316. {
  317. let userDefaultsKey = style.getHintKey(hintType: hintType)
  318. if userDefaultsKey.count == 0 || style == .ptp {
  319. self.pickSinglePhoto(target:target,interceptSelectedPictureBlock: interceptSelectedPictureBlock,complete:complete)
  320. }else{
  321. TSAIListHintBaseVC.userDefaultsKey = userDefaultsKey
  322. if TSAIListHintBaseVC.isShowUploadImageHint{
  323. TSAIListHintBaseVC.isShowUploadImageHint = false
  324. self.presentModalHintVC(target:target,config:style.getConfig(hintType: hintType),complete:complete)
  325. }else {
  326. self.pickSinglePhoto(target:target,interceptSelectedPictureBlock: interceptSelectedPictureBlock,complete:complete)
  327. }
  328. }
  329. }
  330. static func presentModalHintVC(target:UIViewController,config:TSAIListHintBaseVC.Config,complete:@escaping (UIImage)->Void){
  331. let hintBaseVC = TSAIListHintBaseVC(config: config)
  332. hintBaseVC.clickUpImageHandle = { image in
  333. if let image = image {
  334. complete(image)
  335. }else{
  336. dePrint("图片异常")
  337. }
  338. kDelayMainShort {
  339. Self.hintBaseVC?.dismissPageVC()
  340. Self.hintBaseVC = nil
  341. }
  342. }
  343. kPresentModalVC(target: target, modelVC: hintBaseVC,transitionStyle: .crossDissolve)
  344. Self.hintBaseVC = hintBaseVC
  345. }
  346. static func pickSinglePhoto(target:UIViewController,interceptSelectedPictureBlock:((UIImage) -> Bool)? = nil,complete: @escaping (UIImage)->Void) {
  347. let photoPickerManager = TSPhotoPickerManager(viewController: target)
  348. photoPickerManager.interceptSelectedPictureBlock = interceptSelectedPictureBlock
  349. photoPickerManager.pickCustomSinglePhoto() { image, errorString in
  350. if let errorString = errorString {
  351. TSToastShared.showToast(text: errorString)
  352. }else if let image = image {
  353. complete(image)
  354. }else{
  355. dePrint("图片异常")
  356. }
  357. kDelayMainShort {
  358. Self.photoPickerManager?.dismissPageVC()
  359. Self.photoPickerManager = nil
  360. }
  361. }
  362. Self.photoPickerManager = photoPickerManager
  363. }
  364. }
  365. extension TSDiscoverVC:TSTabBarControllerProtocol {
  366. func tabBarDoubleTap(_ tabbar: UITabBarController){
  367. collectionView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
  368. }
  369. }