From acf994d6192aa6bb9f0d4d9a770ee1adfcd54f6c Mon Sep 17 00:00:00 2001 From: wenlei Date: Tue, 9 Jan 2024 19:52:33 +0800 Subject: [PATCH] Evaluation module page construction --- .../IndieMusic.xcodeproj/project.pbxproj | 20 ++ .../IndieMusic/Application/Navigator.swift | 9 + .../IndieMusic/Models/AudioMoreAction.swift | 2 + IndieMusic/IndieMusic/Models/Comment.swift | 48 +++- IndieMusic/IndieMusic/Models/Setting.swift | 1 - .../JournalDetail/AudioMoreActionView.swift | 9 + .../AudioMoreActionViewModel.swift | 10 +- .../CommentDetailViewController.swift | 168 +++++++++++++ .../CommentDetailViewModel.swift | 60 +++++ .../Modules/JournalDetail/CommentView.swift | 135 +++++----- .../JournalDetail/CommentViewController.swift | 61 ++++- .../JournalDetail/CommentViewModel.swift | 60 +++++ .../JournalDetail/ShareActionView.swift | 232 ++++++++++++++++++ .../Personal/CommentListViewController.swift | 22 +- .../Personal/CommentListViewModel.swift | 8 +- .../Player/AudioTrackListViewController.swift | 87 +++++++ .../Player/AudioTrackListViewModel.swift | 57 +++++ IndieMusic/Podfile | 1 + 18 files changed, 899 insertions(+), 91 deletions(-) create mode 100644 IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewModel.swift create mode 100644 IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift create mode 100644 IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift create mode 100644 IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift diff --git a/IndieMusic/IndieMusic.xcodeproj/project.pbxproj b/IndieMusic/IndieMusic.xcodeproj/project.pbxproj index cf111e3..0928d67 100644 --- a/IndieMusic/IndieMusic.xcodeproj/project.pbxproj +++ b/IndieMusic/IndieMusic.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 3C955224FAC6473657A027C3 /* Pods_IndieMusicTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42CE866330C1741ADEC950B2 /* Pods_IndieMusicTests.framework */; }; 49330FC1492387B5155757F6 /* Pods_IndieMusic_IndieMusicUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA03C869C12FEE5FB3D835C2 /* Pods_IndieMusic_IndieMusicUITests.framework */; }; 77165D742B464493002AE0A5 /* BarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77165D732B464493002AE0A5 /* BarButtonItem.swift */; }; + 7736FF442B4CECF2008D5DAD /* CommentViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7736FF432B4CECF2008D5DAD /* CommentViewModel.swift */; }; + 7736FF462B4CF0E6008D5DAD /* CommentDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7736FF452B4CF0E6008D5DAD /* CommentDetailViewController.swift */; }; 7743999E2AFA18C3006F8EEA /* PlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7743999D2AFA18C3006F8EEA /* PlayerViewController.swift */; }; 774399A02AFA1968006F8EEA /* PlayerTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7743999F2AFA1968006F8EEA /* PlayerTabBar.swift */; }; 774399A62AFE036A006F8EEA /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774399A52AFE036A006F8EEA /* PlayerView.swift */; }; @@ -52,6 +54,7 @@ 7751D3802B45271600F1F2BD /* BindPhoneViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D37F2B45271600F1F2BD /* BindPhoneViewModel.swift */; }; 7751D3862B45409000F1F2BD /* NSNotification+IndieMusic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3852B45409000F1F2BD /* NSNotification+IndieMusic.swift */; }; 7751D3882B45584000F1F2BD /* LaunchADManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7751D3872B45584000F1F2BD /* LaunchADManager.swift */; }; + 778638942B4D123D00B00AF9 /* CommentDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778638932B4D123D00B00AF9 /* CommentDetailViewModel.swift */; }; 778B8A212AF8E36D0034AFD4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778B8A202AF8E36D0034AFD4 /* AppDelegate.swift */; }; 778B8A232AF8E36D0034AFD4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */; }; 778B8A282AF8E36D0034AFD4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 778B8A262AF8E36D0034AFD4 /* Main.storyboard */; }; @@ -131,6 +134,8 @@ 77C9B9E92B4BE04C0006C83F /* CommentListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C9B9E82B4BE04C0006C83F /* CommentListViewController.swift */; }; 77C9B9EB2B4BE7E50006C83F /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C9B9EA2B4BE7E50006C83F /* Comment.swift */; }; 77C9B9ED2B4BEA610006C83F /* CommentListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C9B9EC2B4BEA610006C83F /* CommentListViewModel.swift */; }; + 77C9B9EF2B4C2A910006C83F /* AudioTrackListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C9B9EE2B4C2A910006C83F /* AudioTrackListViewController.swift */; }; + 77C9B9F12B4C2B3A0006C83F /* AudioTrackListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77C9B9F02B4C2B3A0006C83F /* AudioTrackListViewModel.swift */; }; 77FA0B282B0B3E1E00404C5E /* Journal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B272B0B3E1E00404C5E /* Journal.swift */; }; 77FA0B2A2B0B5F0D00404C5E /* AudioMoreActionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B292B0B5F0D00404C5E /* AudioMoreActionView.swift */; }; 77FA0B2C2B0C480B00404C5E /* AudioMoreActionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FA0B2B2B0C480B00404C5E /* AudioMoreActionViewModel.swift */; }; @@ -195,6 +200,8 @@ 42CE866330C1741ADEC950B2 /* Pods_IndieMusicTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_IndieMusicTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 69F724137B8F9C1F7E51080D /* Pods-IndieMusicTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-IndieMusicTests.release.xcconfig"; path = "Target Support Files/Pods-IndieMusicTests/Pods-IndieMusicTests.release.xcconfig"; sourceTree = ""; }; 77165D732B464493002AE0A5 /* BarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonItem.swift; sourceTree = ""; }; + 7736FF432B4CECF2008D5DAD /* CommentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewModel.swift; sourceTree = ""; }; + 7736FF452B4CF0E6008D5DAD /* CommentDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentDetailViewController.swift; sourceTree = ""; }; 7743999D2AFA18C3006F8EEA /* PlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = ""; }; 7743999F2AFA1968006F8EEA /* PlayerTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerTabBar.swift; sourceTree = ""; }; 774399A52AFE036A006F8EEA /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = ""; }; @@ -238,6 +245,7 @@ 7751D3812B45324300F1F2BD /* IndieMusic-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IndieMusic-Bridging-Header.h"; sourceTree = ""; }; 7751D3852B45409000F1F2BD /* NSNotification+IndieMusic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSNotification+IndieMusic.swift"; sourceTree = ""; }; 7751D3872B45584000F1F2BD /* LaunchADManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchADManager.swift; sourceTree = ""; }; + 778638932B4D123D00B00AF9 /* CommentDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentDetailViewModel.swift; sourceTree = ""; }; 778B8A1D2AF8E36D0034AFD4 /* IndieMusic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IndieMusic.app; sourceTree = BUILT_PRODUCTS_DIR; }; 778B8A202AF8E36D0034AFD4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -321,6 +329,8 @@ 77C9B9E82B4BE04C0006C83F /* CommentListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentListViewController.swift; sourceTree = ""; }; 77C9B9EA2B4BE7E50006C83F /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; 77C9B9EC2B4BEA610006C83F /* CommentListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentListViewModel.swift; sourceTree = ""; }; + 77C9B9EE2B4C2A910006C83F /* AudioTrackListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioTrackListViewController.swift; sourceTree = ""; }; + 77C9B9F02B4C2B3A0006C83F /* AudioTrackListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioTrackListViewModel.swift; sourceTree = ""; }; 77FA0B272B0B3E1E00404C5E /* Journal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Journal.swift; sourceTree = ""; }; 77FA0B292B0B5F0D00404C5E /* AudioMoreActionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMoreActionView.swift; sourceTree = ""; }; 77FA0B2B2B0C480B00404C5E /* AudioMoreActionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMoreActionViewModel.swift; sourceTree = ""; }; @@ -399,6 +409,8 @@ 7743999F2AFA1968006F8EEA /* PlayerTabBar.swift */, 774399A52AFE036A006F8EEA /* PlayerView.swift */, 774A17F22B0459C900F56DF1 /* PlayerViewModel.swift */, + 77C9B9EE2B4C2A910006C83F /* AudioTrackListViewController.swift */, + 77C9B9F02B4C2B3A0006C83F /* AudioTrackListViewModel.swift */, ); path = Player; sourceTree = ""; @@ -417,6 +429,9 @@ 77FA0B312B0C4E8E00404C5E /* ShareActionView.swift */, 77FA0B592B147EC900404C5E /* CommentViewController.swift */, 77FA0B5B2B147EE800404C5E /* CommentView.swift */, + 7736FF432B4CECF2008D5DAD /* CommentViewModel.swift */, + 7736FF452B4CF0E6008D5DAD /* CommentDetailViewController.swift */, + 778638932B4D123D00B00AF9 /* CommentDetailViewModel.swift */, ); path = JournalDetail; sourceTree = ""; @@ -1108,6 +1123,7 @@ 77C9B9E32B4BDAFA0006C83F /* LikeListViewModel.swift in Sources */, 778B8AAD2AF8ED0E0034AFD4 /* RxMJRefresh.swift in Sources */, 7751D3742B43C9FA00F1F2BD /* MusicStyleViewController.swift in Sources */, + 7736FF462B4CF0E6008D5DAD /* CommentDetailViewController.swift in Sources */, 778B8A922AF8ECF20034AFD4 /* AudioTrack.swift in Sources */, 77C9B9D32B4B9B180006C83F /* BorderLabel.swift in Sources */, 77C9B9E92B4BE04C0006C83F /* CommentListViewController.swift in Sources */, @@ -1124,6 +1140,7 @@ 7751D37E2B451EA800F1F2BD /* UserDefaultKeys.swift in Sources */, 778B8A8E2AF8ECF20034AFD4 /* Artist.swift in Sources */, 774A17F32B0459C900F56DF1 /* PlayerViewModel.swift in Sources */, + 77C9B9EF2B4C2A910006C83F /* AudioTrackListViewController.swift in Sources */, 77FB7A782B4A4B6400B64030 /* MineJournalViewModel.swift in Sources */, 778B8A6D2AF8ECD30034AFD4 /* Observable+Operators.swift in Sources */, 77FA0B542B0F447400404C5E /* Mine.swift in Sources */, @@ -1155,12 +1172,15 @@ 7751D3582B42B5A200F1F2BD /* EditInfoViewController.swift in Sources */, 774A180B2B06F8B900F56DF1 /* JournalDetailController.swift in Sources */, 7751D3522B42AC2B00F1F2BD /* SettingView.swift in Sources */, + 77C9B9F12B4C2B3A0006C83F /* AudioTrackListViewModel.swift in Sources */, + 778638942B4D123D00B00AF9 /* CommentDetailViewModel.swift in Sources */, 77C9B9BE2B4AB4FA0006C83F /* TimingViewModel.swift in Sources */, 77FA0B362B0C50D800404C5E /* Share.swift in Sources */, 778B8A622AF8ECC20034AFD4 /* ErrorTracker.swift in Sources */, 774A18102B070A6900F56DF1 /* SongViewCell.swift in Sources */, 7751D3762B43E8D200F1F2BD /* MusicStyle.swift in Sources */, 77C9B9D72B4BBD780006C83F /* FollowingViewModel.swift in Sources */, + 7736FF442B4CECF2008D5DAD /* CommentViewModel.swift in Sources */, 778B8AA92AF8ED0E0034AFD4 /* UIImage+IndieMusic.swift in Sources */, 77C9B9D12B4B99600006C83F /* BadgeButton.swift in Sources */, 778B8A7F2AF8ECE50034AFD4 /* MineViewModel.swift in Sources */, diff --git a/IndieMusic/IndieMusic/Application/Navigator.swift b/IndieMusic/IndieMusic/Application/Navigator.swift index 2a2425b..ddba5e1 100644 --- a/IndieMusic/IndieMusic/Application/Navigator.swift +++ b/IndieMusic/IndieMusic/Application/Navigator.swift @@ -45,8 +45,11 @@ class Navigator { case followers(viewModel: FollowersViewModel) case likeList(viewModel: LikeListViewModel) case commentList(viewModel: CommentListViewModel) + case comment(viewModel: CommentViewModel) + case commentDetail(viewModel: CommentViewModel) case searchResults(viewModel: SearchResultsViewModel) + case audioTrackList(viewModel: AudioTrackListViewModel) case photoConfirm case alert case test @@ -133,6 +136,12 @@ class Navigator { return LikeListViewController.init(viewModel: viewModel, navigator: self) case .commentList(viewModel: let viewModel): return CommentListViewController.init(viewModel: viewModel, navigator: self) + case .comment(viewModel: let viewModel): + return CommentViewController.init(viewModel: viewModel, navigator: self) + case .commentDetail(viewModel: let viewModel): + return CommentDetailViewController.init(viewModel: viewModel, navigator: self) + case .audioTrackList(viewModel: let viewModel): + return AudioTrackListViewController.init(viewModel: viewModel, navigator: self) case .photoConfirm: return PhotoConfirmViewController.init() diff --git a/IndieMusic/IndieMusic/Models/AudioMoreAction.swift b/IndieMusic/IndieMusic/Models/AudioMoreAction.swift index 802c48e..bc0cb36 100644 --- a/IndieMusic/IndieMusic/Models/AudioMoreAction.swift +++ b/IndieMusic/IndieMusic/Models/AudioMoreAction.swift @@ -11,6 +11,8 @@ import RxDataSources struct AudioMoreAction: Codable { let icon: String let title: String + let detail: String + } struct AudioMoreActionSection { diff --git a/IndieMusic/IndieMusic/Models/Comment.swift b/IndieMusic/IndieMusic/Models/Comment.swift index 9123ff2..b388b6e 100644 --- a/IndieMusic/IndieMusic/Models/Comment.swift +++ b/IndieMusic/IndieMusic/Models/Comment.swift @@ -8,7 +8,7 @@ import Foundation import RxDataSources -struct Comment { +struct CommentList { let avator: String let audioTrackImage: String let name: String @@ -18,12 +18,54 @@ struct Comment { } +struct CommentListSection { + var items: [CommentList] +} + +extension CommentListSection: SectionModelType { + typealias Item = CommentList + + init(original: CommentListSection, items: [Item]) { + self = original + self.items = items + } +} + + + + + +enum CommentType { + case comment(Comment) + case quote(CommentQuote) +} + + +struct Comment { + let avatore: String + let name: String + let date: Int + let isLike: Bool + let comment: String + let commentQuotes: [CommentQuote] + +} + +struct CommentQuote { + let avatore: String + let name: String + let comment: String + let haveMore: Bool +} + + struct CommentSection { - var items: [Comment] + var items: [CommentType] + } extension CommentSection: SectionModelType { - typealias Item = Comment + typealias Item = CommentType init(original: CommentSection, items: [Item]) { self = original diff --git a/IndieMusic/IndieMusic/Models/Setting.swift b/IndieMusic/IndieMusic/Models/Setting.swift index cde9976..5c44934 100644 --- a/IndieMusic/IndieMusic/Models/Setting.swift +++ b/IndieMusic/IndieMusic/Models/Setting.swift @@ -12,7 +12,6 @@ struct Setting: Codable { let title: String let detail: String let arrowIcon: String - } enum SettingType { diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionView.swift index 9f6d8ac..74bd1cd 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionView.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionView.swift @@ -155,6 +155,14 @@ class AudioMoreActionViewCell: UITableViewCell { return titleLabel }() + var detailLabel: UILabel = { + let detailLabel = UILabel.init() + detailLabel.font = UIFont.systemFont(ofSize: 15) + detailLabel.textColor = .tertiaryText() + + return detailLabel + }() + var audioMoreAction: AudioMoreAction? { didSet { @@ -180,6 +188,7 @@ class AudioMoreActionViewCell: UITableViewCell { func makeUI() { contentView.addSubview(iconView) contentView.addSubview(titleLabel) + contentView.addSubview(detailLabel) iconView.snp.makeConstraints { make in make.left.equalTo(contentView).offset(24) diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift index f4ca00f..6836754 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift @@ -35,9 +35,13 @@ class AudioMoreActionViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - let share = AudioMoreAction.init(icon: "audio_share_btn", title: "分享") - let like = AudioMoreAction.init(icon: "audio_like_off", title: "收藏") - let download = AudioMoreAction.init(icon: "audio_download_btn", title: "下载") + let share = AudioMoreAction.init(icon: "audio_share_btn", title: "分享", detail: "") + let like = AudioMoreAction.init(icon: "audio_like_off", title: "收藏", detail: "") + + + let timing = AudioMoreAction.init(icon: "audio_download_btn", title: "定时关闭", detail: "") + + let download = AudioMoreAction.init(icon: "audio_download_btn", title: "下载", detail: "") let selection = AudioMoreActionSection.init(items: [share, like, download]) items.accept([selection]) diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewController.swift new file mode 100644 index 0000000..5972a77 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewController.swift @@ -0,0 +1,168 @@ +// +// CommentDetailViewController.swift +// IndieMusic +// +// Created by WenLei on 2024/1/9. +// + +import UIKit +import RxSwift +import RxCocoa +import RxDataSources + +class CommentDetailViewController: TableViewController { + + + override func viewDidLoad() { + super.viewDidLoad() + + tableView.register(CommentViewCell.self, forCellReuseIdentifier: "CommentViewCell") + + } + + + override func makeUI() { + super.makeUI() + + view.addSubview(tableView) + } + + override func bindViewModel() { + super.bindViewModel() + + guard let viewModel = viewModel as? CommentViewModel else { return } + + let input = CommentViewModel.Input.init(viewWillAppear: rx.viewWillAppear, + selection: tableView.rx.itemSelected.asDriver()) + let output = viewModel.transform(input: input) + + let dataSource = CommentDetailViewController.dataSource() + + output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) + + + + + output.itemSelected.subscribe { sectionItem in + + }.disposed(by: rx.disposeBag) + + + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + + + } + +} + +extension CommentDetailViewController { + static func dataSource() -> RxTableViewSectionedReloadDataSource { + return RxTableViewSectionedReloadDataSource( + configureCell: { dataSource, tableView, indexPath, item in + + switch item { + case .comment(let comment): + let cell: CommentViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentViewCell", for: indexPath) as! CommentViewCell + +// cell.setting = item.setting + + return cell + + + case .quote(let commentQuote): + let cell: CommentQuoteViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentQuoteViewCell", for: indexPath) as! CommentQuoteViewCell + +// cell.setting = item.setting + + return cell + } + + + + } + ) + } +} + + + +class CommentDetailHeaderView: UIView { + let avatorView: UIImageView = { + let avatorView = UIImageView.init() + + return avatorView + }() + + let nameLabel: UILabel = { + let nameLabel = UILabel.init() + nameLabel.font = UIFont.systemFont(ofSize: 14, weight: .medium) + nameLabel.textColor = .tertiaryText() + return nameLabel + }() + + let commentLabel: UILabel = { + let commentLabel = UILabel.init() + commentLabel.textColor = .primaryText() + commentLabel.font = UIFont.systemFont(ofSize: 14) + + return commentLabel + }() + + let lineView: UIView = { + let lineView = UIView.init() + lineView.backgroundColor = .init(hex: 0xF2F3F7) + + return lineView + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + + makeUI() + } + + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func makeUI() { + addSubview(avatorView) + addSubview(nameLabel) + addSubview(commentLabel) + addSubview(lineView) + + + avatorView.snp.makeConstraints { make in + make.left.equalTo(self).offset(18) + make.size.equalTo(CGSize.init(width: 40, height: 40)) + make.centerY.equalTo(self) + } + + nameLabel.snp.makeConstraints { make in + make.left.equalTo(avatorView.snp.right).offset(14) + make.top.equalTo(avatorView).offset(0) + make.right.equalTo(self).offset(-18) + } + + commentLabel.snp.makeConstraints { make in + make.left.equalTo(avatorView.snp.right).offset(14) + make.top.equalTo(nameLabel.snp.bottom).offset(3) + make.right.equalTo(self).offset(-18) + } + + lineView.snp.makeConstraints { make in + make.top.equalTo(commentLabel.snp.bottom).offset(18) + make.height.equalTo(1) + make.bottom.equalTo(self).offset(0) + make.left.equalTo(self).offset(18) + make.right.equalTo(self).offset(-18) + } + } + +} diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewModel.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewModel.swift new file mode 100644 index 0000000..bcd0a09 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentDetailViewModel.swift @@ -0,0 +1,60 @@ +// +// CommentDetailViewModel.swift +// IndieMusic +// +// Created by WenLei on 2024/1/9. +// + +import Foundation +import RxSwift +import RxCocoa + + +class CommentDetailViewModel: ViewModel, ViewModelType { + + struct Input { + let viewWillAppear: ControlEvent + let selection: Driver + } + + struct Output { + let items: BehaviorRelay<[CommentSection]> + + let itemSelected: PublishSubject + } + + + let items = BehaviorRelay<[CommentSection]>.init(value: []) + let itemSelected = PublishSubject() + + + func transform(input: Input) -> Output { + + + let commentQuote = CommentQuote.init(avatore: "", name: "1233", comment: "dfdsadsdads", haveMore: false) + + + + let comment = Comment.init(avatore: "", name: "nike", date: 10000, isLike: false, comment: "test", commentQuotes: [commentQuote, commentQuote]) + + + let journalSection = CommentSection.init(items: [.comment(comment)]) + + items.accept([journalSection]) + + + + + input.selection.drive { indexPath in + guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return } + +// self.itemSelected.onNext(sectionItem) + }.disposed(by: rx.disposeBag) + + + + return Output.init(items: items, + itemSelected: itemSelected) + } + +} diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift index 9469018..f888bc5 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift @@ -6,6 +6,7 @@ // import UIKit +import AttributedString class CommentHeaderView: UIView { var titleLabel: UILabel = { @@ -86,6 +87,8 @@ class CommentHeaderView: UIView { class CommentViewCell: UITableViewCell { var avatarView: UIImageView = { let avatarView = UIImageView.init() + avatarView.layer.cornerRadius = 20 + avatarView.layer.masksToBounds = true return avatarView }() @@ -93,56 +96,38 @@ class CommentViewCell: UITableViewCell { var nameLabel: UILabel = { let nameLabel = UILabel.init() + nameLabel.font = UIFont.systemFont(ofSize: 14, weight: .medium) return nameLabel }() var dateLabel: UILabel = { let dateLabel = UILabel.init() + dateLabel.font = UIFont.systemFont(ofSize: 10) + dateLabel.textColor = .tertiaryText() return dateLabel }() - var likeButton: UIButton = { - let likeButton = UIButton.init() - + var likeButton: LayoutableButton = { + let likeButton = LayoutableButton.init() + likeButton.imageHorizontalAlignment = .right + likeButton.setImage(UIImage.init(named: ""), for: .normal) + likeButton.setImage(UIImage.init(named: ""), for: .selected) + return likeButton }() var commentLabel: UILabel = { let commentLabel = UILabel.init() + commentLabel.font = UIFont.systemFont(ofSize: 14) + commentLabel.textColor = .primaryText() return commentLabel }() - var subCommentView: UIView = { - let subCommentView = UIView.init() - - return subCommentView - }() - - - var subAvatarView: UIImageView = { - let subAvatarView = UIImageView.init() - - return subAvatarView - }() - - var subCommentLabel: UILabel = { - let subCommentLabel = UILabel.init() - - return subCommentLabel - }() - - var moreButton: UIButton = { - let moreButton = UIButton.init() - - return moreButton - }() - - override func awakeFromNib() { @@ -175,10 +160,6 @@ class CommentViewCell: UITableViewCell { contentView.addSubview(likeButton) contentView.addSubview(commentLabel) - contentView.addSubview(subCommentView) - subCommentView.addSubview(subAvatarView) - subCommentView.addSubview(subCommentLabel) - subCommentView.addSubview(moreButton) } @@ -192,16 +173,15 @@ class CommentViewCell: UITableViewCell { make.size.equalTo(CGSize.init(width: 40, height: 40)) } - moreButton.snp.makeConstraints { make in - make.right.equalTo(contentView).offset(18) - make.centerY.equalTo(avatarView) + likeButton.snp.makeConstraints { make in + make.right.equalTo(contentView).offset(-18) + make.top.equalTo(contentView).offset(12) } - nameLabel.snp.makeConstraints { make in make.top.equalTo(avatarView) make.left.equalTo(avatarView.snp.right).offset(14) - make.right.equalTo(moreButton.snp.left).offset(-10) + make.right.equalTo(likeButton.snp.left).offset(-14) } dateLabel.snp.makeConstraints { make in @@ -213,36 +193,75 @@ class CommentViewCell: UITableViewCell { make.left.equalTo(avatarView.snp.right).offset(14) make.right.equalTo(contentView).offset(-18) make.top.equalTo(dateLabel.snp.bottom).offset(10) + make.bottom.equalTo(contentView).offset(0) } - subCommentView.snp.makeConstraints { make in - make.left.equalTo(avatarView.snp.right).offset(14) - make.right.equalTo(contentView).offset(-18) - make.top.equalTo(commentLabel.snp.bottom).offset(15) - make.bottom.equalTo(contentView).offset(-12) - } + } + +} + + +class CommentQuoteViewCell: UITableViewCell { + let avatarView: UIImageView = { + let avatarView = UIImageView.init() + avatarView.layer.cornerRadius = 10 + avatarView.layer.masksToBounds = true + + return avatarView + }() + + let commentLabel: UILabel = { + let commentLabel = UILabel.init() + + return commentLabel + }() + + let moreButton: UIButton = { + let moreButton = UIButton.init() + moreButton.setTitle("更多回复", for: .normal) + moreButton.titleLabel?.font = UIFont.systemFont(ofSize: 14) + moreButton.setTitleColor(.primary(), for: .normal) + + return moreButton + }() + + + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none - subAvatarView.snp.makeConstraints { make in - make.left.equalTo(subCommentView) - make.top.equalTo(subCommentView) + makeUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func makeUI() { + contentView.addSubview(avatarView) + contentView.addSubview(commentLabel) + contentView.addSubview(moreButton) + + avatarView.snp.makeConstraints { make in + make.left.equalTo(contentView).offset(72) + make.top.equalTo(contentView) make.size.equalTo(CGSize.init(width: 20, height: 20)) } - subCommentLabel.snp.makeConstraints { make in - make.left.equalTo(subAvatarView.snp.right).offset(5) - make.right.equalTo(subCommentView) - make.top.equalTo(subCommentView) + commentLabel.snp.makeConstraints { make in + make.left.equalTo(avatarView.snp.right).offset(5) + make.top.equalTo(avatarView) + make.right.equalTo(contentView).offset(-18) } moreButton.snp.makeConstraints { make in - make.top.equalTo(subCommentLabel.snp.bottom).offset(12) - make.bottom.equalTo(subCommentView) - make.left.equalTo(subCommentView) + make.left.equalTo(avatarView.snp.right).offset(5) + make.top.equalTo(commentLabel.snp.bottom).offset(12) + make.bottom.equalTo(contentView).offset(0) } - } - + + } - - diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift index 8d3ae68..6061410 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift @@ -10,20 +10,15 @@ import RxSwift import RxCocoa import RxDataSources -class CommentViewController: ViewController { - var tableView: UITableView = { - let tableView = UITableView.init() - - - return tableView - }() - +class CommentViewController: TableViewController { override func viewDidLoad() { super.viewDidLoad() + tableView.register(CommentViewCell.self, forCellReuseIdentifier: "CommentViewCell") + tableView.register(CommentQuoteViewCell.self, forCellReuseIdentifier: "CommentQuoteViewCell") } @@ -37,17 +32,61 @@ class CommentViewController: ViewController { override func bindViewModel() { super.bindViewModel() + guard let viewModel = viewModel as? CommentViewModel else { return } + + let input = CommentViewModel.Input.init(viewWillAppear: rx.viewWillAppear, + selection: tableView.rx.itemSelected.asDriver()) + let output = viewModel.transform(input: input) + + let dataSource = CommentViewController.dataSource() + + output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) + + + + output.itemSelected.subscribe { sectionItem in + + }.disposed(by: rx.disposeBag) + + } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - tableView.snp.makeConstraints { make in - make.edges.equalTo(view) - } + } } + +extension CommentViewController { + static func dataSource() -> RxTableViewSectionedReloadDataSource { + return RxTableViewSectionedReloadDataSource( + configureCell: { dataSource, tableView, indexPath, item in + + switch item { + case .comment(let comment): + let cell: CommentViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentViewCell", for: indexPath) as! CommentViewCell + +// cell.setting = item.setting + + return cell + + + case .quote(let commentQuote): + let cell: CommentQuoteViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentQuoteViewCell", for: indexPath) as! CommentQuoteViewCell + +// cell.setting = item.setting + + return cell + } + + + + } + ) + } +} diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift new file mode 100644 index 0000000..f89a865 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift @@ -0,0 +1,60 @@ +// +// CommentViewModel.swift +// IndieMusic +// +// Created by WenLei on 2024/1/9. +// + +import Foundation +import RxSwift +import RxCocoa + + +class CommentViewModel: ViewModel, ViewModelType { + + struct Input { + let viewWillAppear: ControlEvent + let selection: Driver + } + + struct Output { + let items: BehaviorRelay<[CommentSection]> + + let itemSelected: PublishSubject + } + + + let items = BehaviorRelay<[CommentSection]>.init(value: []) + let itemSelected = PublishSubject() + + + func transform(input: Input) -> Output { + + + let commentQuote = CommentQuote.init(avatore: "", name: "1233", comment: "dfdsadsdads", haveMore: false) + + + + let comment = Comment.init(avatore: "", name: "nike", date: 10000, isLike: false, comment: "test", commentQuotes: [commentQuote, commentQuote]) + + + let journalSection = CommentSection.init(items: [.comment(comment)]) + + items.accept([journalSection]) + + + + + input.selection.drive { indexPath in + guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return } + +// self.itemSelected.onNext(sectionItem) + }.disposed(by: rx.disposeBag) + + + + return Output.init(items: items, + itemSelected: itemSelected) + } + +} diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/ShareActionView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/ShareActionView.swift index c677968..b441787 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/ShareActionView.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/ShareActionView.swift @@ -54,3 +54,235 @@ class ShareActionViewCell: UICollectionViewCell { } } + + + +class ShareSingleView: UIView { + let containerView: UIView = { + let containerView = UIView.init() + containerView.backgroundColor = .white + containerView.layer.cornerRadius = 3 + + return containerView + }() + + + let coverView: UIImageView = { + let coverView = UIImageView.init() + coverView.layer.cornerRadius = 3 + + return coverView + }() + + let audioTrackLabel: UILabel = { + let audioTrackLabel = UILabel.init() + + return audioTrackLabel + }() + + let authorLabel: UILabel = { + let authorLabel = UILabel.init() + + return authorLabel + }() + + let logoView: UIImageView = { + let logoView = UIImageView.init() + + return logoView + }() + + let qrCodeView: UIImageView = { + let qrCodeView = UIImageView.init() + + return qrCodeView + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + + makeUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func makeUI() { + addSubview(containerView) + addSubview(coverView) + addSubview(audioTrackLabel) + addSubview(authorLabel) + addSubview(logoView) + addSubview(qrCodeView) + + } + + + override func layoutSubviews() { + super.layoutSubviews() + + containerView.snp.makeConstraints { make in + make.size.equalTo(CGSize.init(width: 327, height: 444)) + make.center.equalTo(self) + } + + coverView.snp.makeConstraints { make in + make.left.equalTo(containerView).offset(30) + make.right.equalTo(containerView).offset(-30) + make.top.equalTo(containerView).offset(30) + make.height.equalTo(coverView.snp.width) + } + + audioTrackLabel.snp.makeConstraints { make in + make.left.equalTo(containerView).offset(30) + make.top.equalTo(coverView.snp.bottom).offset(9) + make.right.equalTo(containerView).offset(-30) + + } + + authorLabel.snp.makeConstraints { make in + make.left.equalTo(containerView).offset(30) + make.top.equalTo(audioTrackLabel.snp.bottom).offset(3) + make.right.equalTo(containerView).offset(-30) + } + + logoView.snp.makeConstraints { make in + make.left.equalTo(containerView).offset(30) + make.bottom.equalTo(containerView).offset(-28) + } + + qrCodeView.snp.makeConstraints { make in + make.right.equalTo(containerView).offset(-30) + make.bottom.equalTo(containerView).offset(-16) + make.size.equalTo(CGSize.init(width: 48, height: 48)) + } + } + +} + + +class ShareJournalView: UIView { + let containerView: UIView = { + let containerView = UIView.init() + containerView.backgroundColor = .white + containerView.layer.cornerRadius = 3 + + return containerView + }() + + + let coverView: UIImageView = { + let coverView = UIImageView.init() + coverView.layer.cornerRadius = 3 + + return coverView + }() + + let homeNumberView: HomeNumberView = { + let homeNumberView = HomeNumberView.init() + + return homeNumberView + }() + + + let titleLabel: UILabel = { + let titleLabel = UILabel.init() + + return titleLabel + }() + + var tagArray: [String] = [] { + didSet { + tagArray.removeAll() + tagsButtonArray.removeAll() + + for tag in tagArray { + let tagButton = UIButton.init() + tagButton.titleLabel?.font = UIFont.systemFont(ofSize: 12) + tagButton.setTitle(tag, for: .normal) + + tagsButtonArray.append(tagButton) + + } + } + } + + var tagsButtonArray = [UIButton]() + + let logoView: UIImageView = { + let logoView = UIImageView.init() + + return logoView + }() + + let qrCodeView: UIImageView = { + let qrCodeView = UIImageView.init() + + return qrCodeView + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + + makeUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func makeUI() { + addSubview(containerView) + addSubview(coverView) + addSubview(titleLabel) + + addSubview(logoView) + addSubview(qrCodeView) + + } + + + override func layoutSubviews() { + super.layoutSubviews() + +// containerView.snp.makeConstraints { make in +// make.size.equalTo(CGSize.init(width: 327, height: 444)) +// make.center.equalTo(self) +// } +// +// coverView.snp.makeConstraints { make in +// make.left.equalTo(containerView).offset(30) +// make.right.equalTo(containerView).offset(-30) +// make.top.equalTo(containerView).offset(30) +// make.height.equalTo(coverView.snp.width) +// } +// +// audioTrackLabel.snp.makeConstraints { make in +// make.left.equalTo(containerView).offset(30) +// make.top.equalTo(coverView.snp.bottom).offset(9) +// make.right.equalTo(containerView).offset(-30) +// +// } +// +// authorLabel.snp.makeConstraints { make in +// make.left.equalTo(containerView).offset(30) +// make.top.equalTo(audioTrackLabel.snp.bottom).offset(3) +// make.right.equalTo(containerView).offset(-30) +// } +// +// logoView.snp.makeConstraints { make in +// make.left.equalTo(containerView).offset(30) +// make.bottom.equalTo(containerView).offset(-28) +// } +// +// qrCodeView.snp.makeConstraints { make in +// make.right.equalTo(containerView).offset(-30) +// make.bottom.equalTo(containerView).offset(-16) +// make.size.equalTo(CGSize.init(width: 48, height: 48)) +// } + } + +} diff --git a/IndieMusic/IndieMusic/Modules/Personal/CommentListViewController.swift b/IndieMusic/IndieMusic/Modules/Personal/CommentListViewController.swift index 698ec3d..9692b3a 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/CommentListViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/CommentListViewController.swift @@ -73,13 +73,13 @@ class CommentListViewController: TableViewController { extension CommentListViewController { //TODO - static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, Like) -> Void) -> RxTableViewSectionedReloadDataSource { - return RxTableViewSectionedReloadDataSource( + static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, Like) -> Void) -> RxTableViewSectionedReloadDataSource { + return RxTableViewSectionedReloadDataSource( configureCell: { dataSource, tableView, indexPath, item in let cell: CommentListViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentListViewCell", for: indexPath) as! CommentListViewCell - cell.comment = item + cell.commentList = item return cell } @@ -174,16 +174,16 @@ class CommentListViewCell: UITableViewCell { var buttonTapCallback: ((Following) -> ())? - var comment: Comment? { + var commentList: CommentList? { didSet { - guard let comment = comment else { return } - avatoreView.kf.setImage(with: URL.init(string: comment.avator)) - audioTrackView.kf.setImage(with: URL.init(string: comment.audioTrackImage)) + guard let commentList = commentList else { return } + avatoreView.kf.setImage(with: URL.init(string: commentList.avator)) + audioTrackView.kf.setImage(with: URL.init(string: commentList.audioTrackImage)) - nameLabel.text = comment.name - dateLabel.text = "\(comment.date)" - commentLabel.text = comment.comment - myCommentLabel.text = "我的评论:\(comment.myComment)" + nameLabel.text = commentList.name + dateLabel.text = "\(commentList.date)" + commentLabel.text = commentList.comment + myCommentLabel.text = "我的评论:\(commentList.myComment)" } } diff --git a/IndieMusic/IndieMusic/Modules/Personal/CommentListViewModel.swift b/IndieMusic/IndieMusic/Modules/Personal/CommentListViewModel.swift index 417d040..d9a4a6f 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/CommentListViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/CommentListViewModel.swift @@ -18,10 +18,10 @@ class CommentListViewModel: ViewModel, ViewModelType { } struct Output { - let items: BehaviorRelay<[CommentSection]> + let items: BehaviorRelay<[CommentListSection]> } - let items = BehaviorRelay<[CommentSection]>.init(value: []) + let items = BehaviorRelay<[CommentListSection]>.init(value: []) func transform(input: Input) -> Output { @@ -29,10 +29,10 @@ class CommentListViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - let name = Comment.init(avator: "", audioTrackImage: "", name: "123", date: 1000, comment: "这就是生活,也是理想,也是你我的未来", myComment: "太多了,还有草东我也很") + let name = CommentList.init(avator: "", audioTrackImage: "", name: "123", date: 1000, comment: "这就是生活,也是理想,也是你我的未来", myComment: "太多了,还有草东我也很") - items.accept([CommentSection.init(items: [name, name, name, name])]) + items.accept([CommentListSection.init(items: [name, name, name, name])]) return Output.init(items: items) } diff --git a/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift new file mode 100644 index 0000000..cddda06 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift @@ -0,0 +1,87 @@ +// +// AudioTrackListViewController.swift +// IndieMusic +// +// Created by WenLei on 2024/1/8. +// + +import UIKit +import RxSwift +import RxCocoa +import RxDataSources + +class AudioTrackListViewController: TableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + + override func makeUI() { + super.makeUI() + + + view.backgroundColor = .white + + tableView.register(SongViewCell.self + , forCellReuseIdentifier: "SongViewCell") + + } + + override func bindViewModel() { + super.bindViewModel() + + guard let viewModel = viewModel as? AudioTrackListViewModel else { return } + + let input = AudioTrackListViewModel.Input.init(viewWillAppear: rx.viewWillAppear, + selection: tableView.rx.itemSelected.asDriver()) + let output = viewModel.transform(input: input) + + let dataSource = AudioTrackListViewController.dataSource { cell, audioTrack in + let audioMoreActionViewModel = AudioMoreActionViewModel.init(provider: viewModel.provider) + + self.navigator.show(segue: .audioMore(viewModel: audioMoreActionViewModel), sender: self, transition: .navigationPresent(type: .audioMore)) + + } + + + + output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) + + + output.itemSelected.subscribe { sectionItem in + + + }.disposed(by: rx.disposeBag) + + + } + + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + } + +} + +extension AudioTrackListViewController { + //TODO + static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, AudioTrack) -> Void) -> RxTableViewSectionedReloadDataSource { + return RxTableViewSectionedReloadDataSource( + configureCell: { dataSource, tableView, indexPath, item in + let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell + + cell.audioTrack = item + + cell.buttonTapCallback = {audioTrack in + buttonTapHandler(cell, audioTrack) + } + + return cell + } + ) + } +} diff --git a/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift new file mode 100644 index 0000000..015183e --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift @@ -0,0 +1,57 @@ +// +// AudioTrackListViewModel.swift +// IndieMusic +// +// Created by WenLei on 2024/1/8. +// + +import Foundation +import RxSwift +import RxCocoa +import RxDataSources + + +class AudioTrackListViewModel: ViewModel, ViewModelType { + + struct Input { + let viewWillAppear: ControlEvent + let selection: Driver + } + + struct Output { + let items: BehaviorRelay<[JournalSection]> + + let itemSelected: PublishSubject + } + + + let items = BehaviorRelay<[JournalSection]>.init(value: []) + let itemSelected = PublishSubject() + + + func transform(input: Input) -> Output { + + + let journalDetail = JournalDetail.init(audio: "", cover: "", title: "", artist: "", number: "", tags: [], date: 0, content: "", isExpand: false) + let item = AudioTrack.init(artists: [], availableMarkets: [""], discNumber: 0, durationMs: 0, explicit: false, externalUrls: ["": ""], id: "", name: "123", previewUrl: "") + + let journalSection = JournalSection.init(items: [item, item, item, item], journalDetail: journalDetail) + + items.accept([journalSection]) + + + + + input.selection.drive { indexPath in + guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return } + +// self.itemSelected.onNext(sectionItem) + }.disposed(by: rx.disposeBag) + + + + return Output.init(items: items, + itemSelected: itemSelected) + } + +} diff --git a/IndieMusic/Podfile b/IndieMusic/Podfile index 0cdc728..e529308 100644 --- a/IndieMusic/Podfile +++ b/IndieMusic/Podfile @@ -21,6 +21,7 @@ target 'IndieMusic' do pod 'XHLaunchAd' pod 'DZNEmptyDataSet' pod 'SVProgressHUD', :git => 'https://github.com/SVProgressHUD/SVProgressHUD.git' + pod 'AttributedString' pod 'NSObject+Rx'