Fix the filtering problem

dev
wenlei 11 months ago
parent 822336eee7
commit 0aa474e2d6

@ -1896,7 +1896,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4;
CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = AY569L2R6W;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
@ -1937,7 +1937,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4;
CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = AY569L2R6W;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;

@ -264,11 +264,11 @@ class Navigator {
fatalError("You need to pass in a sender for .navigation or .modal transitions")
}
if let nav = sender as? UINavigationController {
nav.pushViewController(target, animated: false)
return
}
// if let nav = sender as? UINavigationController {
//
// nav.pushViewController(target, animated: false)
// return
// }
switch transition {
case .navigationPush:

@ -15,7 +15,7 @@ protocol DefaultNavigation {
class NavigationController: UINavigationController {
lazy var pullToDismissTransition: PullToDismissTransition = PullToDismissTransition(viewController: self)
override init(rootViewController: UIViewController) {
super.init(navigationBarClass: NavigationBar.self, toolbarClass: nil)
self.viewControllers = [rootViewController]
@ -39,33 +39,33 @@ class NavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
view.backgroundColor = .white
let appearance = UINavigationBarAppearance()
appearance.backgroundColor = .white
appearance.titleTextAttributes = [.foregroundColor: UIColor.black]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
UINavigationBar.appearance().tintColor = UIColor(red: 0.25, green: 0.25, blue: 0.25, alpha: 1.00)
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
//
// navigationBar.barTintColor = UIColor.white
// navigationBar.barTintColor = UIColor.white
navigationBar.isTranslucent = false
// 线
// let image = UIImage().generateImageWithColor(color: .white)
// navigationBar.setBackgroundImage(image, for: .default)
// navigationBar.shadowImage = image
// let image = UIImage().generateImageWithColor(color: .white)
// navigationBar.setBackgroundImage(image, for: .default)
// navigationBar.shadowImage = image
appearance.shadowColor = .clear
// if let navigationBar = navigationBar as? NavigationBar {
// navigationItem.titleView = navigationBar.titleView
// }
// if let navigationBar = navigationBar as? NavigationBar {
// navigationItem.titleView = navigationBar.titleView
// }
}
@ -73,7 +73,7 @@ class NavigationController: UINavigationController {
func setup() {
interactivePopGestureRecognizer?.delegate = self
}
@objc fileprivate func back()
@ -102,41 +102,94 @@ extension NavigationController {
override func pushViewController(_ viewController: UIViewController, animated: Bool)
{
guard let tabbar = self.tabBarController as? HomeTabBarController else { return }
if !children.isEmpty {
tabbar.toggleBars(showTabBar: false, showPlayerBar: false, animated: true)
// if viewController is JournalDetailController {
// let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
// tabbar.toggleBars(showTabBar: false, showPlayerBar: isShowPlayBar, animated: true)
// } else if viewController is LoginViewController {
// AudioManager.sharedInstance.pause()
// tabbar.toggleBars(showTabBar: false, showPlayerBar: false, animated: true)
//
// } else if viewController is CommentViewController {
// tabbar.toggleBars(showTabBar: false, showPlayerBar: false, animated: true)
//
// } else {
// tabbar.toggleBars(showTabBar: false, showPlayerBar: true, animated: true)
// }
switch viewController {
case is MusicStyleViewController,
is FollowersViewController,
is FollowingViewController,
is MineSingleController,
is MineJournalViewController,
is MineDownloadViewController,
is PersonalViewController,
is MessageViewController,
is SettingViewController:
let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
tabbar.toggleBars(showTabBar: false, showPlayerBar: isShowPlayBar, animated: true)
case is HomeViewController,
is SearchViewController,
is MineViewController:
let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
tabbar.toggleBars(showTabBar: true, showPlayerBar: isShowPlayBar, animated: true)
default:
tabbar.toggleBars(showTabBar: false, showPlayerBar: false, animated: true)
}
}
super.pushViewController(viewController, animated: animated)
}
override func popViewController(animated: Bool) -> UIViewController? {
guard let tabbar = self.tabBarController as? HomeTabBarController else { return super.popViewController(animated: animated)}
// if let vc = children.last as? CommentViewController {
// let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
// tabbar.toggleBars(showTabBar: false, showPlayerBar: isShowPlayBar, animated: true)
//
// }
switch children[children.count - 2] {
case is MusicStyleViewController,
is FollowersViewController,
is FollowingViewController,
is MineSingleController,
is MineJournalViewController,
is MineDownloadViewController,
is PersonalViewController,
is MessageViewController,
is SettingViewController:
let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
tabbar.toggleBars(showTabBar: false, showPlayerBar: isShowPlayBar, animated: true)
case is HomeViewController,
is SearchViewController,
is MineViewController:
let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
tabbar.toggleBars(showTabBar: true, showPlayerBar: isShowPlayBar, animated: true)
default:
tabbar.toggleBars(showTabBar: false, showPlayerBar: false, animated: true)
}
// switch children[children.count - 2] {
// case
// is FollowersViewController,
// is FollowingViewController,
// is MineSingleController,
// is MineJournalViewController,
// is MineDownloadViewController,
// is PersonalViewController,
// is MessageViewController,
// is SettingViewController:
// let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
// tabbar.toggleBars(showTabBar: false, showPlayerBar: isShowPlayBar, animated: true)
//
//// is JournalDetailController,
//// is MusicStyleViewController,
// case is SearchViewController,
// is HomeViewController,
// is MineViewController:
// let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
// tabbar.toggleBars(showTabBar: true, showPlayerBar: isShowPlayBar, animated: true)
// default:
// tabbar.toggleBars(showTabBar: false, showPlayerBar: false, animated: true)
//
// }
return super.popViewController(animated: animated)
}
@ -175,7 +228,7 @@ extension NavigationController: UIGestureRecognizerDelegate{
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return gestureRecognizer.isKind(of: UIScreenEdgePanGestureRecognizer.self)
}
}
@ -185,7 +238,7 @@ extension NavigationController: PullToDismissable, UIViewControllerTransitioning
super.didMove(toParent: parent)
setupPullToDismiss()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupPullToDismiss()
@ -203,15 +256,15 @@ extension NavigationController: PullToDismissable, UIViewControllerTransitioning
func animationController(forDismissed dismissed: UIViewController)
-> UIViewControllerAnimatedTransitioning? {
guard isPullToDismissEnabled else { return nil }
return PresentAndDismissTransition(true)
-> UIViewControllerAnimatedTransitioning? {
guard isPullToDismissEnabled else { return nil }
return PresentAndDismissTransition(true)
}
func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning)
-> UIViewControllerInteractiveTransitioning? {
guard isPullToDismissEnabled else { return nil }
return pullToDismissTransition
-> UIViewControllerInteractiveTransitioning? {
guard isPullToDismissEnabled else { return nil }
return pullToDismissTransition
}
}

@ -125,7 +125,7 @@ struct Comment: Codable, IdentifiableType, Equatable {
}
static func == (lhs: Comment, rhs: Comment) -> Bool {
return lhs.id == rhs.id && lhs.haveThumbup == rhs.haveThumbup && lhs.content == rhs.content && lhs.commentCount == rhs.commentCount && lhs.isSelected == rhs.isSelected
return lhs.id == rhs.id && lhs.haveThumbup == rhs.haveThumbup && lhs.content == rhs.content && lhs.commentCount == rhs.commentCount && lhs.isSelected == rhs.isSelected && lhs.topChildrenComment == rhs.topChildrenComment
}
}

@ -19,7 +19,7 @@ struct Mine: Codable, IdentifiableType, Equatable {
}
static func == (lhs: Mine, rhs: Mine) -> Bool {
return lhs.title == rhs.title
return lhs.title == rhs.title && lhs.icon == rhs.icon
}
}

@ -71,10 +71,16 @@ class HomeTabBarController: UITabBarController, Navigatable {
var viewModel: HomeTabBarViewModel?
var navigator: Navigator!
var customeTabBar: UITabBar = {
let tabBar = UITabBar.init()
tabBar.isTranslucent = false
let blurEffect = UIBlurEffect(style: .light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = tabBar.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tabBar.insertSubview(blurEffectView, at: 0)
return tabBar
}()
@ -313,6 +319,19 @@ class HomeTabBarController: UITabBarController, Navigatable {
}
if showPlayerBar {
self.playerTabBar.isHidden = false
let appearance = UITabBarAppearance()
appearance.configureWithOpaqueBackground()
appearance.shadowImage = nil
appearance.shadowColor = nil
appearance.backgroundImage = UIImage()
customeTabBar.standardAppearance = appearance
customeTabBar.scrollEdgeAppearance = appearance
playerTabBar.snp.remakeConstraints { make in
make.left.right.equalTo(view)
make.bottom.equalTo(view)
@ -323,6 +342,14 @@ class HomeTabBarController: UITabBarController, Navigatable {
}
}
} else {
let appearance = UITabBarAppearance()
appearance.configureWithDefaultBackground()
customeTabBar.standardAppearance = appearance
customeTabBar.standardAppearance = appearance
customeTabBar.scrollEdgeAppearance = appearance
playerTabBar.snp.remakeConstraints { make in
make.left.right.equalTo(view)
make.bottom.equalTo(customeTabBar.snp.top).offset(BaseDimensions.tabBarHeight)
@ -331,7 +358,7 @@ class HomeTabBarController: UITabBarController, Navigatable {
let animationDuration = animated ? 0.35 : 0
let animationDuration = animated ? 0.4 : 0
UIView.animate(withDuration: animationDuration, animations: {
@ -342,6 +369,7 @@ class HomeTabBarController: UITabBarController, Navigatable {
self.customeTabBar.isHidden = !showTabBar
self.playerTabBar.isHidden = !showPlayerBar
self.isAnimating = false
}
}

@ -204,10 +204,17 @@ class HomeViewController: TableViewController, ScrollableNavBar {
self.headerRefreshTrigger.onNext(())
}.disposed(by: rx.disposeBag)
output.showUpdateAlert.subscribe { version in
output.showUpdateAlert.subscribe { [weak self] version in
let versionViewModel = VersionViewModel.init(version: version, provider: viewModel.provider)
self.navigator.show(segue: .version(viewMode: versionViewModel), sender: self, transition: .navigationPresent(type: .tips(false)))
self?.navigator.show(segue: .version(viewMode: versionViewModel), sender: self, transition: .navigationPresent(type: .tips(false)))
}.disposed(by: rx.disposeBag)
output.showPlayer.subscribe { [weak self] audioTrack in
let playerViewModel = PlayerViewModel.init(playerViewType: .FM, track: audioTrack, provider: viewModel.provider)
self?.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal)
}.disposed(by: rx.disposeBag)

@ -29,6 +29,7 @@ class HomeViewModel: ViewModel, ViewModelType {
// let footerState: PublishRelay<RxMJRefreshFooterState>
let randomAudioTrack: BehaviorRelay<[AudioTrack]>
let showUpdateAlert: PublishRelay<Version>
let showPlayer: PublishRelay<AudioTrack>
}
@ -43,6 +44,7 @@ class HomeViewModel: ViewModel, ViewModelType {
let isNeedRefresh = BehaviorRelay<Bool>.init(value: false)
let showUpdateAlert = PublishRelay<Version>.init()
let showPlayer = PublishRelay<AudioTrack>.init()
func transform(input: Input) -> Output {
let carouselItems = BehaviorRelay<[Carousel]>(value: [])
@ -80,7 +82,9 @@ class HomeViewModel: ViewModel, ViewModelType {
input.headerRefresh.flatMapLatest({ [weak self] () -> Observable<[Journal]> in
guard let self = self else { return Observable.just([]) }
self.page = 1
return self.request(categoryId: self.categoryId.value, journalNoRange: self.journalNoRange.value, pageNum: page, pageSize: 10)
return self.request(categoryId: filter.value?.id ?? nil, journalNoRange: filter.value?.id == "" ? filter.value?.name : nil, pageNum: page, pageSize: 10)
.trackActivity(self.headerLoading)
})
.subscribe(onNext: { (items) in
@ -100,7 +104,11 @@ class HomeViewModel: ViewModel, ViewModelType {
input.footerRefresh.flatMapLatest({ [weak self] () -> Observable<[Journal]> in
guard let self = self else { return Observable.just([]) }
self.page += 1
return self.request(categoryId: self.categoryId.value, journalNoRange: self.journalNoRange.value, pageNum: page, pageSize: 10)
print("filter?.id \(filter.value?.id)")
return self.request(categoryId: filter.value?.id ?? nil, journalNoRange: filter.value?.id == "" ? filter.value?.name : nil, pageNum: page, pageSize: 10)
.trackActivity(self.footerLoading)
})
.subscribe(onNext: { (items) in
@ -126,14 +134,20 @@ class HomeViewModel: ViewModel, ViewModelType {
input.randomAudioTrackTrigger.subscribe { [weak self] _ in
guard let self = self else { return }
if let currentTrack = AudioManager.sharedInstance.currentTrack.value,
AudioManager.sharedInstance.playerType.value == .FM {
self.showPlayer.accept(currentTrack)
} else {
self.requestRandomAudioTrack().subscribe { [weak self] audioTrackArray in
guard let self = self else { return }
self.randomAudioTrack.accept(audioTrackArray)
} onError: { error in
}.disposed(by: self.rx.disposeBag)
}
self.requestRandomAudioTrack().subscribe { [weak self] audioTrackArray in
guard let self = self else { return }
self.randomAudioTrack.accept(audioTrackArray)
} onError: { error in
}.disposed(by: self.rx.disposeBag)
}.disposed(by: rx.disposeBag)
@ -186,7 +200,8 @@ class HomeViewModel: ViewModel, ViewModelType {
itemSelected: itemSelected,
// footerState: footerState,
randomAudioTrack: randomAudioTrack,
showUpdateAlert: showUpdateAlert)
showUpdateAlert: showUpdateAlert,
showPlayer: showPlayer)
}

@ -67,6 +67,7 @@ class CommentDetailViewController: TableViewController {
view.addSubview(commentToolView)
tableView.headRefreshControl = nil
emptyDataSetDescription = "没有其他回复了"
}
override func bindViewModel() {
@ -132,25 +133,23 @@ class CommentDetailViewController: TableViewController {
input.modelSelected.drive { [weak self] comment in
if viewModel.selectedItem.value == nil {
viewModel.selectedItem.accept(comment.comment)
} else {
viewModel.selectedItem.accept(nil)
viewModel.selectedItem.accept(comment.comment)
self?.commentToolView.textField.becomeFirstResponder()
self?.commentToolView.textField.placeholder = "回复\(comment.comment.nickName ?? "")"
}
}.disposed(by: rx.disposeBag)
viewModel.selectedItem.subscribe { comment in
if let comment = comment.element,
let detail = comment {
self.commentToolView.textField.becomeFirstResponder()
self.commentToolView.textField.placeholder = "回复\(comment?.nickName ?? "")"
} else {
self.view.endEditing(false)
self.commentToolView.textField.placeholder = "说点想说的"
}
// if let comment = comment.element,
// let detail = comment {
// self.commentToolView.textField.becomeFirstResponder()
// self.commentToolView.textField.placeholder = "\(comment?.nickName ?? "")"
// } else {
// self.view.endEditing(false)
// self.commentToolView.textField.placeholder = ""
// }
}.disposed(by: rx.disposeBag)
@ -166,6 +165,8 @@ class CommentDetailViewController: TableViewController {
output.clearTextSubject.subscribe { [weak self] _ in
self?.commentToolView.textField.text = ""
}.disposed(by: rx.disposeBag)
output.modelSelected
commentToolView.textField.rx.controlEvent(.editingDidBegin)
.subscribe { _ in
@ -282,7 +283,7 @@ class CommentDetailViewController: TableViewController {
func showMenu(comment: Comment, tapLocation: CGPoint, cell: UITableViewCell) {
guard let viewModel = self.viewModel as? CommentViewModel else { return }
guard let viewModel = self.viewModel as? CommentDetailViewModel else { return }
if comment.userId != UserDefaults.AccountInfo.string(forKey: .userID) {
@ -341,6 +342,12 @@ class CommentDetailViewController: TableViewController {
}
extension CommentDetailViewController {
override func verticalOffset(forEmptyDataSet scrollView: UIScrollView!) -> CGFloat {
guard let tableHeaderView = self.tableView.tableHeaderView else { return -60 }
return -(tableHeaderView.frame.height)
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 60

@ -41,8 +41,10 @@ class CommentDetailViewModel: ViewModel, ViewModelType {
let comment: Comment
init(comment: Comment, provider: IndieMusicAPI) {
let needParentRefresh: PublishRelay<String>
init(comment: Comment, needRefresh: PublishRelay<String>, provider: IndieMusicAPI) {
self.comment = comment
self.needParentRefresh = needRefresh
super.init(provider: provider)
}
@ -89,9 +91,11 @@ class CommentDetailViewModel: ViewModel, ViewModelType {
input.sendCommentTrigger
.withLatestFrom(input.commentText)
.drive(onNext: { comment in
if let comment = comment, !comment.isEmpty {
self.sendCommentData(content: comment, journalId: self.comment.journalId, parentId: self.comment.id, journalImage: self.comment.journalImage)
let parentId = self.selectedItem.value?.id ?? self.comment.id
self.sendCommentData(content: comment, journalId: self.comment.journalId, parentId: parentId, journalImage: self.comment.journalImage)
.subscribe { comment in
let newItems = self.insertComment(newComment: comment)
@ -100,6 +104,10 @@ class CommentDetailViewModel: ViewModel, ViewModelType {
self.clearTextSubject.accept(())
if let parentId = comment.parentId {
self.needParentRefresh.accept(parentId)
}
} onError: { error in
}.disposed(by: self.rx.disposeBag)
@ -140,7 +148,17 @@ class CommentDetailViewModel: ViewModel, ViewModelType {
guard let commentID = comment.element?.id else { return }
self.requestDeleteComment(commentId: commentID)
.subscribe { _ in
self.deleteComment(commentId: commentID)
let newItems = self.deleteComment(commentId: commentID)
self.items.accept(newItems)
if let parentId = comment.element?.parentId {
self.needParentRefresh.accept(parentId)
}
} onError: { error in
}.disposed(by: self.rx.disposeBag)

@ -211,10 +211,15 @@ class CommentViewController: TableViewController {
input.modelSelected.drive { [weak self] commentType in
guard self?.isToLoginView() == false else { return }
let commentDetailViewModel = CommentDetailViewModel.init(comment: commentType.comment, provider: viewModel.provider)
let commentDetailViewModel = CommentDetailViewModel.init(comment: commentType.comment, needRefresh: viewModel.needRefresh, provider: viewModel.provider)
//
self?.navigator.show(segue: .commentDetail(viewModel:commentDetailViewModel), sender: self, transition: .modal)
// guard let navigator = self?.navigator else { return }
// let detai = CommentDetailViewController.init(viewModel: commentDetailViewModel, navigator: navigator)
//
// self?.present(detai, animated: true)
}.disposed(by: rx.disposeBag)
@ -336,9 +341,9 @@ class CommentViewController: TableViewController {
if comment.userId != UserDefaults.AccountInfo.string(forKey: .userID) {
self.menuView.items = self.setupMenuItems(comment: comment, features: [.copy, .report])
self.menuView.items = self.setupMenuItems(comment: comment, subComment: nil, features: [.copy, .report])
} else {
self.menuView.items = self.setupMenuItems(comment: comment, features: [.copy, .delete])
self.menuView.items = self.setupMenuItems(comment: nil, subComment: comment.topChildrenComment, features: [.copy, .delete])
}
viewModel.selectedItem.accept(comment)
@ -349,7 +354,7 @@ class CommentViewController: TableViewController {
}
func setupMenuItems(comment: Comment, features: [PopoverMenu] = [.copy, .delete]) -> [FSPopoverListItem] {
func setupMenuItems(comment: Comment?, subComment: SubComment?, features: [PopoverMenu] = [.copy, .delete]) -> [FSPopoverListItem] {
guard let viewModel = viewModel as? CommentViewModel else { return []}
let items: [FSPopoverListItem] = features.map { feature in
@ -367,16 +372,28 @@ class CommentViewController: TableViewController {
switch item.title {
case PopoverMenu.copy.description:
UIPasteboard.general.string = comment.content
case PopoverMenu.report.description:
let reportMenuViewModel = ReportMenuViewModel.init(commentId: comment.id, provider: viewModel.provider)
self?.navigator.show(segue: .reportMenu(viewModel: reportMenuViewModel), sender: self, transition: .navigationPresent(type: .reportMenu))
if let comment = comment {
UIPasteboard.general.string = comment.content
} else if let subComment = subComment {
UIPasteboard.general.string = subComment.content
}
case PopoverMenu.report.description:
if let comment = comment {
let reportMenuViewModel = ReportMenuViewModel.init(commentId: comment.id, provider: viewModel.provider)
self?.navigator.show(segue: .reportMenu(viewModel: reportMenuViewModel), sender: self, transition: .navigationPresent(type: .reportMenu))
} else if let subComment = subComment {
let reportMenuViewModel = ReportMenuViewModel.init(commentId: subComment.id, provider: viewModel.provider)
self?.navigator.show(segue: .reportMenu(viewModel: reportMenuViewModel), sender: self, transition: .navigationPresent(type: .reportMenu))
}
case PopoverMenu.delete.description:
if let comment = comment {
viewModel.itemDelete.accept(comment.id)
} else if let subComment = subComment {
viewModel.itemDelete.accept(subComment.id)
}
case PopoverMenu.delete.description:
viewModel.itemDelete.accept(comment)
default: break
}
}

@ -35,7 +35,7 @@ class CommentViewModel: ViewModel, ViewModelType {
let insertCommment = PublishSubject<CommentType>.init()
let itemDelete = PublishRelay<Comment>()
let itemDelete = PublishRelay<String>()
let toCommentDetail: PublishRelay<CommentType> = .init()
let clearTextSubject = PublishRelay<Void>()
@ -45,6 +45,8 @@ class CommentViewModel: ViewModel, ViewModelType {
let avatarViewTrigger = PublishRelay<String>.init()
let longPressGestureTrigger = PublishRelay<(UITableViewCell, CGPoint)>.init()
let needRefresh: PublishRelay<String> = .init()
var journal: Journal
init(journal: Journal, provider: IndieMusicAPI) {
@ -187,8 +189,8 @@ class CommentViewModel: ViewModel, ViewModelType {
}).disposed(by: rx.disposeBag)
itemDelete.subscribe { comment in
guard let commentID = comment.element?.id else { return }
itemDelete.subscribe { commentID in
guard let commentID = commentID.element else { return }
self.requestDeleteComment(commentId: commentID)
.subscribe { _ in
let newItems = self.deleteComment(commentId: commentID)
@ -200,6 +202,20 @@ class CommentViewModel: ViewModel, ViewModelType {
}.disposed(by: rx.disposeBag)
needRefresh.subscribe { commentID in
self.requestCommentDetail(commentID: commentID)
.subscribe { comment in
let newItems = self.updateComment(withId: commentID, newComment: comment)
self.items.accept(newItems)
} onError: { error in
}.disposed(by: self.rx.disposeBag)
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
insertCommment: insertCommment,
@ -283,7 +299,7 @@ class CommentViewModel: ViewModel, ViewModelType {
for (sectionIndex, section) in currentSections.enumerated() {
let updatedItems = section.items.filter { $0.comment.id != commentId }
let updatedItems = section.items.filter { $0.comment.id != commentId || $0.comment.topChildrenComment?.id == commentId}
currentSections[sectionIndex] = CommentSection(original: section, items: updatedItems)
}
@ -291,6 +307,11 @@ class CommentViewModel: ViewModel, ViewModelType {
return currentSections
}
func requestCommentDetail(commentID: String) -> Observable<Comment> {
return self.provider.commentDetail(commentID: commentID)
.trackActivity(loading)
.trackError(error)
}
func updateComment(byId id: String, withUpdateBlock updateBlock: @escaping (inout CommentType) -> Void) {
@ -315,18 +336,21 @@ class CommentViewModel: ViewModel, ViewModelType {
for (sectionIndex, section) in currentSections.enumerated() {
var updatedItems = section.items
if let commentIndex = updatedItems.firstIndex(where: { $0.comment.id == commentId }) {
switch updatedItems[commentIndex] {
case .comment:
updatedItems[commentIndex] = CommentType.comment(newComment)
case .quote:
updatedItems[commentIndex] = CommentType.quote(newComment)
for (itemIndex, item) in updatedItems.enumerated() {
if item.comment.id == commentId {
switch item {
case .comment:
updatedItems[itemIndex] = CommentType.comment(newComment)
case .quote:
var comment = newComment
comment.topChildrenComment?.parentCommentCount = comment.commentCount
updatedItems[itemIndex] = CommentType.quote(comment)
}
}
currentSections[sectionIndex] = CommentSection(original: section, items: updatedItems)
break
}
currentSections[sectionIndex] = CommentSection(original: section, items: updatedItems)
}
return currentSections

@ -95,6 +95,33 @@ class JournalDetailController: TableViewController {
.bind(to: viewModel.moreButtonTapped)
.disposed(by: cell.disposeBag)
cell.doubleTapGesture.rx.event.subscribe { tap in
if audioTrack.src == AudioManager.sharedInstance.currentTrack.value?.src {
viewModel.doubleTapTrigger.accept(audioTrack)
}
}.disposed(by: cell.disposeBag)
cell.tapGesture.rx.event.subscribe { tap in
guard let tap = tap.element else { return }
let location = tap.location(in: cell)
if let _ = cell.hitTest(location, with: nil) as? UIImageView ,audioTrack.src == AudioManager.sharedInstance.currentTrack.value?.src {
viewModel.tapTrigger.accept(audioTrack)
} else {
viewModel.modelSelected.accept(audioTrack)
}
}.disposed(by: cell.disposeBag)
return cell
case .journaItem(let journals):
let cell: JournalContainerViewCell = tableView.dequeueReusableCell(withIdentifier: "JournalContainerViewCell", for: indexPath) as! JournalContainerViewCell
@ -131,38 +158,88 @@ class JournalDetailController: TableViewController {
}.disposed(by: rx.disposeBag)
output.modelSelected.drive {[weak self] journalItem in
self?.deselectSelectedRow()
switch journalItem {
case .audioItem(let track):
let audioTracks: [AudioTrack] = output.items.value.flatMap { section -> [AudioTrack] in
switch section {
case .audioSection(_, let journalItems):
return journalItems.compactMap { item -> AudioTrack? in
if case .audioItem(let model) = item {
return model
} else {
return nil
}
viewModel.modelSelected.subscribe { audioTrack in
let audioTracks: [AudioTrack] = output.items.value.flatMap { section -> [AudioTrack] in
switch section {
case .audioSection(_, let journalItems):
return journalItems.compactMap { item -> AudioTrack? in
if case .audioItem(let model) = item {
return model
} else {
return nil
}
default:
return []
}
default:
return []
}
let playerViewModel = PlayerViewModel.init(track: track, provider: viewModel.provider)
self?.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal)
AudioManager.sharedInstance.changePlaylistAndPlay(audioTrack: track, audioTracks: audioTracks)
case .journaItem(_): break
}
if audioTrack.src == AudioManager.sharedInstance.currentTrack.value?.src {
print("isPlaying: \(AudioManager.sharedInstance.isPlaying())")
if AudioManager.sharedInstance.isPlaying() {
AudioManager.sharedInstance.pause()
} else {
AudioManager.sharedInstance.resume()
}
} else {
AudioManager.sharedInstance.changePlaylistAndPlay(audioTrack: audioTrack, audioTracks: audioTracks)
}
}.disposed(by: rx.disposeBag)
output.modelSelected.drive {[weak self] journalItem in
// self?.deselectSelectedRow()
//
// switch journalItem {
// case .audioItem(let track):
// let audioTracks: [AudioTrack] = output.items.value.flatMap { section -> [AudioTrack] in
// switch section {
// case .audioSection(_, let journalItems):
// return journalItems.compactMap { item -> AudioTrack? in
// if case .audioItem(let model) = item {
// return model
// } else {
// return nil
// }
// }
// default:
// return []
// }
// }
//
// print("isPlaying 1234: \(track.src) \(AudioManager.sharedInstance.currentTrack.value?.src)")
//
// if track.src == AudioManager.sharedInstance.currentTrack.value?.src {
// print("isPlaying: \(AudioManager.sharedInstance.isPlaying())")
// if AudioManager.sharedInstance.isPlaying() {
// AudioManager.sharedInstance.pause()
// } else {
// AudioManager.sharedInstance.resume()
// }
// } else {
// AudioManager.sharedInstance.changePlaylistAndPlay(audioTrack: track, audioTracks: audioTracks)
// }
// case .journaItem(_): break
// }
}.disposed(by: rx.disposeBag)
viewModel.doubleTapTrigger.subscribe { [weak self] audioTrack in
let playerViewModel = PlayerViewModel.init(track: audioTrack, provider: viewModel.provider)
self?.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal)
}.disposed(by: rx.disposeBag)
viewModel.tapTrigger.subscribe { [weak self] audioTrack in
let playerViewModel = PlayerViewModel.init(track: audioTrack, provider: viewModel.provider)
self?.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal)
}.disposed(by: rx.disposeBag)
@ -237,14 +314,10 @@ class JournalDetailController: TableViewController {
viewModel.moreButtonTapped.subscribe { [weak self] track in
guard self?.isToLoginView() == false else { return }
viewModel.item.accept(track.element)
let audioMoreActionViewModel = AudioMoreActionViewModel(audioTrack: viewModel.item, provider: viewModel.provider)
self?.navigator.show(segue: .audioMore(viewModel: audioMoreActionViewModel), sender: self, transition: .navigationPresent(type: .audioMore(false)))
}.disposed(by: rx.disposeBag)
viewModel.journalModelSelected.subscribe { [weak self] journal in
@ -306,12 +379,22 @@ class JournalDetailController: TableViewController {
AudioManager.sharedInstance.playlist.subscribe { audioTracks in
let isShow = audioTracks.element?.isEmpty == false
// if let tabbar = self.tabBarController as? HomeTabBarController {
// tabbar.toggleBars(showTabBar: false, showPlayerBar: isShow, animated: true)
// }
}.disposed(by: rx.disposeBag)
viewModel.toPlayer.subscribe { [weak self] _ in
guard let audioTrack = AudioManager.sharedInstance.currentTrack.value else { return }
let audioTracks = AudioManager.sharedInstance.playlist.value
let playerViewModel = PlayerViewModel.init(track: audioTrack, provider: viewModel.provider)
self?.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal)
}.disposed(by: rx.disposeBag)
}

@ -557,6 +557,7 @@ class JournalAudioViewCell: UITableViewCell {
coverView.layer.cornerRadius = 3
coverView.layer.masksToBounds = true
coverView.backgroundColor = .gray
coverView.isUserInteractionEnabled = true
return coverView
}()
@ -661,6 +662,9 @@ class JournalAudioViewCell: UITableViewCell {
}
}
let doubleTapGesture = UITapGestureRecognizer()
let tapGesture = UITapGestureRecognizer()
var disposeBag = DisposeBag()
//
@ -671,9 +675,23 @@ class JournalAudioViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
makeUI()
doubleTapGesture.numberOfTapsRequired = 2
tapGesture.numberOfTapsRequired = 1
tapGesture.require(toFail: doubleTapGesture)
contentView.addGestureRecognizer(tapGesture)
contentView.addGestureRecognizer(doubleTapGesture)
doubleTapGesture.delegate = self
tapGesture.delegate = self
}
@ -801,7 +819,12 @@ class JournalAudioViewCell: UITableViewCell {
}
override func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}

@ -30,10 +30,10 @@ class JournalDetailViewModel: ViewModel, ViewModelType {
let dowloadState: Driver<Float>
let isLike: BehaviorRelay<Bool>
let toShare: PublishSubject<Void>
let toPlayer: PublishRelay<Void>
}
let itemSelected = PublishSubject<JournalItem>()
let items = BehaviorRelay<[JournalSection]>.init(value: [])
@ -51,6 +51,12 @@ class JournalDetailViewModel: ViewModel, ViewModelType {
let item: BehaviorRelay<AudioTrack?> = .init(value: nil)
let doubleTapTrigger = PublishRelay<AudioTrack>()
let tapTrigger = PublishRelay<AudioTrack>()
let toPlayer = PublishRelay<Void>.init()
let modelSelected: PublishRelay<AudioTrack> = .init()
init(journal: BehaviorRelay<Journal>, provider: IndieMusicAPI) {
self.journal = journal
@ -240,7 +246,12 @@ class JournalDetailViewModel: ViewModel, ViewModelType {
}
doubleTapTrigger.subscribe { [weak self] _ in
self?.toPlayer.accept(())
}.disposed(by: rx.disposeBag)
@ -250,7 +261,8 @@ class JournalDetailViewModel: ViewModel, ViewModelType {
currentPlaying: currentPlaying,
dowloadState: dowloadState,
isLike: isLike,
toShare: toShare
toShare: toShare,
toPlayer: toPlayer
)
}

@ -103,10 +103,10 @@ class ShareActionController: ViewController {
case .poster:
guard let vc = self?.presentingViewController else { return }
self?.navigator.dismiss(sender: self)
// self?.navigator.dismiss(sender: self)
let shareCardViewModel = ShareCardViewModel.init(audioTrack: viewModel.audioTrack, journal: viewModel.journal, provider: viewModel.provider)
self?.navigator.show(segue: .shareCrad(viewModel: shareCardViewModel), sender: vc, transition: .navigationPresent(type: .share))
self?.navigator.show(segue: .shareCrad(viewModel: shareCardViewModel), sender: self, transition: .navigationPresent(type: .share))
case .url:
UIPasteboard.general.string = ""

@ -281,8 +281,8 @@ class MineMenuSubView: UIControl {
}
class MineViewCell: UITableViewCell {
lazy var coverView: UIImageView = {
let coverView = UIImageView.init()
lazy var coverView: MineCoverView = {
let coverView = MineCoverView.init(frame: .zero)
coverView.layer.cornerRadius = 3
coverView.layer.masksToBounds = true
@ -398,3 +398,69 @@ class MineViewCell: UITableViewCell {
}
}
class MineCoverView: UIImageView {
let titleLabel: UILabel = {
let titleLabel = UILabel.init()
titleLabel.font = UIFont.systemFont(ofSize: 14, weight: .medium)
titleLabel.textColor = .white
titleLabel.text = "VOL"
return titleLabel
}()
let containerView: UIView = {
let containerView = UIView.init()
containerView.layer.cornerRadius = 5
containerView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMinYCorner]
containerView.backgroundColor = .init(hex: 0x000000, alpha: 0.7)
containerView.isHidden = true
return containerView
}()
var imageUrl: String? {
didSet {
guard let imageUrl = imageUrl else {
containerView.isHidden = true
return
}
kf.setImage(with: URL.init(string: imageUrl), placeholder: UIImage.init(named: "mine_journal_img"))
containerView.isHidden = false
}
}
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(containerView)
containerView.addSubview(titleLabel)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
containerView.snp.makeConstraints { make in
make.left.equalTo(self)
make.bottom.equalTo(self)
}
titleLabel.snp.makeConstraints { make in
make.left.equalTo(containerView).offset(6)
make.bottom.equalTo(containerView).offset(-2)
make.right.equalTo(containerView).offset(-6)
make.top.equalTo(containerView).offset(2)
}
}
}

@ -224,6 +224,14 @@ class MineViewController: TableViewController {
}.disposed(by: rx.disposeBag)
viewModel.lastJournalCover.subscribe { [weak self] url in
guard let url = url.element,
let cell = self?.tableView.cellForRow(at: IndexPath.init(row: 1, section: 0)) as? MineViewCell else { return }
cell.coverView.imageUrl = url
}.disposed(by: rx.disposeBag)
}
@ -238,6 +246,7 @@ extension MineViewController {
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "MineViewCell", for: indexPath) as! MineViewCell
cell.mine = item
cell.coverView.containerView.isHidden = true
cell.playClousres = {
buttonTapHandler(cell, item)

@ -33,6 +33,8 @@ class MineViewModel: ViewModel, ViewModelType {
let playSubject = PublishRelay<Void>.init()
let lastJournalCover = PublishRelay<String>.init()
func transform(input: Input) -> Output {
let toPlay = PublishRelay<[AudioTrack]>.init()
@ -42,7 +44,7 @@ class MineViewModel: ViewModel, ViewModelType {
self.user.accept(user)
let single = Mine.init(icon: "mine_like_img", title: "单曲", detail: "\(user.songCount ?? 0)", isShowPlay: true)
let journal = Mine.init(icon: "mine_journal_img", title: "期刊", detail: "\(user.journalCount ?? 0)", isShowPlay: false)
let journal = Mine.init(icon: "", title: "期刊", detail: "\(user.journalCount ?? 0)", isShowPlay: false)
let download = Mine.init(icon: "mine_download_img", title: "下载", detail: "\(FileManager.default.downloadAudioTrackCount)", isShowPlay: false)
self.items.accept([MineSection.init(items: [single, journal, download])])
@ -52,6 +54,15 @@ class MineViewModel: ViewModel, ViewModelType {
UserDefaults.AccountInfo.set(user.nickName, forKey: .userName)
self.requestLastJournalCover().subscribe { url in
self.lastJournalCover.accept(url)
} onError: { error in
self.lastJournalCover.accept("")
}.disposed(by: self.rx.disposeBag)
} onError: { error in
self.user.accept(nil)
@ -115,5 +126,10 @@ class MineViewModel: ViewModel, ViewModelType {
.trackError(error)
}
func requestLastJournalCover() -> Observable<String> {
return self.provider.lastJournalCover()
.trackActivity(loading)
.trackError(error)
}
}

@ -211,6 +211,10 @@ extension MyFollowersViewController {
cell.followingButton.setTitle("回关", for: .normal)
cell.followingButton.setTitle("互相关注", for: .selected)
cell.followingButton.setTitleColor(.primary(), for: .normal)
cell.followingButton.setTitleColor(.tertiaryText(), for: .selected)
if item.relation == .mutualFollowing {
cell.followingButton.isSelected = true
}

@ -55,9 +55,38 @@ class MyCommentListController: TableViewController {
let output = viewModel.transform(input: input)
let dataSource = MyCommentListController.dataSource { [weak self] cell, myComment in
viewModel.item.accept(myComment)
}
let dataSource = RxTableViewSectionedReloadDataSource<MyCommentListSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: CommentListViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentListViewCell", for: indexPath) as! CommentListViewCell
cell.myComment = item
cell.avatarView.rx.tapGesture().when(.recognized)
.subscribe { tap in
guard let commenterId = item.commenterId else { return }
viewModel.avatarViewTrigger.accept(commenterId)
}.disposed(by: cell.disposeBag)
cell.audioTrackView.rx.tapGesture().when(.recognized)
.subscribe { tap in
guard let journalId = item.journalId else { return }
viewModel.journalTrigger.accept(journalId)
}.disposed(by: cell.disposeBag)
cell.commentButton.rx.tap.subscribe { _ in
viewModel.item.accept(item)
}.disposed(by: cell.disposeBag)
return cell
}
)
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
@ -133,6 +162,22 @@ class MyCommentListController: TableViewController {
}.disposed(by: rx.disposeBag)
viewModel.avatarViewTrigger.subscribe { [weak self] userID in
let personalViewModel = PersonalViewModel.init(userID: userID, provider: viewModel.provider)
self?.navigator.show(segue: .personal(viewModel: personalViewModel), sender: self)
}.disposed(by: rx.disposeBag)
viewModel.toJournalDetail.subscribe { [weak self] journal in
let value = BehaviorRelay<Journal>.init(value: journal)
let journalDetailViewModel = JournalDetailViewModel.init(journal: value, provider: viewModel.provider)
self?.navigator.show(segue: .journalDetail(viewModel: journalDetailViewModel), sender: self)
}.disposed(by: rx.disposeBag)
}
@ -152,26 +197,6 @@ class MyCommentListController: TableViewController {
}
extension MyCommentListController {
//TODO
static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, MyComment) -> Void) -> RxTableViewSectionedReloadDataSource<MyCommentListSection> {
return RxTableViewSectionedReloadDataSource<MyCommentListSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: CommentListViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentListViewCell", for: indexPath) as! CommentListViewCell
cell.myComment = item
cell.buttonTapCallback = { mineThumbup in
buttonTapHandler(cell, mineThumbup)
}
return cell
}
)
}
}
class CommentListViewCell: UITableViewCell {
@ -191,6 +216,7 @@ class CommentListViewCell: UITableViewCell {
audioTrackView.layer.masksToBounds = true
audioTrackView.backgroundColor = .init(hex: 0xf5f5f5)
audioTrackView.isUserInteractionEnabled = true
return audioTrackView
}()
@ -273,6 +299,15 @@ class CommentListViewCell: UITableViewCell {
}
}
var disposeBag = DisposeBag()
//
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none

@ -24,6 +24,7 @@ class MyCommentListViewModel: ViewModel, ViewModelType {
let items: BehaviorRelay<[MyCommentListSection]>
let item: BehaviorRelay<MyComment?>
let clearTextSubject: PublishRelay<Void>
let toJournalDetail: PublishRelay<Journal>
}
@ -32,6 +33,13 @@ class MyCommentListViewModel: ViewModel, ViewModelType {
let clearTextSubject: PublishRelay<Void> = .init()
let avatarViewTrigger: PublishRelay<String> = .init()
let journalTrigger: PublishRelay<String> = .init()
let replyButtonTrigger: PublishRelay<Void> = .init()
let toJournalDetail: PublishRelay<Journal> = .init()
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { [weak self] _ in
@ -78,12 +86,27 @@ class MyCommentListViewModel: ViewModel, ViewModelType {
}
}).disposed(by: rx.disposeBag)
journalTrigger.subscribe { journalID in
guard let journalID = journalID.element else { return }
self.requestJournalDetailByID(journalID: journalID)
.subscribe { journal in
self.toJournalDetail.accept(journal)
} onError: { error in
}.disposed(by: self.rx.disposeBag)
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
item: item,
clearTextSubject: clearTextSubject)
clearTextSubject: clearTextSubject,
toJournalDetail: toJournalDetail
)
}
@ -99,6 +122,12 @@ class MyCommentListViewModel: ViewModel, ViewModelType {
.trackError(error)
}
func requestJournalDetailByID(journalID: String) -> Observable<Journal> {
return self.provider.journalDetailByID(journalID: journalID)
.trackActivity(loading)
.trackError(error)
}
}

@ -10,7 +10,7 @@ import MarqueeLabel
class PlayerTabBar: UIControl {
var blurEffectView: BlurEffectView = {
let blurEffectView = BlurEffectView.init(style: .systemMaterial, frame: .zero)
let blurEffectView = BlurEffectView.init(style: .light, frame: .zero)
// blurEffectView.isHidden = true
blurEffectView.backgroundColor = .white
return blurEffectView
@ -92,8 +92,11 @@ class PlayerTabBar: UIControl {
func makeUI() {
// backgroundColor = .white
layer.shadowOffset = CGSize.init(width: 0, height: 7)
layer.shadowOpacity = 0.3
layer.shadowRadius = 6
layer.shadowColor = UIColor.black.cgColor
addSubview(blurEffectView)
containerView.addSubview(titleLabel)
@ -157,7 +160,7 @@ class PlayerTabBar: UIControl {
progressView.snp.makeConstraints { make in
make.left.equalTo(self).offset(30)
make.right.equalTo(self).offset(-30)
make.top.equalTo(containerView.snp.bottom)
make.bottom.equalTo(containerView.snp.bottom)
make.height.equalTo(2)
}

@ -13,6 +13,19 @@ import RxDataSources
import RxModal
class FeedbackViewController: ViewController {
let scrollView: UIScrollView = {
let scrollView = UIScrollView.init()
return scrollView
}()
let containerView: UIView = {
let containerView = UIView.init()
return containerView
}()
let feedbackTypeView: FeedbackTypeView = {
let feedbackTypeView = FeedbackTypeView.init()
@ -68,6 +81,8 @@ class FeedbackViewController: ViewController {
override func makeUI() {
view.backgroundColor = .init(hex: 0xf5f5f5)
view.addSubview(scrollView)
scrollView.addSubview(containerView)
view.addSubview(feedbackTypeView)
view.addSubview(feedbackDetailView)
@ -76,7 +91,9 @@ class FeedbackViewController: ViewController {
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}
override func bindViewModel() {
super.bindViewModel()
@ -179,27 +196,39 @@ class FeedbackViewController: ViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.snp.makeConstraints { make in
make.edges.equalTo(view)
}
containerView.snp.makeConstraints { make in
make.height.greaterThanOrEqualToSuperview()
make.edges.equalTo(scrollView)
make.width.equalToSuperview()
}
feedbackTypeView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.top.equalTo(view)
make.left.equalTo(containerView)
make.right.equalTo(containerView)
make.top.equalTo(containerView)
}
feedbackDetailView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.left.equalTo(containerView)
make.right.equalTo(containerView)
make.top.equalTo(feedbackTypeView.snp.bottom).offset(12)
}
feedbackContactView.snp.makeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.left.equalTo(containerView)
make.right.equalTo(containerView)
make.top.equalTo(feedbackDetailView.snp.bottom).offset(12)
}
confirmButton.snp.makeConstraints { make in
make.left.equalTo(view).offset(46)
make.right.equalTo(view).offset(-46)
make.left.equalTo(containerView).offset(46)
make.right.equalTo(containerView).offset(-46)
make.top.equalTo(feedbackContactView.snp.bottom).offset(30)
make.height.equalTo(44)
}
@ -428,6 +457,7 @@ class FeedbackDetailSubView: UIView {
collectionView.register(FeedbackDetailViewCell.self, forCellWithReuseIdentifier: "FeedbackDetailViewCell")
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
collectionView.isScrollEnabled = false
return collectionView
}()
@ -498,6 +528,16 @@ class FeedbackDetailSubView: UIView {
}
// override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// let hitView = super.hitTest(point, with: event)
//
// if let hitView = hitView, hitView.isDescendant(of: self) && hitView is UICollectionViewCell {
// return hitView
// }
// return nil
//
// }
}
extension FeedbackDetailSubView {

@ -81,6 +81,8 @@ protocol IndieMusicAPI {
///
func subCommentList(parentId: String, page: Int, size: Int) -> Single<[Comment]>
///
func commentDetail(commentID: String) -> Single<Comment>
///
func commentLike(commentId: String) -> Single<CommentThumbState>
///
@ -116,5 +118,9 @@ protocol IndieMusicAPI {
func deleteComment(commentId: String) -> Single<Void>
///
func thanksList() -> Single<[Thanks]>
func lastJournalCover() -> Single<String>
func journalDetailByID(journalID: String) -> Single<Journal>
}

@ -49,6 +49,7 @@ enum APIConfig {
case latestCommentList(String, Int, Int)
case subCommentList(String, Int, Int)
case commentDetail(String)
case commentLike(String, [String: Any])
case sendComment([String: Any])
@ -69,6 +70,8 @@ enum APIConfig {
case deleteComment(String)
case thanks
case lastJournalCover
case journalDetailByID(String)
}
@ -143,6 +146,8 @@ extension APIConfig: TargetType {
return "luoo-comment/comment/new/\(journalId)/\(page)/\(size)"
case .subCommentList(let parentId, let page, let size):
return "luoo-comment/comment/comment/\(parentId)/\(page)/\(size)"
case .commentDetail(let commentId):
return "luoo-comment/comment/\(commentId)"
case .commentLike(let commentID, _):
return "luoo-comment/comment/thumbup/\(commentID)"
case .sendComment:
@ -176,12 +181,17 @@ extension APIConfig: TargetType {
return "luoo-comment/comment/\(commentId)"
case .thanks:
return "user/my/thanks"
case .lastJournalCover:
return "luoo-music/journal/collectLatestImage"
case .journalDetailByID(let journalID):
return "luoo-music/journal/\(journalID)"
}
}
var method: Moya.Method {
switch self {
case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .searchSong, .searchJournal, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .suggestions, .thanks, .collectJournalSongList, .otherMessageDetail, .journalDetail:
case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .searchSong, .searchJournal, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .suggestions, .thanks, .collectJournalSongList, .otherMessageDetail, .journalDetail, .commentDetail, .lastJournalCover, .journalDetailByID:
return .get
case .sendsms, .login, .autoLogin, .editAvatar, .like, .checkVersion, .logout, .sendComment, .feedback, .commentReport, .otherMessageList:
return .post
@ -189,13 +199,14 @@ extension APIConfig: TargetType {
return .put
case .cancelLike, .deleteComment:
return .delete
}
}
var parameterEncoding: ParameterEncoding {
switch self {
case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .sendsms, .imageCheckCode, .login, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .like, .cancelLike, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .searchSong, .searchJournal, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .suggestions, .commentReport, .deleteComment, .thanks, .collectJournalSongList, .otherMessageList, .otherMessageDetail, .checkVersion, .journalDetail:
case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .sendsms, .imageCheckCode, .login, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .like, .cancelLike, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .searchSong, .searchJournal, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .suggestions, .commentReport, .deleteComment, .thanks, .collectJournalSongList, .otherMessageList, .otherMessageDetail, .checkVersion, .journalDetail, .commentDetail, .lastJournalCover, .journalDetailByID:
return URLEncoding.default
case .autoLogin, .editUserInfo, .editAvatar, .logout, .commentLike, .sendComment, .feedback:
@ -207,7 +218,7 @@ extension APIConfig: TargetType {
var task: Task {
var parameters: [String: Any] = [:]
switch self {
case .wechatAccessToken, .countryCode, .journalMusic, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .commentReport, .deleteComment, .thanks, .otherMessageList, .otherMessageDetail, .journalDetail:
case .wechatAccessToken, .countryCode, .journalMusic, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .commentReport, .deleteComment, .thanks, .otherMessageList, .otherMessageDetail, .journalDetail, .commentDetail, .lastJournalCover, .journalDetailByID:
return .requestPlain
case .login(let dic), .journalList(let dic), .sendsms(let dic), .autoLogin(let dic), .editUserInfo(let dic), .like(let dic), .cancelLike(let dic), .logout(let dic), .checkVersion(let dic), .commentLike(_, let dic), .sendComment(let dic), .collectSongList(let dic), .journalCollectList(let dic), .suggestions(let dic), .searchSong(let dic), .searchJournal(let dic), .collectJournalSongList(let dic):
@ -253,7 +264,7 @@ extension APIConfig: TargetType {
var headers : [String : String]? {
switch self {
case .autoLogin, .getUserInfo, .journalList, .journalMusic, .otherUserInfo, .like, .cancelLike, .single, .journal, .collectSongList, .journalCollectList, .followingList, .messageList, .followerList, .blackList, .editUserInfo, .logout, .editAvatar, .hotCommentList, .latestCommentList, .subCommentList, .commentLike, .filterMenu, .journalRecommend, .searchSong, .searchJournal, .randomAudioTrack, .sendComment, .myThumbupList, .myCommentReplyList, .feedback, .suggestions, .commentReport, .deleteComment, .collectJournalSongList, .otherMessageList, .journalDetail:
case .autoLogin, .getUserInfo, .journalList, .journalMusic, .otherUserInfo, .like, .cancelLike, .single, .journal, .collectSongList, .journalCollectList, .followingList, .messageList, .followerList, .blackList, .editUserInfo, .logout, .editAvatar, .hotCommentList, .latestCommentList, .subCommentList, .commentLike, .filterMenu, .journalRecommend, .searchSong, .searchJournal, .randomAudioTrack, .sendComment, .myThumbupList, .myCommentReplyList, .feedback, .suggestions, .commentReport, .deleteComment, .collectJournalSongList, .otherMessageList, .journalDetail, .commentDetail, .lastJournalCover, .journalDetailByID:
return ["Authorization": AuthManager.shared.token?.basicToken ?? ""]
default:
return nil

@ -283,6 +283,11 @@ extension RestApi {
return requestObject(.subCommentList(parentId, page, size), with: "data.rows", type: [Comment].self)
}
func commentDetail(commentID: String) -> Single<Comment> {
return requestObject(.commentDetail(commentID), with: "data", type: Comment.self)
}
func commentLike(commentId: String) -> Single<CommentThumbState> {
return requestObject(.commentLike(commentId, ["": ""]), with: "data", type: CommentThumbState.self)
}
@ -380,4 +385,13 @@ extension RestApi {
func thanksList() -> Single<[Thanks]> {
return requestObject(.thanks, with: "data", type: [Thanks].self)
}
func lastJournalCover() -> Single<String> {
return requestObject(.lastJournalCover, with: "data", type: String.self)
}
func journalDetailByID(journalID: String) -> Single<Journal> {
return requestObject(.journalDetailByID(journalID), with: "data", type: Journal.self)
}
}

Loading…
Cancel
Save