parent
33577405d6
commit
d4d3f26316
@ -0,0 +1,22 @@
|
||||
//
|
||||
// PopoverListView.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/2/21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import FSPopoverView
|
||||
|
||||
class PopoverListView: FSPopoverListView {
|
||||
var dismissClosures: (()->())? = nil
|
||||
|
||||
override func popoverViewShouldDismissOnTapOutside(_ popoverView: FSPopoverView) -> Bool {
|
||||
|
||||
if let dismissClosures = self.dismissClosures {
|
||||
dismissClosures()
|
||||
}
|
||||
|
||||
return super.popoverViewShouldDismissOnTapOutside(popoverView)
|
||||
}
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
//
|
||||
// ReportMenuViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/2/20.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
import SVProgressHUD
|
||||
|
||||
class ReportMenuViewModel: ViewModel, ViewModelType {
|
||||
|
||||
struct Input {
|
||||
let viewWillAppear: ControlEvent<Bool>
|
||||
let modelSelected: Driver<Sheet>
|
||||
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let items: BehaviorRelay<[SheetSection]>
|
||||
let modelSelected: Driver<Sheet>
|
||||
let popView: PublishSubject<Void>
|
||||
}
|
||||
|
||||
let items = BehaviorRelay<[SheetSection]>.init(value: [])
|
||||
let popView = PublishSubject<Void>.init()
|
||||
|
||||
let commentId: String
|
||||
|
||||
init(commentId: String, provider: IndieMusicAPI) {
|
||||
self.commentId = commentId
|
||||
super.init(provider: provider)
|
||||
}
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
input.viewWillAppear.subscribe { (_) in
|
||||
|
||||
let array = ReportType.allCases.map { reportType in
|
||||
return Sheet.report(reportType)
|
||||
}
|
||||
|
||||
|
||||
self.items.accept([SheetSection.init(items: array)])
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
input.modelSelected.drive { sheet in
|
||||
switch sheet {
|
||||
case .report(let reportType):
|
||||
|
||||
self.requestCommentReport(commentId: self.commentId, type: reportType.rawValue)
|
||||
.subscribe { _ in
|
||||
SVProgressHUD.showText(withStatus: "提交成功")
|
||||
self.popView.onNext(())
|
||||
} onError: { error in
|
||||
|
||||
}.disposed(by: self.rx.disposeBag)
|
||||
default: break
|
||||
}
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
return Output.init(items: items,
|
||||
modelSelected: input.modelSelected,
|
||||
popView: popView)
|
||||
}
|
||||
|
||||
func requestCommentReport(commentId: String, type: String) -> Observable<Void> {
|
||||
self.provider.commentReport(commentId: commentId, type: type)
|
||||
.trackActivity(loading)
|
||||
.trackError(error)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
class ReportMenuViewController: ViewController, UIScrollViewDelegate {
|
||||
|
||||
let footerView: UIView = {
|
||||
let footerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 48))
|
||||
|
||||
|
||||
return footerView
|
||||
}()
|
||||
|
||||
lazy var dismissButton: UIButton = {
|
||||
let dismissButton = UIButton.init(frame: footerView.bounds)
|
||||
dismissButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
|
||||
dismissButton.setTitleColor(.primaryText(), for: .normal)
|
||||
dismissButton.setTitle("取消", for: .normal)
|
||||
return dismissButton
|
||||
}()
|
||||
|
||||
lazy var tableView: TableView = {
|
||||
let view = TableView(frame: view.bounds, style: .plain)
|
||||
view.rx.setDelegate(self).disposed(by: rx.disposeBag)
|
||||
return view
|
||||
}()
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
view.backgroundColor = .white
|
||||
|
||||
footerView.addSubview(dismissButton)
|
||||
|
||||
tableView.tableFooterView = footerView
|
||||
|
||||
tableView.register(SheetViewCell.self, forCellReuseIdentifier: "SheetViewCell")
|
||||
|
||||
view.addSubview(tableView)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
guard let viewModel = viewModel as? ReportMenuViewModel else { return }
|
||||
|
||||
let input = ReportMenuViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
||||
modelSelected: tableView.rx.modelSelected(Sheet.self).asDriver())
|
||||
|
||||
let output = viewModel.transform(input: input)
|
||||
|
||||
let dataSource = ReportMenuViewController.dataSource()
|
||||
|
||||
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
output.popView.subscribe { [weak self] _ in
|
||||
self?.navigator.dismiss(sender: self)
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
dismissButton.rx.tap.subscribe { [weak self] _ in
|
||||
self?.navigator.dismiss(sender: self)
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension ReportMenuViewController {
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<SheetSection> {
|
||||
return RxTableViewSectionedReloadDataSource<SheetSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: SheetViewCell = tableView.dequeueReusableCell(withIdentifier: "SheetViewCell", for: indexPath) as! SheetViewCell
|
||||
cell.sheet = item
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ReportMenuViewController: UIViewControllerTransitioningDelegate {
|
||||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||||
|
||||
let carePresentationVC = CardPresentationController.init(presentedViewController: presented, presenting: presenting)
|
||||
carePresentationVC.viewType = .reportMenu
|
||||
|
||||
return carePresentationVC
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
//
|
||||
// SheetViewCell.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/2/20.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class SheetViewCell: UITableViewCell {
|
||||
var titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.textColor = .primaryText()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
var sheet: Sheet? {
|
||||
didSet {
|
||||
titleLabel.text = sheet?.description
|
||||
}
|
||||
}
|
||||
|
||||
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.centerX.equalTo(contentView)
|
||||
make.height.equalTo(51)
|
||||
make.top.equalTo(contentView)
|
||||
make.bottom.equalTo(contentView)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
//
|
||||
// FeedbackMenuViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/2/21.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class FeedbackMenuViewModel: ViewModel, ViewModelType {
|
||||
|
||||
struct Input {
|
||||
let viewWillAppear: ControlEvent<Bool>
|
||||
let modelSelected: Driver<Sheet>
|
||||
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let items: BehaviorRelay<[SheetSection]>
|
||||
let modelSelected: Driver<Sheet>
|
||||
let popView: PublishSubject<Void>
|
||||
}
|
||||
|
||||
let items = BehaviorRelay<[SheetSection]>.init(value: [])
|
||||
let popView = PublishSubject<Void>.init()
|
||||
var feedbackType = PublishRelay<FeedbackType>.init()
|
||||
|
||||
|
||||
init(feedbackType: PublishRelay<FeedbackType>, provider: IndieMusicAPI) {
|
||||
super.init(provider: provider)
|
||||
|
||||
self.feedbackType = feedbackType
|
||||
}
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
input.viewWillAppear.subscribe { (_) in
|
||||
let array = FeedbackType.allCases.map { feedbackType in
|
||||
return Sheet.feedback(feedbackType)
|
||||
}
|
||||
|
||||
self.items.accept([SheetSection.init(items: array)])
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
input.modelSelected.drive { sheet in
|
||||
switch sheet {
|
||||
case .feedback(let feedbackType):
|
||||
self.feedbackType.accept(feedbackType)
|
||||
self.popView.onNext(())
|
||||
default: break
|
||||
}
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
|
||||
return Output.init(items: items,
|
||||
modelSelected: input.modelSelected,
|
||||
popView: popView)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
class FeedbackMenuViewController: ViewController, UIScrollViewDelegate {
|
||||
|
||||
let footerView: UIView = {
|
||||
let footerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 48))
|
||||
|
||||
|
||||
return footerView
|
||||
}()
|
||||
|
||||
lazy var dismissButton: UIButton = {
|
||||
let dismissButton = UIButton.init(frame: footerView.bounds)
|
||||
dismissButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
|
||||
dismissButton.setTitleColor(.primaryText(), for: .normal)
|
||||
dismissButton.setTitle("取消", for: .normal)
|
||||
return dismissButton
|
||||
}()
|
||||
|
||||
lazy var tableView: TableView = {
|
||||
let view = TableView(frame: view.bounds, style: .plain)
|
||||
// view.emptyDataSetSource = self
|
||||
// view.emptyDataSetDelegate = self
|
||||
view.rx.setDelegate(self).disposed(by: rx.disposeBag)
|
||||
return view
|
||||
}()
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
view.backgroundColor = .white
|
||||
|
||||
footerView.addSubview(dismissButton)
|
||||
|
||||
tableView.tableFooterView = footerView
|
||||
|
||||
tableView.register(SheetViewCell.self, forCellReuseIdentifier: "SheetViewCell")
|
||||
|
||||
view.addSubview(tableView)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
guard let viewModel = viewModel as? FeedbackMenuViewModel else { return }
|
||||
|
||||
let input = FeedbackMenuViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
||||
modelSelected: tableView.rx.modelSelected(Sheet.self).asDriver())
|
||||
|
||||
let output = viewModel.transform(input: input)
|
||||
|
||||
let dataSource = FeedbackMenuViewController.dataSource()
|
||||
|
||||
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
output.popView.subscribe { [weak self] _ in
|
||||
self?.navigator.dismiss(sender: self)
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
dismissButton.rx.tap.subscribe { [weak self] _ in
|
||||
self?.navigator.dismiss(sender: self)
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension FeedbackMenuViewController {
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<SheetSection> {
|
||||
return RxTableViewSectionedReloadDataSource<SheetSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: SheetViewCell = tableView.dequeueReusableCell(withIdentifier: "SheetViewCell", for: indexPath) as! SheetViewCell
|
||||
cell.sheet = item
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FeedbackMenuViewController: UIViewControllerTransitioningDelegate {
|
||||
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||||
|
||||
let carePresentationVC = CardPresentationController.init(presentedViewController: presented, presenting: presenting)
|
||||
carePresentationVC.viewType = .feedbackMenu
|
||||
|
||||
return carePresentationVC
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
I am the Electric Man
|
||||
Yes, I am
|
||||
|
||||
I've got the electric band
|
||||
I've got everything but the electric van
|
||||
Electric Man's always got a helping hand for the motherland
|
||||
But it makes it so hard to hold on to the metal can
|
||||
|
||||
"Come on Electric Man!"
|
||||
I'm trying
|
||||
"Yes, you can!"
|
||||
|
||||
I am the Electric Man
|
||||
"He is the Electric Man"
|
||||
I am the Electric Man
|
||||
Yes I am
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "thanks_nav_icon.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 3.7 KiB |
Loading…
Reference in new issue