|
|
|
@ -15,9 +15,45 @@ class SearchResultsController: ViewController {
|
|
|
|
|
let searchTopBar: SearchTopBar = {
|
|
|
|
|
let searchTopBar = SearchTopBar.init()
|
|
|
|
|
|
|
|
|
|
searchTopBar.setContentHuggingPriority(.required, for: .horizontal)
|
|
|
|
|
searchTopBar.setContentCompressionResistancePriority(.required, for: .horizontal)
|
|
|
|
|
|
|
|
|
|
return searchTopBar
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
lazy var segmentControl: ScrollSegmentView = {
|
|
|
|
|
|
|
|
|
|
var style = SegmentStyle()
|
|
|
|
|
style.showLine = true
|
|
|
|
|
style.normalTitleColor = UIColor.tertiaryText()
|
|
|
|
|
style.selectedTitleColor = UIColor.white
|
|
|
|
|
style.backgroundColor = UIColor.white
|
|
|
|
|
style.titleSelectFont = UIFont.systemFont(ofSize: 14, weight: .medium)
|
|
|
|
|
style.titleFont = UIFont.systemFont(ofSize: 14)
|
|
|
|
|
|
|
|
|
|
style.scrollLineHeight = 0
|
|
|
|
|
style.scrollLineColor = .clear
|
|
|
|
|
style.coverBackgroundColor = .init(hex: 0x0d0d0d)
|
|
|
|
|
style.normalborderColor = UIColor.tertiaryText()
|
|
|
|
|
style.scrollTitle = false
|
|
|
|
|
style.showCover = true
|
|
|
|
|
|
|
|
|
|
// style.scrollTitle = true
|
|
|
|
|
// style.lineSpace = 12
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let segmentControl = ScrollSegmentView.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 32), segmentStyle: style, titles: ["单曲", "期刊"])
|
|
|
|
|
segmentControl.isHidden = true
|
|
|
|
|
// segmentControl.scrollView.backgroundColor = .red
|
|
|
|
|
|
|
|
|
|
segmentControl.setContentHuggingPriority(.required, for: .horizontal)
|
|
|
|
|
segmentControl.setContentCompressionResistancePriority(.required, for: .horizontal)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return segmentControl
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let searchNoDataView: SearchNoDataView = {
|
|
|
|
@ -55,6 +91,15 @@ class SearchResultsController: ViewController {
|
|
|
|
|
return collectionView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
let searchSuggestionsView: SearchSuggestionsView = {
|
|
|
|
|
let searchSuggestionsView = SearchSuggestionsView.init()
|
|
|
|
|
searchSuggestionsView.isHidden = true
|
|
|
|
|
|
|
|
|
|
return searchSuggestionsView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let searchType = BehaviorRelay<SearchType>.init(value: .audio)
|
|
|
|
|
|
|
|
|
|
override func viewDidLoad() {
|
|
|
|
@ -66,7 +111,7 @@ class SearchResultsController: ViewController {
|
|
|
|
|
override func makeUI() {
|
|
|
|
|
super.makeUI()
|
|
|
|
|
|
|
|
|
|
searchTopBar.segmentControl.titleBtnOnClick = { [weak self] (label, index) in
|
|
|
|
|
segmentControl.titleBtnOnClick = { [weak self] (label, index) in
|
|
|
|
|
if index == 0 {
|
|
|
|
|
self?.searchType.accept(.audio)
|
|
|
|
|
} else {
|
|
|
|
@ -80,8 +125,10 @@ class SearchResultsController: ViewController {
|
|
|
|
|
view.backgroundColor = .white
|
|
|
|
|
|
|
|
|
|
view.addSubview(searchTopBar)
|
|
|
|
|
view.addSubview(segmentControl)
|
|
|
|
|
view.addSubview(searchNoDataView)
|
|
|
|
|
view.addSubview(collectionView)
|
|
|
|
|
view.addSubview(searchSuggestionsView)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -108,21 +155,34 @@ class SearchResultsController: ViewController {
|
|
|
|
|
let input = SearchResultsViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
|
|
|
|
closeButtonTrigger: self.searchTopBar.cancelButton.rx.tap.asDriver(),
|
|
|
|
|
searchText: searchTopBar.searchControl.textField.rx.text.asDriver(),
|
|
|
|
|
searchTrigger: searchTopBar.searchControl.textField.rx.controlEvent(.editingDidEndOnExit).asDriver(),
|
|
|
|
|
modelSelected: collectionView.rx.modelSelected(SearchResultsItem.self).asDriver(),
|
|
|
|
|
suggestionSelected: searchSuggestionsView.tableView.rx.modelSelected(String.self).asDriver(),
|
|
|
|
|
searchType: searchType)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let output = viewModel.transform(input: input)
|
|
|
|
|
|
|
|
|
|
let dataSource = SearchResultsController.dataSource { [weak self] cell, audioTrack in
|
|
|
|
|
// let audioMoreActionViewModel = AudioMoreActionViewModel.init(audioTrack: audioTrack, provider: viewModel.provider)
|
|
|
|
|
//
|
|
|
|
|
// self?.navigator.show(segue: .audioMore(viewModel: audioMoreActionViewModel), sender: self, transition: .navigationPresent(type: .audioMore))
|
|
|
|
|
let item: BehaviorRelay<AudioTrack?> = .init(value: audioTrack)
|
|
|
|
|
|
|
|
|
|
let audioMoreActionViewModel = AudioMoreActionViewModel.init(audioTrack: item, provider: viewModel.provider)
|
|
|
|
|
|
|
|
|
|
self?.navigator.show(segue: .audioMore(viewModel: audioMoreActionViewModel), sender: self, transition: .navigationPresent(type: .audioMore))
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output.items.bind(to: collectionView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
output.items.subscribe { items in
|
|
|
|
|
|
|
|
|
|
self.segmentControl.isHidden = items.element?.first?.items.isEmpty ?? true
|
|
|
|
|
self.searchSuggestionsView.isHidden = true
|
|
|
|
|
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
searchTopBar.cancelButton.rx.tap.subscribe { [weak self] _ in
|
|
|
|
|
self?.navigator.pop(sender: self)
|
|
|
|
|
|
|
|
|
@ -156,6 +216,19 @@ class SearchResultsController: ViewController {
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let searchSuggestionsDataSource = SearchSuggestionsView.dataSource()
|
|
|
|
|
|
|
|
|
|
output.suggestionsItems.bind(to: searchSuggestionsView.tableView.rx.items(dataSource: searchSuggestionsDataSource)).disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
output.suggestionsItems.subscribe { suggestionsItems in
|
|
|
|
|
self.searchSuggestionsView.isHidden = suggestionsItems.element?.first?.items.isEmpty ?? true
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
searchSuggestionsView.tableView.rx.itemSelected
|
|
|
|
|
.subscribe { indexPath in
|
|
|
|
|
self.searchSuggestionsView.tableView.deselectRow(at: indexPath, animated: true)
|
|
|
|
|
}.disposed(by: rx.disposeBag)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -167,7 +240,13 @@ class SearchResultsController: ViewController {
|
|
|
|
|
make.left.equalTo(view)
|
|
|
|
|
make.right.equalTo(view)
|
|
|
|
|
make.top.equalTo(view).offset(BaseDimensions.statusBarHeight + 15)
|
|
|
|
|
make.height.equalTo(135)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
segmentControl.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(view).offset(18)
|
|
|
|
|
make.top.equalTo(searchTopBar.snp.bottom).offset(9)
|
|
|
|
|
make.width.equalTo(200)
|
|
|
|
|
make.height.equalTo(40)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
searchNoDataView.snp.makeConstraints { make in
|
|
|
|
@ -178,7 +257,14 @@ class SearchResultsController: ViewController {
|
|
|
|
|
collectionView.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(view)
|
|
|
|
|
make.right.equalTo(view)
|
|
|
|
|
make.top.equalTo(searchTopBar.snp.bottom).offset(0)
|
|
|
|
|
make.top.equalTo(segmentControl.snp.bottom).offset(0)
|
|
|
|
|
make.bottom.equalTo(view)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
searchSuggestionsView.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(view)
|
|
|
|
|
make.right.equalTo(view)
|
|
|
|
|
make.top.equalTo(searchTopBar.snp.bottom)
|
|
|
|
|
make.bottom.equalTo(view)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -190,7 +276,7 @@ class SearchResultsController: ViewController {
|
|
|
|
|
|
|
|
|
|
extension SearchResultsController {
|
|
|
|
|
//TODO
|
|
|
|
|
static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, AudioTrack) -> Void) -> RxCollectionViewSectionedReloadDataSource<SearchResultsSection> {
|
|
|
|
|
static func dataSource(_ buttonTapHandler: @escaping (UICollectionViewCell, AudioTrack) -> Void) -> RxCollectionViewSectionedReloadDataSource<SearchResultsSection> {
|
|
|
|
|
return RxCollectionViewSectionedReloadDataSource<SearchResultsSection>(
|
|
|
|
|
configureCell: { dataSource, collectionView, indexPath, item in
|
|
|
|
|
|
|
|
|
@ -200,6 +286,10 @@ extension SearchResultsController {
|
|
|
|
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "JournalAudioCollectionViewCell", for: indexPath) as! JournalAudioCollectionViewCell
|
|
|
|
|
cell.audioTrack = audioTrack
|
|
|
|
|
|
|
|
|
|
cell.buttonTapCallback = { audioTrack in
|
|
|
|
|
buttonTapHandler(cell, audioTrack)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return cell
|
|
|
|
|
|
|
|
|
|
case .journal(let journal):
|
|
|
|
@ -252,7 +342,6 @@ class SearchTopBar: UIView {
|
|
|
|
|
let searchControl: SearchControl = {
|
|
|
|
|
let searchControl = SearchControl.init()
|
|
|
|
|
searchControl.layer.cornerRadius = 20
|
|
|
|
|
|
|
|
|
|
return searchControl
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
@ -267,33 +356,7 @@ class SearchTopBar: UIView {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lazy var segmentControl: ScrollSegmentView = {
|
|
|
|
|
|
|
|
|
|
var style = SegmentStyle()
|
|
|
|
|
style.showLine = true
|
|
|
|
|
style.normalTitleColor = UIColor.tertiaryText()
|
|
|
|
|
style.selectedTitleColor = UIColor.white
|
|
|
|
|
style.backgroundColor = UIColor.white
|
|
|
|
|
style.titleSelectFont = UIFont.systemFont(ofSize: 14, weight: .medium)
|
|
|
|
|
style.titleFont = UIFont.systemFont(ofSize: 14)
|
|
|
|
|
|
|
|
|
|
style.scrollLineHeight = 0
|
|
|
|
|
style.scrollLineColor = .clear
|
|
|
|
|
style.coverBackgroundColor = .init(hex: 0x0d0d0d)
|
|
|
|
|
style.normalborderColor = UIColor.tertiaryText()
|
|
|
|
|
style.scrollTitle = false
|
|
|
|
|
style.showCover = true
|
|
|
|
|
// style.scrollTitle = true
|
|
|
|
|
// style.lineSpace = 12
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let segmentControl = ScrollSegmentView.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 32), segmentStyle: style, titles: ["单曲", "期刊"])
|
|
|
|
|
|
|
|
|
|
// segmentControl.scrollView.backgroundColor = .red
|
|
|
|
|
|
|
|
|
|
return segmentControl
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -312,7 +375,6 @@ class SearchTopBar: UIView {
|
|
|
|
|
|
|
|
|
|
addSubview(searchControl)
|
|
|
|
|
addSubview(cancelButton)
|
|
|
|
|
addSubview(segmentControl)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -329,17 +391,10 @@ class SearchTopBar: UIView {
|
|
|
|
|
searchControl.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(self).offset(18)
|
|
|
|
|
make.top.equalTo(self).offset(15)
|
|
|
|
|
make.bottom.equalTo(self).offset(-15)
|
|
|
|
|
make.height.equalTo(40)
|
|
|
|
|
make.right.equalTo(cancelButton.snp.left).offset(-12)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
segmentControl.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(self).offset(18)
|
|
|
|
|
make.top.equalTo(searchControl.snp.bottom).offset(24)
|
|
|
|
|
make.bottom.equalTo(self).offset(-24)
|
|
|
|
|
make.width.equalTo(200)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
@ -376,3 +431,86 @@ class SearchNoDataView: UIView {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SearchSuggestionsView: UIView {
|
|
|
|
|
let tableView: UITableView = {
|
|
|
|
|
let tableView = UITableView.init()
|
|
|
|
|
tableView.register(SearchSuggestionsViewCell.self, forCellReuseIdentifier: "SearchSuggestionsViewCell")
|
|
|
|
|
|
|
|
|
|
return tableView
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override init(frame: CGRect) {
|
|
|
|
|
super.init(frame: frame)
|
|
|
|
|
|
|
|
|
|
makeUI()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
required init?(coder: NSCoder) {
|
|
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func makeUI() {
|
|
|
|
|
addSubview(tableView)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func layoutSubviews() {
|
|
|
|
|
super.layoutSubviews()
|
|
|
|
|
|
|
|
|
|
tableView.snp.makeConstraints { make in
|
|
|
|
|
make.edges.equalTo(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extension SearchSuggestionsView {
|
|
|
|
|
static func dataSource() -> RxTableViewSectionedReloadDataSource<SearchSuggestionSection> {
|
|
|
|
|
return RxTableViewSectionedReloadDataSource<SearchSuggestionSection>(
|
|
|
|
|
configureCell: { dataSource, tableView, indexPath, item in
|
|
|
|
|
let cell: SearchSuggestionsViewCell = tableView.dequeueReusableCell(withIdentifier: "SearchSuggestionsViewCell", for: indexPath) as! SearchSuggestionsViewCell
|
|
|
|
|
|
|
|
|
|
cell.titleLabel.text = item
|
|
|
|
|
|
|
|
|
|
return cell
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SearchSuggestionsViewCell: UITableViewCell {
|
|
|
|
|
let titleLabel: UILabel = {
|
|
|
|
|
let titleLabel = UILabel.init()
|
|
|
|
|
titleLabel.textColor = .tertiaryText()
|
|
|
|
|
|
|
|
|
|
return titleLabel
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
|
|
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
|
|
|
|
|
|
|
|
makeUI()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
required init?(coder: NSCoder) {
|
|
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func makeUI() {
|
|
|
|
|
contentView.addSubview(titleLabel)
|
|
|
|
|
|
|
|
|
|
titleLabel.snp.makeConstraints { make in
|
|
|
|
|
make.left.equalTo(contentView).offset(18)
|
|
|
|
|
make.centerY.equalTo(contentView)
|
|
|
|
|
make.right.equalTo(contentView).offset(-18)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|