Evaluation module page construction

dev
wenlei 11 months ago
parent d14bb84a28
commit acf994d619

@ -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 = "<group>"; };
77165D732B464493002AE0A5 /* BarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonItem.swift; sourceTree = "<group>"; };
7736FF432B4CECF2008D5DAD /* CommentViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewModel.swift; sourceTree = "<group>"; };
7736FF452B4CF0E6008D5DAD /* CommentDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentDetailViewController.swift; sourceTree = "<group>"; };
7743999D2AFA18C3006F8EEA /* PlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerViewController.swift; sourceTree = "<group>"; };
7743999F2AFA1968006F8EEA /* PlayerTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerTabBar.swift; sourceTree = "<group>"; };
774399A52AFE036A006F8EEA /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = "<group>"; };
@ -238,6 +245,7 @@
7751D3812B45324300F1F2BD /* IndieMusic-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "IndieMusic-Bridging-Header.h"; sourceTree = "<group>"; };
7751D3852B45409000F1F2BD /* NSNotification+IndieMusic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSNotification+IndieMusic.swift"; sourceTree = "<group>"; };
7751D3872B45584000F1F2BD /* LaunchADManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchADManager.swift; sourceTree = "<group>"; };
778638932B4D123D00B00AF9 /* CommentDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentDetailViewModel.swift; sourceTree = "<group>"; };
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 = "<group>"; };
778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -321,6 +329,8 @@
77C9B9E82B4BE04C0006C83F /* CommentListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentListViewController.swift; sourceTree = "<group>"; };
77C9B9EA2B4BE7E50006C83F /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = "<group>"; };
77C9B9EC2B4BEA610006C83F /* CommentListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentListViewModel.swift; sourceTree = "<group>"; };
77C9B9EE2B4C2A910006C83F /* AudioTrackListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioTrackListViewController.swift; sourceTree = "<group>"; };
77C9B9F02B4C2B3A0006C83F /* AudioTrackListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioTrackListViewModel.swift; sourceTree = "<group>"; };
77FA0B272B0B3E1E00404C5E /* Journal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Journal.swift; sourceTree = "<group>"; };
77FA0B292B0B5F0D00404C5E /* AudioMoreActionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMoreActionView.swift; sourceTree = "<group>"; };
77FA0B2B2B0C480B00404C5E /* AudioMoreActionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioMoreActionViewModel.swift; sourceTree = "<group>"; };
@ -399,6 +409,8 @@
7743999F2AFA1968006F8EEA /* PlayerTabBar.swift */,
774399A52AFE036A006F8EEA /* PlayerView.swift */,
774A17F22B0459C900F56DF1 /* PlayerViewModel.swift */,
77C9B9EE2B4C2A910006C83F /* AudioTrackListViewController.swift */,
77C9B9F02B4C2B3A0006C83F /* AudioTrackListViewModel.swift */,
);
path = Player;
sourceTree = "<group>";
@ -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 = "<group>";
@ -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 */,

@ -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()

@ -11,6 +11,8 @@ import RxDataSources
struct AudioMoreAction: Codable {
let icon: String
let title: String
let detail: String
}
struct AudioMoreActionSection {

@ -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

@ -12,7 +12,6 @@ struct Setting: Codable {
let title: String
let detail: String
let arrowIcon: String
}
enum SettingType {

@ -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)

@ -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])

@ -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<CommentSection> {
return RxTableViewSectionedReloadDataSource<CommentSection>(
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)
}
}
}

@ -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<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[CommentSection]>
let itemSelected: PublishSubject<Comment>
}
let items = BehaviorRelay<[CommentSection]>.init(value: [])
let itemSelected = PublishSubject<Comment>()
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)
}
}

@ -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)
}
}
}

@ -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<CommentSection> {
return RxTableViewSectionedReloadDataSource<CommentSection>(
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
}
}
)
}
}

@ -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<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[CommentSection]>
let itemSelected: PublishSubject<Comment>
}
let items = BehaviorRelay<[CommentSection]>.init(value: [])
let itemSelected = PublishSubject<Comment>()
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)
}
}

@ -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))
// }
}
}

@ -73,13 +73,13 @@ class CommentListViewController: TableViewController {
extension CommentListViewController {
//TODO
static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, Like) -> Void) -> RxTableViewSectionedReloadDataSource<CommentSection> {
return RxTableViewSectionedReloadDataSource<CommentSection>(
static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, Like) -> Void) -> RxTableViewSectionedReloadDataSource<CommentListSection> {
return RxTableViewSectionedReloadDataSource<CommentListSection>(
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)"
}
}

@ -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)
}

@ -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<JournalSection> {
return RxTableViewSectionedReloadDataSource<JournalSection>(
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
}
)
}
}

@ -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<Bool>
let selection: Driver<IndexPath>
}
struct Output {
let items: BehaviorRelay<[JournalSection]>
let itemSelected: PublishSubject<MusicStyle>
}
let items = BehaviorRelay<[JournalSection]>.init(value: [])
let itemSelected = PublishSubject<MusicStyle>()
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)
}
}

@ -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'

Loading…
Cancel
Save