|
|
|
@ -11,19 +11,32 @@ import RxCocoa
|
|
|
|
|
import RxDataSources
|
|
|
|
|
|
|
|
|
|
class PersonalViewController: ViewController {
|
|
|
|
|
let personalHeaderView: PersonalHeaderView = {
|
|
|
|
|
let personalHeaderView = PersonalHeaderView.init()
|
|
|
|
|
|
|
|
|
|
return personalHeaderView
|
|
|
|
|
}()
|
|
|
|
|
var personalHeaderView: PersonalHeaderView?
|
|
|
|
|
|
|
|
|
|
let personalView: PersonalView = {
|
|
|
|
|
let personalView = PersonalView.init()
|
|
|
|
|
personalView.tableView.register(SongViewCell.self, forCellReuseIdentifier: "SongViewCell")
|
|
|
|
|
personalView.collectionView.register(JournalViewCell.self, forCellWithReuseIdentifier: "JournalViewCell")
|
|
|
|
|
lazy var collectionView: UICollectionView = {
|
|
|
|
|
|
|
|
|
|
let layout = UICollectionViewCompositionalLayout { (sectionIndex, environment) -> NSCollectionLayoutSection? in
|
|
|
|
|
let viewModel = self.viewModel as? PersonalViewModel
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return self.createSingleColumnSection()
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let collectionView = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: layout)
|
|
|
|
|
collectionView.register(JournalViewCell.self, forCellWithReuseIdentifier: "JournalViewCell")
|
|
|
|
|
collectionView.register(JournalAudioViewCell.self, forCellWithReuseIdentifier: "JournalAudioViewCell")
|
|
|
|
|
|
|
|
|
|
collectionView.register(PersonalHeaderView.self, forSupplementaryViewOfKind: "UICollectionElementKindSectionHeader", withReuseIdentifier: "PersonalHeaderView")
|
|
|
|
|
|
|
|
|
|
collectionView.backgroundColor = .white
|
|
|
|
|
|
|
|
|
|
return personalView
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return collectionView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let noDataView: MineSingleNoDataView = {
|
|
|
|
|
let noDataView = MineSingleNoDataView.init()
|
|
|
|
@ -32,6 +45,29 @@ class PersonalViewController: ViewController {
|
|
|
|
|
return noDataView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
let personInfoLikeType = BehaviorRelay<PersonInfoLikeType>.init(value: .audio)
|
|
|
|
|
|
|
|
|
|
let headerRefreshTrigger = PublishSubject<Void>()
|
|
|
|
|
let footerRefreshTrigger = PublishSubject<Void>()
|
|
|
|
|
|
|
|
|
|
let isHeaderLoading = BehaviorRelay<(RefreshType, Bool)>.init(value: (.refresh, false))
|
|
|
|
|
let isFooterLoading = BehaviorRelay<(RefreshType, Bool)>.init(value: (.loadMore, false))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
|
|
|
super.viewWillAppear(animated)
|
|
|
|
|
|
|
|
|
|
navBarBgAlpha = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
|
|
|
super.viewWillDisappear(animated)
|
|
|
|
|
navBarBgAlpha = 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
override func viewDidLoad() {
|
|
|
|
|
super.viewDidLoad()
|
|
|
|
|
|
|
|
|
@ -43,81 +79,163 @@ class PersonalViewController: ViewController {
|
|
|
|
|
override func makeUI() {
|
|
|
|
|
super.makeUI()
|
|
|
|
|
|
|
|
|
|
view.addSubview(personalHeaderView)
|
|
|
|
|
view.addSubview(personalView)
|
|
|
|
|
// view.addSubview(personalHeaderView)
|
|
|
|
|
view.addSubview(collectionView)
|
|
|
|
|
view.addSubview(noDataView)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.personalHeaderView.nameLabel.text = "123"
|
|
|
|
|
self.personalHeaderView.ipLabel.text = "IP 南京"
|
|
|
|
|
collectionView.rx.refresh.subscribe { refreshType in
|
|
|
|
|
|
|
|
|
|
switch refreshType.element {
|
|
|
|
|
case .refresh:
|
|
|
|
|
self.headerRefreshTrigger.onNext(())
|
|
|
|
|
case .loadMore where AuthManager.shared.token?.isValid == true:
|
|
|
|
|
self.footerRefreshTrigger.onNext(())
|
|
|
|
|
|
|
|
|
|
default: break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func bindViewModel() {
|
|
|
|
|
super.bindViewModel()
|
|
|
|
|
|
|
|
|
|
self.personalView.currentSearchType = .single
|
|
|
|
|
|
|
|
|
|
guard let viewModel = viewModel as? PersonalViewModel else { return }
|
|
|
|
|
|
|
|
|
|
let input = PersonalViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
|
|
|
|
collectionViewSelection: personalView.collectionView.rx.itemSelected.asDriver(),
|
|
|
|
|
followingControlTrigger: self.personalHeaderView.followersControl.rx.controlEvent(.touchUpInside).asDriver(),
|
|
|
|
|
followersControlTrigger: self.personalHeaderView.followersControl.rx.controlEvent(.touchUpInside).asDriver(),
|
|
|
|
|
likeTrigger: self.personalHeaderView.likeControl.rx.controlEvent(.touchUpInside).asDriver(),
|
|
|
|
|
followingButtonTrigger: self.personalHeaderView.followingButton.rx.controlEvent(.touchUpInside).asDriver(),
|
|
|
|
|
messageTrigger: self.personalHeaderView.messageButton.rx.controlEvent(.touchUpInside).asDriver())
|
|
|
|
|
headerRefresh: headerRefreshTrigger,
|
|
|
|
|
footerRefresh: footerRefreshTrigger,
|
|
|
|
|
personInfoLikeType: personInfoLikeType,
|
|
|
|
|
selection: collectionView.rx.itemSelected.asDriver(),
|
|
|
|
|
followingButtonTrigger: headerRefreshTrigger.asDriver(onErrorJustReturn: ()),
|
|
|
|
|
messageButtonTrigger: headerRefreshTrigger.asDriver(onErrorJustReturn: ())
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let output = viewModel.transform(input: input)
|
|
|
|
|
|
|
|
|
|
let tableViewDataSource = PersonalViewController.tableViewDataSource { [weak self] cell, audioTrack in
|
|
|
|
|
// let audioMoreActionViewModel = AudioMoreActionViewModel.init(audioTrack: audioTrack, provider: viewModel.provider)
|
|
|
|
|
let dataSource = RxCollectionViewSectionedReloadDataSource<PersonInfoSection>(
|
|
|
|
|
configureCell: { dataSource, collectionView, indexPath, item in
|
|
|
|
|
switch dataSource[indexPath] {
|
|
|
|
|
case .audioItem(let audioTrack):
|
|
|
|
|
let cell: JournalAudioViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "JournalAudioViewCell", for: indexPath) as! JournalAudioViewCell
|
|
|
|
|
|
|
|
|
|
cell.audioTrack = audioTrack
|
|
|
|
|
cell.buttonTapCallback = { [weak self] audioTrack in
|
|
|
|
|
let audioMoreActionViewModel = AudioMoreActionViewModel.init(audioTrack: viewModel.needRefresh, provider: viewModel.provider)
|
|
|
|
|
|
|
|
|
|
self?.navigator.show(segue: .audioMore(viewModel: audioMoreActionViewModel), sender: self, transition: .navigationPresent(type: .audioMore))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cell
|
|
|
|
|
case .journaItem(let journalDetail):
|
|
|
|
|
let cell: JournalViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "JournalViewCell", for: indexPath) as! JournalViewCell
|
|
|
|
|
|
|
|
|
|
cell.journal = journalDetail
|
|
|
|
|
|
|
|
|
|
return cell
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
configureSupplementaryView: { [weak self] dataSource, collectionView, kind, indexPath in
|
|
|
|
|
guard kind == UICollectionView.elementKindSectionHeader, let self = self else {
|
|
|
|
|
return UICollectionReusableView()
|
|
|
|
|
}
|
|
|
|
|
let resuableView: PersonalHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: "UICollectionElementKindSectionHeader", withReuseIdentifier: "PersonalHeaderView", for: indexPath) as! PersonalHeaderView
|
|
|
|
|
self.personalHeaderView = resuableView
|
|
|
|
|
|
|
|
|
|
let section = dataSource.sectionModels.first.value
|
|
|
|
|
// resuableView.user = viewModel.us
|
|
|
|
|
|
|
|
|
|
// resuableView.followingControl.rx.controlEvent(.touchUpInside).subscribe { _ in
|
|
|
|
|
// let followingViewModel = FollowingViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self.navigator.show(segue: .following(viewModel: followingViewModel), sender: self)
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
//
|
|
|
|
|
// self?.navigator.show(segue: .audioMore(viewModel: audioMoreActionViewModel), sender: self, transition: .navigationPresent(type: .audioMore))
|
|
|
|
|
// resuableView.followersControl.rx.controlEvent(.touchUpInside).subscribe { _ in
|
|
|
|
|
// let followersViewModel = FollowersViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self.navigator.show(segue: .followers(viewModel: followersViewModel), sender: self)
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
//
|
|
|
|
|
// resuableView.likeControl.rx.controlEvent(.touchUpInside).subscribe { _ in
|
|
|
|
|
// let likeListViewModel = LikeListViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self.navigator.show(segue: .likeList(viewModel: likeListViewModel), sender: self)
|
|
|
|
|
//
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
resuableView.followingButton.rx.tap.subscribe { _ in
|
|
|
|
|
viewModel.followingButtonTrigger.accept(())
|
|
|
|
|
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
resuableView.messageButton.rx.tap.subscribe { _ in
|
|
|
|
|
viewModel.messageButtonTrigger.accept(())
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return resuableView
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
let collectionViewDataSource = SearchResultsController.collectionViewDataSource()
|
|
|
|
|
|
|
|
|
|
output.collectionViewItems.bind(to: personalView.collectionView.rx.items(dataSource: collectionViewDataSource)).disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
output.tableViewItems.bind(to: personalView.tableView.rx.items(dataSource: tableViewDataSource)).disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.personalHeaderView.followingControl.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in
|
|
|
|
|
let followingViewModel = FollowingViewModel.init(provider: viewModel.provider)
|
|
|
|
|
|
|
|
|
|
self?.navigator.show(segue: .following(viewModel: followingViewModel), sender: self)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
output.items.bind(to: collectionView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
self.personalHeaderView.followersControl.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in
|
|
|
|
|
let followersViewModel = FollowersViewModel.init(provider: viewModel.provider)
|
|
|
|
|
|
|
|
|
|
self?.navigator.show(segue: .followers(viewModel: followersViewModel), sender: self)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
self.personalHeaderView.likeControl.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in
|
|
|
|
|
let likeListViewModel = LikeListViewModel.init(provider: viewModel.provider)
|
|
|
|
|
|
|
|
|
|
self?.navigator.show(segue: .likeList(viewModel: likeListViewModel), sender: self)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output.user.subscribe { user in
|
|
|
|
|
self.personalHeaderView?.user = user
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.personalHeaderView.messageButton.rx.tap.subscribe { [weak self] _ in
|
|
|
|
|
let messageViewModel = MessageViewModel.init(provider: viewModel.provider)
|
|
|
|
|
|
|
|
|
|
self?.navigator.show(segue: .message(viewModel: messageViewModel), sender: self)
|
|
|
|
|
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
// self.personalHeaderView.followingControl.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in
|
|
|
|
|
// let followingViewModel = FollowingViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self?.navigator.show(segue: .following(viewModel: followingViewModel), sender: self)
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
//
|
|
|
|
|
// self.personalHeaderView.followersControl.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in
|
|
|
|
|
// let followersViewModel = FollowersViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self?.navigator.show(segue: .followers(viewModel: followersViewModel), sender: self)
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
//
|
|
|
|
|
// self.personalHeaderView.likeControl.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in
|
|
|
|
|
// let likeListViewModel = LikeListViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self?.navigator.show(segue: .likeList(viewModel: likeListViewModel), sender: self)
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// self.personalHeaderView.messageButton.rx.tap.subscribe { [weak self] _ in
|
|
|
|
|
// let messageViewModel = MessageViewModel.init(provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self?.navigator.show(segue: .message(viewModel: messageViewModel), sender: self)
|
|
|
|
|
//
|
|
|
|
|
// }.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -127,17 +245,10 @@ class PersonalViewController: ViewController {
|
|
|
|
|
override func viewDidLayoutSubviews() {
|
|
|
|
|
super.viewDidLayoutSubviews()
|
|
|
|
|
|
|
|
|
|
personalHeaderView.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(view)
|
|
|
|
|
make.top.equalTo(view)
|
|
|
|
|
make.right.equalTo(view)
|
|
|
|
|
// make.height.equalTo(BaseDimensions.topHeight + 224)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
personalView.snp.makeConstraints { make in
|
|
|
|
|
collectionView.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(view)
|
|
|
|
|
make.right.equalTo(view)
|
|
|
|
|
make.top.equalTo(personalHeaderView.snp.bottom)
|
|
|
|
|
make.top.equalTo(view).offset(-BaseDimensions.topHeight)
|
|
|
|
|
make.bottom.equalTo(view)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -146,41 +257,77 @@ class PersonalViewController: ViewController {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extension PersonalViewController {
|
|
|
|
|
//TODO
|
|
|
|
|
static func tableViewDataSource(_ 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
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
func createSingleColumnSection() -> NSCollectionLayoutSection {
|
|
|
|
|
let singleColumnItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(100))
|
|
|
|
|
let singleColumnItem = NSCollectionLayoutItem(layoutSize: singleColumnItemSize)
|
|
|
|
|
|
|
|
|
|
let singleColumnGroup = NSCollectionLayoutGroup.horizontal(layoutSize: singleColumnItemSize, subitems: [singleColumnItem])
|
|
|
|
|
|
|
|
|
|
let singleColumnSection = NSCollectionLayoutSection(group: singleColumnGroup)
|
|
|
|
|
|
|
|
|
|
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(329 + BaseDimensions.statusBarHeight))
|
|
|
|
|
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
|
|
|
|
|
singleColumnSection.boundarySupplementaryItems = [header]
|
|
|
|
|
|
|
|
|
|
return singleColumnSection
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func createDoubleColumnSection() -> NSCollectionLayoutSection {
|
|
|
|
|
let doubleColumnItemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .absolute(147))
|
|
|
|
|
let doubleColumnItem = NSCollectionLayoutItem(layoutSize: doubleColumnItemSize)
|
|
|
|
|
|
|
|
|
|
let doubleColumnGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(100)), subitem: doubleColumnItem, count: 2)
|
|
|
|
|
doubleColumnGroup.interItemSpacing = .fixed(10)
|
|
|
|
|
|
|
|
|
|
let doubleColumnSection = NSCollectionLayoutSection(group: doubleColumnGroup)
|
|
|
|
|
|
|
|
|
|
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44))
|
|
|
|
|
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
|
|
|
|
|
doubleColumnSection.boundarySupplementaryItems = [header]
|
|
|
|
|
|
|
|
|
|
doubleColumnSection.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 18, bottom: 0, trailing: 18)
|
|
|
|
|
|
|
|
|
|
return doubleColumnSection
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extension PersonalViewController {
|
|
|
|
|
//TODO
|
|
|
|
|
// static func tableViewDataSource(_ 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
|
|
|
|
|
// }
|
|
|
|
|
// )
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extension PersonalViewController {
|
|
|
|
|
|
|
|
|
|
static func collectionViewDataSource() -> RxCollectionViewSectionedReloadDataSource<MusicStyleSection> {
|
|
|
|
|
return RxCollectionViewSectionedReloadDataSource<MusicStyleSection>(
|
|
|
|
|
configureCell: { dataSource, collectionView, indexPath, item in
|
|
|
|
|
// 配置和返回 cell
|
|
|
|
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "JournalViewCell", for: indexPath) as! JournalViewCell
|
|
|
|
|
// 配置 cell
|
|
|
|
|
cell.titleLabel.text = item.title
|
|
|
|
|
cell.volLabel.text = item.subTitle
|
|
|
|
|
|
|
|
|
|
return cell
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
// static func collectionViewDataSource() -> RxCollectionViewSectionedReloadDataSource<MusicStyleSection> {
|
|
|
|
|
// return RxCollectionViewSectionedReloadDataSource<MusicStyleSection>(
|
|
|
|
|
// configureCell: { dataSource, collectionView, indexPath, item in
|
|
|
|
|
// // 配置和返回 cell
|
|
|
|
|
// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "JournalViewCell", for: indexPath) as! JournalViewCell
|
|
|
|
|
// // 配置 cell
|
|
|
|
|
// cell.titleLabel.text = item.title
|
|
|
|
|
// cell.volLabel.text = item.subTitle
|
|
|
|
|
//
|
|
|
|
|
// return cell
|
|
|
|
|
// }
|
|
|
|
|
// )
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -321,12 +468,16 @@ class PersonalView: UIView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PersonalHeaderView: UIView {
|
|
|
|
|
let backgroungView: UIImageView = {
|
|
|
|
|
let backgroungView = UIImageView.init()
|
|
|
|
|
backgroungView.backgroundColor = .white
|
|
|
|
|
class PersonalHeaderView: UICollectionReusableView {
|
|
|
|
|
|
|
|
|
|
var blurEffectView: UIImageView = {
|
|
|
|
|
let titleImageView = UIImageView.init()
|
|
|
|
|
let blurEffect = UIBlurEffect(style: .regular)
|
|
|
|
|
let blurEffectView = UIVisualEffectView(effect: blurEffect)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return backgroungView
|
|
|
|
|
titleImageView.addSubview(blurEffectView)
|
|
|
|
|
return titleImageView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -336,7 +487,7 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
containerView.layer.masksToBounds = true
|
|
|
|
|
containerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
|
|
|
|
containerView.backgroundColor = .white
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return containerView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
@ -350,14 +501,14 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
|
|
|
|
|
let sexView: UIImageView = {
|
|
|
|
|
let sexView = UIImageView.init()
|
|
|
|
|
sexView.image = UIImage.init(named: "personal_sex_icon")
|
|
|
|
|
// sexView.image = UIImage.init(named: "personal_sex_icon")
|
|
|
|
|
|
|
|
|
|
return sexView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
let badgeView: UIImageView = {
|
|
|
|
|
let badgeView = UIImageView.init()
|
|
|
|
|
badgeView.image = UIImage.init(named: "personal_badge_icon")
|
|
|
|
|
// badgeView.image = UIImage.init(named: "personal_badge_icon")
|
|
|
|
|
|
|
|
|
|
return badgeView
|
|
|
|
|
}()
|
|
|
|
@ -370,6 +521,7 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
ipLabel.layer.borderColor = UIColor.separator().cgColor
|
|
|
|
|
ipLabel.layer.borderWidth = 1
|
|
|
|
|
ipLabel.layer.cornerRadius = 3
|
|
|
|
|
ipLabel.isHidden = true
|
|
|
|
|
|
|
|
|
|
return ipLabel
|
|
|
|
|
}()
|
|
|
|
@ -427,10 +579,12 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
followingButton.setTitle("取消", for: .selected)
|
|
|
|
|
followingButton.setTitleColor(.white, for: .normal)
|
|
|
|
|
followingButton.setTitleColor(.primaryText(), for: .selected)
|
|
|
|
|
followingButton.backgroundColor = .primaryText()
|
|
|
|
|
followingButton.setBackgroundColor(color: .primaryText(), forState: .normal)
|
|
|
|
|
followingButton.setBackgroundColor(color: .white, forState: .selected)
|
|
|
|
|
|
|
|
|
|
followingButton.layer.cornerRadius = 16
|
|
|
|
|
followingButton.layer.masksToBounds = true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return followingButton
|
|
|
|
|
}()
|
|
|
|
@ -443,6 +597,93 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
return messageButton
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lazy var segmentControl: ScrollSegmentView = {
|
|
|
|
|
|
|
|
|
|
var style = SegmentStyle()
|
|
|
|
|
style.showLine = true
|
|
|
|
|
style.normalTitleColor = UIColor.secondaryText()
|
|
|
|
|
style.selectedTitleColor = UIColor.primaryText()
|
|
|
|
|
style.backgroundColor = UIColor.white
|
|
|
|
|
style.titleSelectFont = UIFont.systemFont(ofSize: 15, weight: .medium)
|
|
|
|
|
style.titleFont = UIFont.systemFont(ofSize: 15)
|
|
|
|
|
|
|
|
|
|
style.scrollLineHeight = 2
|
|
|
|
|
style.scrollLineColor = .primary()
|
|
|
|
|
style.coverBackgroundColor = .init(hex: 0x0d0d0d)
|
|
|
|
|
style.normalborderColor = UIColor.tertiaryText()
|
|
|
|
|
style.scrollTitle = false
|
|
|
|
|
style.showCover = false
|
|
|
|
|
style.normalborderColor = .clear
|
|
|
|
|
|
|
|
|
|
// style.scrollTitle = true
|
|
|
|
|
style.lineSpace = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let segmentControl = ScrollSegmentView.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 32), segmentStyle: style, titles: ["收藏的单曲", "收藏期刊"])
|
|
|
|
|
|
|
|
|
|
// segmentControl.scrollView.backgroundColor = .red
|
|
|
|
|
|
|
|
|
|
return segmentControl
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var user: User? {
|
|
|
|
|
didSet {
|
|
|
|
|
guard let user = user else { return }
|
|
|
|
|
blurEffectView.kf.setImage(with: URL.init(string: user.avatar ?? ""))
|
|
|
|
|
avatarView.kf.setImage(with: URL.init(string: user.avatar ?? ""))
|
|
|
|
|
|
|
|
|
|
nameLabel.text = user.nickName
|
|
|
|
|
slognLabel.addAttributed(attributedes: [("\(user.ipLocation ?? "") | ", [NSAttributedString.Key.foregroundColor: UIColor.secondaryText()]),
|
|
|
|
|
("\(user.signature ?? "这个人很懒 没有留下签名…")", [NSAttributedString.Key.foregroundColor: UIColor.tertiaryText()])
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
followingControl.titleLabel.text = "关注"
|
|
|
|
|
followingControl.countLabel.text = "\(user.followCount ?? 0)"
|
|
|
|
|
followersControl.countLabel.text = "\(user.fansCount ?? 0)"
|
|
|
|
|
likeControl.countLabel.text = "\(user.thumbUpCount ?? 0)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sexView.image = UIImage.init(named: user.sex?.image ?? "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch user.relation {
|
|
|
|
|
case .notFollowing:
|
|
|
|
|
followingButton.setTitle("关注", for: .normal)
|
|
|
|
|
followingButton.setTitle("取消", for: .selected)
|
|
|
|
|
|
|
|
|
|
updateButtonState(isSelcted: false)
|
|
|
|
|
case .following:
|
|
|
|
|
followingButton.setTitle("关注", for: .normal)
|
|
|
|
|
followingButton.setTitle("取消", for: .selected)
|
|
|
|
|
|
|
|
|
|
updateButtonState(isSelcted: true)
|
|
|
|
|
|
|
|
|
|
case .mutualFollowing:
|
|
|
|
|
followingButton.setTitle("互相关注", for: .normal)
|
|
|
|
|
followingButton.setTitle("取消", for: .selected)
|
|
|
|
|
|
|
|
|
|
followingButton.isSelected = true
|
|
|
|
|
updateButtonState(isSelcted: true)
|
|
|
|
|
|
|
|
|
|
case .blockedByMe:
|
|
|
|
|
followingButton.setTitle("互相关注", for: .normal)
|
|
|
|
|
followingButton.setTitle("解除黑名单", for: .selected)
|
|
|
|
|
|
|
|
|
|
followingButton.isSelected = true
|
|
|
|
|
updateButtonState(isSelcted: true)
|
|
|
|
|
|
|
|
|
|
case .blockedByOther:
|
|
|
|
|
break
|
|
|
|
|
default: break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override init(frame: CGRect) {
|
|
|
|
|
super.init(frame: frame)
|
|
|
|
|
|
|
|
|
@ -454,8 +695,10 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func makeUI() {
|
|
|
|
|
addSubview(backgroungView)
|
|
|
|
|
|
|
|
|
|
addSubview(blurEffectView)
|
|
|
|
|
addSubview(containerView)
|
|
|
|
|
addSubview(segmentControl)
|
|
|
|
|
containerView.addSubview(nameLabel)
|
|
|
|
|
containerView.addSubview(badgeView)
|
|
|
|
|
containerView.addSubview(sexView)
|
|
|
|
@ -473,20 +716,30 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
override func layoutSubviews() {
|
|
|
|
|
super.layoutSubviews()
|
|
|
|
|
|
|
|
|
|
backgroungView.snp.makeConstraints { make in
|
|
|
|
|
blurEffectView.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(self)
|
|
|
|
|
make.right.equalTo(self)
|
|
|
|
|
make.top.equalTo(self)
|
|
|
|
|
make.height.equalTo(261)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
segmentControl.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(self).offset(18)
|
|
|
|
|
make.right.equalTo(self).offset(-18)
|
|
|
|
|
make.height.equalTo(74)
|
|
|
|
|
make.bottom.equalTo(self)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
containerView.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(self)
|
|
|
|
|
make.right.equalTo(self)
|
|
|
|
|
make.top.equalTo(self).offset(BaseDimensions.topHeight + 60)
|
|
|
|
|
make.bottom.equalTo(self)
|
|
|
|
|
make.bottom.equalTo(segmentControl.snp.top)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nameLabel.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(containerView).offset(18)
|
|
|
|
|
make.top.equalTo(containerView).offset(18)
|
|
|
|
@ -518,9 +771,8 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
make.right.equalTo(avatarView.snp.left).offset(-18)
|
|
|
|
|
make.top.equalTo(nameLabel.snp.bottom).offset(3)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
followingControl.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(containerView).offset(18)
|
|
|
|
|
make.left.equalTo(containerView.snp.left).offset(18)
|
|
|
|
|
make.top.equalTo(slognLabel.snp.bottom).offset(15)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -537,7 +789,7 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
followingButton.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(containerView).offset(18)
|
|
|
|
|
make.top.equalTo(followingControl.snp.bottom).offset(24)
|
|
|
|
|
make.bottom.equalTo(self.snp.bottom).offset(-24)
|
|
|
|
|
make.bottom.equalTo(containerView.snp.bottom).offset(-24)
|
|
|
|
|
make.size.equalTo(CGSize.init(width: 76, height: 32))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -547,6 +799,19 @@ class PersonalHeaderView: UIView {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func updateButtonState(isSelcted: Bool) {
|
|
|
|
|
followingButton.isSelected = isSelcted
|
|
|
|
|
followingButton.layer.borderWidth = 1
|
|
|
|
|
if isSelcted {
|
|
|
|
|
self.followingButton.layer.borderColor = UIColor.separator().cgColor
|
|
|
|
|
} else {
|
|
|
|
|
self.followingButton.layer.borderColor = UIColor.primaryText().cgColor
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -595,7 +860,8 @@ class PersonalMenuControl: UIControl {
|
|
|
|
|
|
|
|
|
|
countLabel.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(titleLabel.snp.right).offset(6)
|
|
|
|
|
make.centerY.equalTo(self)
|
|
|
|
|
make.top.equalTo(self)
|
|
|
|
|
make.bottom.equalTo(self)
|
|
|
|
|
make.right.equalTo(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|