Refactor the message module, the focus module

dev
wenlei 11 months ago
parent d51519e4a1
commit 5381371839

@ -25,6 +25,10 @@
770FC3F62B92F4380023DE28 /* AVPlayer+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F22B92F4380023DE28 /* AVPlayer+Rx.swift */; }; 770FC3F62B92F4380023DE28 /* AVPlayer+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F22B92F4380023DE28 /* AVPlayer+Rx.swift */; };
770FC3F72B92F4380023DE28 /* AVPlayerItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F32B92F4380023DE28 /* AVPlayerItem+Rx.swift */; }; 770FC3F72B92F4380023DE28 /* AVPlayerItem+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F32B92F4380023DE28 /* AVPlayerItem+Rx.swift */; };
770FC3F82B92F4380023DE28 /* AVPlayerLayer+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F42B92F4380023DE28 /* AVPlayerLayer+Rx.swift */; }; 770FC3F82B92F4380023DE28 /* AVPlayerLayer+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F42B92F4380023DE28 /* AVPlayerLayer+Rx.swift */; };
770FC3FA2B9319FC0023DE28 /* PrivateMessageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3F92B9319FC0023DE28 /* PrivateMessageViewController.swift */; };
770FC3FC2B931A370023DE28 /* OtherMessageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3FB2B931A370023DE28 /* OtherMessageViewController.swift */; };
770FC3FE2B9325B60023DE28 /* MyFollowersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3FD2B9325B60023DE28 /* MyFollowersViewController.swift */; };
770FC4002B9327E20023DE28 /* BlackListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770FC3FF2B9327E20023DE28 /* BlackListViewController.swift */; };
771233EC2B6B6476009FAF01 /* UIButton+IndieMusic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 771233EB2B6B6476009FAF01 /* UIButton+IndieMusic.swift */; }; 771233EC2B6B6476009FAF01 /* UIButton+IndieMusic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 771233EB2B6B6476009FAF01 /* UIButton+IndieMusic.swift */; };
771233EE2B6B8CE6009FAF01 /* NavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 771233ED2B6B8CE6009FAF01 /* NavigationBar.swift */; }; 771233EE2B6B8CE6009FAF01 /* NavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 771233ED2B6B8CE6009FAF01 /* NavigationBar.swift */; };
77165D742B464493002AE0A5 /* BarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77165D732B464493002AE0A5 /* BarButtonItem.swift */; }; 77165D742B464493002AE0A5 /* BarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77165D732B464493002AE0A5 /* BarButtonItem.swift */; };
@ -293,6 +297,10 @@
770FC3F22B92F4380023DE28 /* AVPlayer+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayer+Rx.swift"; sourceTree = "<group>"; }; 770FC3F22B92F4380023DE28 /* AVPlayer+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayer+Rx.swift"; sourceTree = "<group>"; };
770FC3F32B92F4380023DE28 /* AVPlayerItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayerItem+Rx.swift"; sourceTree = "<group>"; }; 770FC3F32B92F4380023DE28 /* AVPlayerItem+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayerItem+Rx.swift"; sourceTree = "<group>"; };
770FC3F42B92F4380023DE28 /* AVPlayerLayer+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayerLayer+Rx.swift"; sourceTree = "<group>"; }; 770FC3F42B92F4380023DE28 /* AVPlayerLayer+Rx.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVPlayerLayer+Rx.swift"; sourceTree = "<group>"; };
770FC3F92B9319FC0023DE28 /* PrivateMessageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateMessageViewController.swift; sourceTree = "<group>"; };
770FC3FB2B931A370023DE28 /* OtherMessageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OtherMessageViewController.swift; sourceTree = "<group>"; };
770FC3FD2B9325B60023DE28 /* MyFollowersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyFollowersViewController.swift; sourceTree = "<group>"; };
770FC3FF2B9327E20023DE28 /* BlackListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlackListViewController.swift; sourceTree = "<group>"; };
771233EB2B6B6476009FAF01 /* UIButton+IndieMusic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+IndieMusic.swift"; sourceTree = "<group>"; }; 771233EB2B6B6476009FAF01 /* UIButton+IndieMusic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+IndieMusic.swift"; sourceTree = "<group>"; };
771233ED2B6B8CE6009FAF01 /* NavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = "<group>"; }; 771233ED2B6B8CE6009FAF01 /* NavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = "<group>"; };
77165D732B464493002AE0A5 /* BarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonItem.swift; sourceTree = "<group>"; }; 77165D732B464493002AE0A5 /* BarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarButtonItem.swift; sourceTree = "<group>"; };
@ -696,6 +704,8 @@
children = ( children = (
77C9B9DA2B4BC40F0006C83F /* FollowersViewController.swift */, 77C9B9DA2B4BC40F0006C83F /* FollowersViewController.swift */,
77C9B9DC2B4BC5D20006C83F /* FollowersViewModel.swift */, 77C9B9DC2B4BC5D20006C83F /* FollowersViewModel.swift */,
770FC3FD2B9325B60023DE28 /* MyFollowersViewController.swift */,
770FC3FF2B9327E20023DE28 /* BlackListViewController.swift */,
); );
path = Followers; path = Followers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1148,6 +1158,8 @@
children = ( children = (
77FB7A7A2B4A4FC900B64030 /* MessageViewController.swift */, 77FB7A7A2B4A4FC900B64030 /* MessageViewController.swift */,
77FB7A7C2B4A4FD400B64030 /* MessageViewModel.swift */, 77FB7A7C2B4A4FD400B64030 /* MessageViewModel.swift */,
770FC3F92B9319FC0023DE28 /* PrivateMessageViewController.swift */,
770FC3FB2B931A370023DE28 /* OtherMessageViewController.swift */,
); );
path = Message; path = Message;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1441,6 +1453,7 @@
77FA0B302B0C4D5A00404C5E /* ShareActionController.swift in Sources */, 77FA0B302B0C4D5A00404C5E /* ShareActionController.swift in Sources */,
778B8AA82AF8ED0E0034AFD4 /* Color.swift in Sources */, 778B8AA82AF8ED0E0034AFD4 /* Color.swift in Sources */,
770228EB2B55174D00E07F7A /* InternationalNumberViewModel.swift in Sources */, 770228EB2B55174D00E07F7A /* InternationalNumberViewModel.swift in Sources */,
770FC3FA2B9319FC0023DE28 /* PrivateMessageViewController.swift in Sources */,
778B8AAE2AF8ED0E0034AFD4 /* TextView.swift in Sources */, 778B8AAE2AF8ED0E0034AFD4 /* TextView.swift in Sources */,
778B8A9B2AF8ECFC0034AFD4 /* AuthManager.swift in Sources */, 778B8A9B2AF8ECFC0034AFD4 /* AuthManager.swift in Sources */,
778B8AAF2AF8ED0E0034AFD4 /* UIColor+IndieMusic.swift in Sources */, 778B8AAF2AF8ED0E0034AFD4 /* UIColor+IndieMusic.swift in Sources */,
@ -1495,6 +1508,7 @@
7773EBFA2B8B3D4D0054CFE6 /* CircularIndicatorView.swift in Sources */, 7773EBFA2B8B3D4D0054CFE6 /* CircularIndicatorView.swift in Sources */,
7751D37A2B450BB100F1F2BD /* AgreementViewController.swift in Sources */, 7751D37A2B450BB100F1F2BD /* AgreementViewController.swift in Sources */,
778B8AAB2AF8ED0E0034AFD4 /* UIView+Borders.swift in Sources */, 778B8AAB2AF8ED0E0034AFD4 /* UIView+Borders.swift in Sources */,
770FC3FC2B931A370023DE28 /* OtherMessageViewController.swift in Sources */,
778B8AC12AF8ED280034AFD4 /* TableView.swift in Sources */, 778B8AC12AF8ED280034AFD4 /* TableView.swift in Sources */,
778B8A9C2AF8ECFC0034AFD4 /* LogManager.swift in Sources */, 778B8A9C2AF8ECFC0034AFD4 /* LogManager.swift in Sources */,
778B8A992AF8ECFC0034AFD4 /* Reachability.swift in Sources */, 778B8A992AF8ECFC0034AFD4 /* Reachability.swift in Sources */,
@ -1528,6 +1542,7 @@
778B8A862AF8ECE50034AFD4 /* SearchViewModel.swift in Sources */, 778B8A862AF8ECE50034AFD4 /* SearchViewModel.swift in Sources */,
77C9B9DD2B4BC5D20006C83F /* FollowersViewModel.swift in Sources */, 77C9B9DD2B4BC5D20006C83F /* FollowersViewModel.swift in Sources */,
778B8A802AF8ECE50034AFD4 /* MineViewController.swift in Sources */, 778B8A802AF8ECE50034AFD4 /* MineViewController.swift in Sources */,
770FC3FE2B9325B60023DE28 /* MyFollowersViewController.swift in Sources */,
770FC3EF2B92C8130023DE28 /* Array+IndieMusic.swift in Sources */, 770FC3EF2B92C8130023DE28 /* Array+IndieMusic.swift in Sources */,
778B8A8F2AF8ECF20034AFD4 /* EmptyModel.swift in Sources */, 778B8A8F2AF8ECF20034AFD4 /* EmptyModel.swift in Sources */,
778B8ABD2AF8ED280034AFD4 /* View.swift in Sources */, 778B8ABD2AF8ED280034AFD4 /* View.swift in Sources */,
@ -1603,6 +1618,7 @@
77A60D862B5B97C300D4E435 /* CachingAVURLAsset.swift in Sources */, 77A60D862B5B97C300D4E435 /* CachingAVURLAsset.swift in Sources */,
778B8A9A2AF8ECFC0034AFD4 /* AudioManager.swift in Sources */, 778B8A9A2AF8ECFC0034AFD4 /* AudioManager.swift in Sources */,
774A180E2B07000C00F56DF1 /* JournalDetailView.swift in Sources */, 774A180E2B07000C00F56DF1 /* JournalDetailView.swift in Sources */,
770FC4002B9327E20023DE28 /* BlackListViewController.swift in Sources */,
77AC35712B6CE8E200D046C2 /* ShareCardViewController.swift in Sources */, 77AC35712B6CE8E200D046C2 /* ShareCardViewController.swift in Sources */,
778B8A842AF8ECE50034AFD4 /* HomeTabBarController.swift in Sources */, 778B8A842AF8ECE50034AFD4 /* HomeTabBarController.swift in Sources */,
77DFA9C52B4E8388005B8B13 /* MineDownloadViewController.swift in Sources */, 77DFA9C52B4E8388005B8B13 /* MineDownloadViewController.swift in Sources */,

@ -101,44 +101,28 @@ class NavigationController: UINavigationController {
extension NavigationController { extension NavigationController {
override func pushViewController(_ viewController: UIViewController, animated: Bool) override func pushViewController(_ viewController: UIViewController, animated: Bool)
{ {
guard let tabbar = self.tabBarController as? HomeTabBarController else { return }
if !children.isEmpty { if !children.isEmpty {
// viewController.hidesBottomBarWhenPushed = true
// if children.count > 1 {
// viewController.hidesBottomBarWhenPushed = false if viewController is JournalDetailController {
// } let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
if let tabbar = self.tabBarController as? HomeTabBarController { tabbar.toggleBars(showTabBar: false, showPlayerBar: isShowPlayBar, animated: true)
tabbar.showAllBar(false, 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)
} }
// viewController.hidesBottomBarWhenPushed = true
// let leftButton = UIButton.init()
// leftButton.setTitle("", for: .normal)
// leftButton.setImage(UIImage.init(named: "nav_back_btn"), for: .normal)
// leftButton.addTarget(self, action: #selector(backAction), for: .touchUpInside)
//
// let navLeftButton = UIBarButtonItem.init(customView: leftButton)
// navLeftButton.accessibilityLabel = ""
// viewController.navigationItem.leftBarButtonItem = navLeftButton
//
// let leftBarBtn = UIBarButtonItem(title: "", style: .plain, target: self,action: #selector(backAction))
// leftBarBtn.image = UIImage(named: "nav_back_icon")
// self.navigationItem.leftBarButtonItem = leftBarBtn
// let button = UIButton.init()
// button.setImage(UIImage(named:"nav_back_btn"), for: .normal)
//// button.setTitle("1", for: .normal)
// button.addTarget(self, action: #selector(backAction), for: .touchUpInside)
//
// let leftBarBtn = UIBarButtonItem(customView: button)
//
// //
// let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil,
// action: nil)
// spacer.width = -10
//
// self.navigationItem.leftBarButtonItem = leftBarBtn
} }
super.pushViewController(viewController, animated: animated) super.pushViewController(viewController, animated: animated)
} }

@ -62,6 +62,8 @@ struct BaseDimensions {
static let bottomHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height > 20.0 ? 34.0 : 0 static let bottomHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height > 20.0 ? 34.0 : 0
/// tab /// tab
static let tabBarHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height > 20.0 ? 83.0 : 49.0 static let tabBarHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height > 20.0 ? 83.0 : 49.0
/// Bar
static let playBarHeight: CGFloat = 66
static let inset: CGFloat = 8 static let inset: CGFloat = 8
static let borderWidth: CGFloat = 1 static let borderWidth: CGFloat = 1

@ -221,6 +221,8 @@ class AudioManager {
player.play() player.play()
NotificationCenter.default.post(name: .notiPlayResume, object: nil) NotificationCenter.default.post(name: .notiPlayResume, object: nil)
} else if let track = playlist.value.first {
playTrack(track: track)
} }
} }

@ -8,13 +8,10 @@
import Foundation import Foundation
import RxDataSources import RxDataSources
enum FollowersType: Codable {
case followers
case blackList
}
struct FollowersSection { struct FollowersSection {
var followersType: FollowersType // var followersType: FollowersType
var items: [User] var items: [User]
} }

@ -18,6 +18,18 @@ enum CustomMessageType: Codable {
case like(String) case like(String)
case follow(String) case follow(String)
var content: String {
switch self {
case .comment(let string):
return string
case .like(let string):
return string
case .follow(let string):
return string
}
}
var description: String { var description: String {
switch self { switch self {
case .comment: case .comment:
@ -55,9 +67,9 @@ enum CustomMessageType: Codable {
struct MessageList: Codable { struct MessageList: Codable {
let comment: Message let comment: Message?
let follow: Message let follow: Message?
let thumbup: Message let thumbup: Message?
} }

@ -133,11 +133,16 @@ class HomeTabBarController: UITabBarController, Navigatable {
} }
playerTabBar.snp.makeConstraints { make in playerTabBar.snp.makeConstraints { make in
make.left.equalTo(view) make.left.right.equalTo(view)
make.right.equalTo(view) make.bottom.equalTo(view)
make.bottom.equalTo(customeTabBar.snp.top).offset(BaseDimensions.tabBarHeight) if !self.customeTabBar.isHidden {
make.height.equalTo(BaseDimensions.bottomHeight + BaseDimensions.tabBarHeight + BaseDimensions.playBarHeight)
} else {
make.height.equalTo(BaseDimensions.bottomHeight + BaseDimensions.playBarHeight)
}
} }
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
@ -275,7 +280,6 @@ class HomeTabBarController: UITabBarController, Navigatable {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
} }
override func viewWillDisappear(_ animated: Bool) { override func viewWillDisappear(_ animated: Bool) {
@ -283,180 +287,55 @@ class HomeTabBarController: UITabBarController, Navigatable {
} }
func showAllBar(_ isShowing: Bool, animated: Bool) { func toggleBars(showTabBar: Bool, showPlayerBar: Bool, animated: Bool) {
if isAnimating { return } if isAnimating { return }
isAnimating = true isAnimating = true
if showTabBar {
self.customeTabBar.isHidden = false
if isShowing {
customeTabBar.isHidden = false
if AudioManager.sharedInstance.currentTrack != nil {
playerTabBar.isHidden = false
}
customeTabBar.snp.remakeConstraints { make in customeTabBar.snp.remakeConstraints { make in
make.left.equalTo(view) make.left.right.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(view) make.bottom.equalTo(view)
make.height.equalTo(BaseDimensions.tabBarHeight) make.height.equalTo(BaseDimensions.tabBarHeight)
} }
playerTabBar.snp.remakeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(customeTabBar.snp.top)
}
} else { } else {
customeTabBar.snp.remakeConstraints { make in customeTabBar.snp.remakeConstraints { make in
make.left.equalTo(view) make.left.right.equalTo(view)
make.right.equalTo(view) make.bottom.equalTo(view).offset(BaseDimensions.tabBarHeight)
make.bottom.equalTo(view).offset(self.tabBar.bounds.height)
make.height.equalTo(BaseDimensions.tabBarHeight) make.height.equalTo(BaseDimensions.tabBarHeight)
} }
playerTabBar.snp.remakeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(customeTabBar.snp.top).offset(BaseDimensions.tabBarHeight)
}
}
var animationDuration = 0.3
if animated == false {
animationDuration = 0
}
UIView.animate(withDuration: animationDuration) {
if isShowing {
self.customeTabBar.alpha = 1
self.playerTabBar.alpha = 1
} else {
self.customeTabBar.alpha = 0
self.playerTabBar.alpha = 0
}
self.view.layoutIfNeeded()
} completion: { completed in
self.isTabBarShowing = isShowing
self.isPlayerBarShowing = isShowing
self.customeTabBar.isHidden = !isShowing
if AudioManager.sharedInstance.currentTrack != nil {
self.playerTabBar.isHidden = !isShowing
}
self.isAnimating = false
}
} }
open func showTabBar(_ isShowing: Bool, animated: Bool) { if showPlayerBar {
if isAnimating { return } playerTabBar.snp.remakeConstraints { make in
make.left.right.equalTo(view)
isAnimating = true
if isShowing {
customeTabBar.isHidden = false
customeTabBar.snp.remakeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(view) make.bottom.equalTo(view)
make.height.equalTo(BaseDimensions.tabBarHeight) if showTabBar {
} make.height.equalTo( BaseDimensions.tabBarHeight + BaseDimensions.playBarHeight)
} else {
customeTabBar.snp.remakeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(view).offset(self.tabBar.bounds.height)
make.height.equalTo(BaseDimensions.tabBarHeight)
}
}
var animationDuration = 0.3
if animated == false {
animationDuration = 0
}
UIView.animate(withDuration: animationDuration,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.25,
options: .curveEaseInOut,
animations: {
if isShowing {
self.customeTabBar.alpha = 1
} else { } else {
self.customeTabBar.alpha = 0 make.height.equalTo(BaseDimensions.bottomHeight + BaseDimensions.playBarHeight)
}
self.view.layoutIfNeeded()
}) { (completed) in
self.isTabBarShowing = isShowing
self.customeTabBar.isHidden = !isShowing
self.isAnimating = false
} }
} }
open func showPlayerBar(_ isShowing: Bool, animated: Bool) {
if isAnimating { return }
isAnimating = true
if isShowing {
playerTabBar.isHidden = false
playerTabBar.snp.remakeConstraints { make in
make.left.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(customeTabBar.snp.top)
}
} else { } else {
playerTabBar.snp.remakeConstraints { make in playerTabBar.snp.remakeConstraints { make in
make.left.equalTo(view) make.left.right.equalTo(view)
make.right.equalTo(view)
make.bottom.equalTo(customeTabBar.snp.top).offset(BaseDimensions.tabBarHeight) make.bottom.equalTo(customeTabBar.snp.top).offset(BaseDimensions.tabBarHeight)
} }
} }
var animationDuration = 0.3
if animated == false {
animationDuration = 0
}
UIView.animate(withDuration: animationDuration,
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.25,
options: .curveEaseInOut,
animations: {
if isShowing { let animationDuration = animated ? 0.35 : 0
self.playerTabBar.alpha = 1
} else { UIView.animate(withDuration: animationDuration, animations: {
self.playerTabBar.alpha = 0
}
self.view.layoutIfNeeded() self.view.layoutIfNeeded()
}) { (completed) in }) { completed in
self.isPlayerBarShowing = isShowing self.isTabBarShowing = showTabBar
self.playerTabBar.isHidden = !isShowing self.isPlayerBarShowing = showPlayerBar
self.customeTabBar.isHidden = !showTabBar
self.playerTabBar.isHidden = !showPlayerBar
self.isAnimating = false self.isAnimating = false
} }
} }

@ -53,12 +53,19 @@ class HomeViewController: TableViewController, ScrollableNavBar {
self.navigationItem.leftBarButtonItem = nil self.navigationItem.leftBarButtonItem = nil
if let tabbar = self.tabBarController as? HomeTabBarController { if let tabbar = self.tabBarController as? HomeTabBarController {
if tabbar.customeTabBar.isHidden == true && tabbar.playerTabBar.isHidden == true { // if tabbar.customeTabBar.isHidden == true && tabbar.playerTabBar.isHidden == true {
tabbar.showAllBar(true, animated: true) // tabbar.showAllBar(true, animated: true)
} else if tabbar.playerTabBar.isHidden == true { // } else if tabbar.playerTabBar.isHidden == true {
//
// tabbar.showPlayerBar(true, animated: true)
// }
let isShowPlayBar = AudioManager.sharedInstance.currentTrack.value != nil
tabbar.playerTabBar.audioTrack = AudioManager.sharedInstance.currentTrack.value tabbar.playerTabBar.audioTrack = AudioManager.sharedInstance.currentTrack.value
tabbar.showPlayerBar(true, animated: true) tabbar.toggleBars(showTabBar: true, showPlayerBar: isShowPlayBar, animated: true)
}
} }
if let navigationBar = self.navigationController?.navigationBar as? NavigationBar { if let navigationBar = self.navigationController?.navigationBar as? NavigationBar {

@ -308,6 +308,15 @@ class JournalDetailController: TableViewController {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
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)
} }
@ -316,13 +325,19 @@ class JournalDetailController: TableViewController {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()
commentToolView.snp.makeConstraints { make in commentToolView.snp.remakeConstraints { make in
make.left.equalTo(view) make.left.equalTo(view)
make.right.equalTo(view) make.right.equalTo(view)
if AudioManager.sharedInstance.playlist.value.isEmpty == false {
make.bottom.equalTo(view).offset(-BaseDimensions.playBarHeight - 10)
} else {
make.bottom.equalTo(view) make.bottom.equalTo(view)
}
make.height.equalTo(BaseDimensions.bottomHeight + 48) make.height.equalTo(BaseDimensions.bottomHeight + 48)
} }
tableView.snp.remakeConstraints { make in tableView.snp.remakeConstraints { make in
make.left.equalTo(view) make.left.equalTo(view)
make.right.equalTo(view) make.right.equalTo(view)

@ -1076,11 +1076,33 @@ class JournalAudioCollectionViewCell: UICollectionViewCell {
coverView.kf.setImage(with: URL.init(string: audioTrack.pic ?? "")) coverView.kf.setImage(with: URL.init(string: audioTrack.pic ?? ""))
if AudioManager.sharedInstance.currentTrack.value?.id == audioTrack.id {
musicIndicator.state = AudioManager.sharedInstance.isPlaying() ? .playing : .paused musicIndicator.state = AudioManager.sharedInstance.isPlaying() ? .playing : .paused
} else {
self.musicIndicator.state = .stopped
}
AudioManager.sharedInstance.isPlayingState.subscribe { [weak self] isPlaying in
if AudioManager.sharedInstance.currentTrack.value?.id == audioTrack.id {
self?.musicIndicator.state = AudioManager.sharedInstance.isPlaying() ? .playing : .paused
} else {
self?.musicIndicator.state = .stopped
}
}.disposed(by: disposeBag)
} }
} }
var disposeBag = DisposeBag()
//
override func prepareForReuse() {
super.prepareForReuse()
disposeBag = DisposeBag()
}
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)

@ -12,6 +12,11 @@ import RxDataSources
import FSPopoverView import FSPopoverView
class MessageViewController: ViewController, UIScrollViewDelegate { class MessageViewController: ViewController, UIScrollViewDelegate {
var pageViewController: UIPageViewController!
var pages = [UIViewController]()
let currentPageIndex = BehaviorRelay<Int>(value: 0)
let messageTopView: MessageTopView = { let messageTopView: MessageTopView = {
let messageTopView = MessageTopView.init() let messageTopView = MessageTopView.init()
@ -19,83 +24,48 @@ class MessageViewController: ViewController, UIScrollViewDelegate {
return messageTopView return messageTopView
}() }()
var tableView: UITableView = {
let tableView = UITableView.init()
tableView.register(MessageCellView.self, forCellReuseIdentifier: "MessageCellView")
tableView.register(MessageActivitiesViewCell.self, forCellReuseIdentifier: "MessageActivitiesViewCell")
return tableView override func viewDidLoad() {
}() super.viewDidLoad()
private let menuView: PopoverListView = {
let menuView = PopoverListView.init(scrollDirection: .horizontal)
do {
let features: [PopoverMenu] = [.blockList, .delete]
let items: [FSPopoverListItem] = features.map { feature in
let item = FSPopoverListTextItem(scrollDirection: .horizontal)
item.title = feature.description
item.titleFont = UIFont.systemFont(ofSize: 12)
item.isSeparatorHidden = false
item.titleColor = .white
item.contentInset = .init(top: 9, left: 15, bottom: 9, right: 15)
item.selectedHandler = { item in
guard let item = item as? FSPopoverListTextItem else {
return
} }
print(item.title ?? "")
}
item.updateLayout()
return item
}
items.last?.isSeparatorHidden = true
menuView.shadowOpacity = 0
menuView.shadowRadius = 0
menuView.shadowColor = .clear
menuView.items = items
menuView.cornerRadius = 3
menuView.transitioningDelegate = nil
menuView.arrowSize = CGSize.init(width: 18, height: 5) override func makeUI() {
menuView.backgroundColor = .primaryText() super.makeUI()
self.navigationItem.title = "消息列表"
messageTopView.segmentControl.titleBtnOnClick = { [weak self] (label, index) in
if index == 0 {
self?.goToNextPage()
} else {
self?.goToPreviousPage()
} }
return menuView
}()
}
let headerRefreshTrigger = PublishSubject<Void>()
let footerRefreshTrigger = PublishSubject<Void>()
let isHeaderLoading = BehaviorRelay(value: false) guard let viewModel = viewModel as? MessageViewModel else { return }
let isFooterLoading = BehaviorRelay(value: false)
let messageType = BehaviorRelay<MessageType>.init(value: .message)
let privateMessageViewModel = PrivateMessageViewModel.init(provider: viewModel.provider)
override func viewDidLoad() { let privateMessage = PrivateMessageViewController.init(viewModel: privateMessageViewModel, navigator: self.navigator)
super.viewDidLoad()
let otherMessageViewModel = OtherMessageViewModel.init(provider: viewModel.provider)
} let otherMessage = OtherMessageViewController.init(viewModel: otherMessageViewModel, navigator: self.navigator)
override func makeUI() { pages.append(privateMessage)
super.makeUI() pages.append(otherMessage)
messageTopView.segmentControl.titleBtnOnClick = { [weak self] (label, index) in
if index == 0 {
self?.messageType.accept(.message)
} else {
self?.messageType.accept(.activities)
}
} setupPageViewController()
self.navigationItem.title = "消息列表" view.addSubview(messageTopView)
tableView.rx.setDelegate(self).disposed(by: rx.disposeBag) view.backgroundColor = .white
view.addSubview(messageTopView)
view.addSubview(tableView)
} }
override func bindViewModel() { override func bindViewModel() {
@ -103,40 +73,26 @@ class MessageViewController: ViewController, UIScrollViewDelegate {
// self.segmentControl.currentSearchType = .single
guard let viewModel = viewModel as? MessageViewModel else { return } guard let viewModel = viewModel as? MessageViewModel else { return }
let refresh = Observable.of(Observable.just(()), headerRefreshTrigger).merge() let input = MessageViewModel.Input.init(viewWillAppear: rx.viewWillAppear)
let input = MessageViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
headerRefresh: refresh,
footerRefresh: footerRefreshTrigger,
messageType: messageType,
modelSelected: tableView.rx.modelSelected(MessageSectionItem.self).asDriver())
let output = viewModel.transform(input: input) let output = viewModel.transform(input: input)
let dataSource = MessageViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.modelSelected.drive { [weak self] messageSectionItem in pageViewController.rx.didFinishAnimating.subscribe { [weak self] (isFinished, previousViewControllers, completed) in
switch messageSectionItem {
case .customMessage(let customMessageType):
self?.navigateToScreen(customMessageType: customMessageType)
case .messageItem(let message): break
case .activitiesItem(let message): break
if let privateMessage = self?.pageViewController.viewControllers?.first as? PrivateMessageViewController {
self?.messageTopView.segmentControl.selectedIndex(0, animated: true)
} else {
self?.messageTopView.segmentControl.selectedIndex(1, animated: true)
} }
}.disposed(by: rx.disposeBag)
}.disposed(by: rx.disposeBag)
} }
@ -146,22 +102,19 @@ class MessageViewController: ViewController, UIScrollViewDelegate {
messageTopView.snp.makeConstraints { make in messageTopView.snp.makeConstraints { make in
make.top.equalTo(view)
make.left.equalTo(view) make.left.equalTo(view)
make.right.equalTo(view) make.right.equalTo(view)
make.height.equalTo(49) make.top.equalTo(view)
} }
pageViewController.view.snp.remakeConstraints { make in
tableView.snp.makeConstraints { make in
make.top.equalTo(messageTopView.snp.bottom)
make.left.equalTo(view) make.left.equalTo(view)
make.right.equalTo(view) make.right.equalTo(view)
make.top.equalTo(messageTopView.snp.bottom)
make.bottom.equalTo(view) make.bottom.equalTo(view)
} }
} }
func navigateToScreen(customMessageType: CustomMessageType) { func navigateToScreen(customMessageType: CustomMessageType) {
guard let viewModel = viewModel as? MessageViewModel else { return } guard let viewModel = viewModel as? MessageViewModel else { return }
@ -179,7 +132,36 @@ class MessageViewController: ViewController, UIScrollViewDelegate {
} }
private func setupPageViewController() {
pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
pageViewController.dataSource = self
if let firstViewController = pages.first {
pageViewController.setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)
}
addChild(pageViewController)
view.addSubview(pageViewController.view)
pageViewController.didMove(toParent: self)
}
func goToNextPage() {
guard let currentViewController = pageViewController?.viewControllers?.first,
let nextPage = pages.first else {
return
}
pageViewController?.setViewControllers([nextPage], direction: .reverse, animated: true, completion: nil)
}
func goToPreviousPage() {
guard let currentViewController = pageViewController?.viewControllers?.first,
let previousPage = pages.last else {
return
}
pageViewController?.setViewControllers([previousPage], direction: .forward, animated: true, completion: nil)
}
} }
@ -221,6 +203,47 @@ extension MessageViewController {
} }
extension MessageViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.firstIndex(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard pages.count > previousIndex else {
return nil
}
return pages[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.firstIndex(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let pagesCount = pages.count
guard pagesCount != nextIndex else {
return nil
}
guard pagesCount > nextIndex else {
return nil
}
return pages[nextIndex]
}
}
class MessageTopView: UIView { class MessageTopView: UIView {
@ -282,13 +305,15 @@ class MessageTopView: UIView {
segmentControl.snp.makeConstraints { make in segmentControl.snp.makeConstraints { make in
make.width.equalTo(185) make.width.equalTo(185)
make.height.equalTo(44) make.height.equalTo(44)
make.center.equalTo(self) make.top.equalTo(self)
make.centerX.equalTo(self)
} }
lineView.snp.makeConstraints { make in lineView.snp.makeConstraints { make in
make.left.equalTo(self) make.left.equalTo(self)
make.right.equalTo(self) make.right.equalTo(self)
make.bottom.equalTo(self) make.bottom.equalTo(self)
make.top.equalTo(segmentControl.snp.bottom)
make.height.equalTo(6) make.height.equalTo(6)
} }
@ -370,7 +395,13 @@ class MessageCellView: UITableViewCell {
avatarView.image = UIImage.init(named: customMessageType.image) avatarView.image = UIImage.init(named: customMessageType.image)
nameLabel.text = customMessageType.description nameLabel.text = customMessageType.description
if customMessageType.content == "" {
detailLabel.text = "暂无\(customMessageType.description)"
} else {
detailLabel.text = customMessageType.detail detailLabel.text = customMessageType.detail
}
} }
} }

@ -14,20 +14,10 @@ class MessageViewModel: ViewModel, ViewModelType {
struct Input { struct Input {
let viewWillAppear: ControlEvent<Bool> let viewWillAppear: ControlEvent<Bool>
let headerRefresh: Observable<Void> // let messageType: BehaviorRelay<MessageType>
let footerRefresh: Observable<Void>
let messageType: BehaviorRelay<MessageType>
let modelSelected: Driver<MessageSectionItem>
} }
struct Output { struct Output {
let messageItems: PublishRelay<[MessageSection]>
let activitiesItems: PublishRelay<[MessageSection]>
let items: BehaviorRelay<[MessageSection]>
let selection: PublishSubject<MessageSectionItem>
let modelSelected: Driver<MessageSectionItem>
} }
@ -86,72 +76,64 @@ class MessageViewModel: ViewModel, ViewModelType {
// self.items.accept([MessageSection.activities(items: new)]) } // self.items.accept([MessageSection.activities(items: new)]) }
// }).disposed(by: rx.disposeBag) // }).disposed(by: rx.disposeBag)
input.messageType.subscribe { [weak self] messageType in // input.messageType.subscribe { [weak self] messageType in
guard let self = self, let messageType = messageType.element else { return } // guard let self = self, let messageType = messageType.element else { return }
self.messageType.accept(messageType) // self.messageType.accept(messageType)
//
print("messageType \(messageType)") // print("messageType \(messageType)")
self.page = 1 // self.page = 1
switch messageType { // switch messageType {
case .message: // case .message:
//
self.requestMessageList() // self.requestMessageList()
.subscribe { messageList in // .subscribe { messageList in
var items = [messageList.comment, messageList.thumbup, messageList.follow] // var items = [messageList.comment, messageList.thumbup, messageList.follow]
//
let comment = MessageSectionItem.customMessage(customMessageType: .comment(messageList.comment.sendUserNickName ?? "")) // let comment = MessageSectionItem.customMessage(customMessageType: .comment(messageList.comment.sendUserNickName ?? ""))
let thumbup = MessageSectionItem.customMessage(customMessageType: .like(messageList.thumbup.sendUserNickName ?? "")) // let thumbup = MessageSectionItem.customMessage(customMessageType: .like(messageList.thumbup.sendUserNickName ?? ""))
let follow = MessageSectionItem.customMessage(customMessageType: .follow(messageList.follow.sendUserNickName ?? "")) // let follow = MessageSectionItem.customMessage(customMessageType: .follow(messageList.follow.sendUserNickName ?? ""))
//
//
//
self.messageItems.accept([MessageSection.message(items: [comment, thumbup, follow])]) // self.messageItems.accept([MessageSection.message(items: [comment, thumbup, follow])])
} onError: { error in // } onError: { error in
//
}.disposed(by: self.rx.disposeBag) // }.disposed(by: self.rx.disposeBag)
//
// case .activities: break
// }
//
//
//
// }.disposed(by: rx.disposeBag)
case .activities: break
}
// let cuttentItems = Observable.merge(messageItems.asObservable(), activitiesItems.asObservable())
//
// cuttentItems.subscribe { [weak self] followersSections in
// guard let self = self else { return }
//
// if self.messageType.value == .activities {
//
// } else {
// self.items.accept(followersSections)
// }
//
// }.disposed(by: rx.disposeBag)
}.disposed(by: rx.disposeBag)
let cuttentItems = Observable.merge(messageItems.asObservable(), activitiesItems.asObservable())
cuttentItems.subscribe { [weak self] followersSections in return Output.init()
guard let self = self else { return }
if self.messageType.value == .activities {
} else {
self.items.accept(followersSections)
} }
}.disposed(by: rx.disposeBag)
return Output.init(messageItems: messageItems,
activitiesItems: activitiesItems,
items: items,
selection: selection,
modelSelected: input.modelSelected)
}
func requestMessageList() -> Observable<MessageList> {
return self.provider.messageList()
.trackActivity(loading)
.trackError(error)
}
// func requestActivitiesList(page: Int, size: Int) -> Observable<[Message]> { // func requestActivitiesList(page: Int, size: Int) -> Observable<[Message]> {
// return self.provider.messageList(page: page, size: size) // return self.provider.messageList(page: page, size: size)
// .trackActivity(loading) // .trackActivity(loading)

@ -0,0 +1,147 @@
//
// OtherMessageViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/3/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class OtherMessageViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let modelSelected: Driver<MessageSectionItem>
let footerRefresh: Observable<Void>
}
struct Output {
let items: BehaviorRelay<[MessageSection]>
let modelSelected: Driver<MessageSectionItem>
}
let items = BehaviorRelay<[MessageSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { _ in
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
modelSelected: input.modelSelected)
}
func requestMessageList() -> Observable<MessageList> {
return self.provider.messageList()
.trackActivity(loading)
.trackError(error)
}
}
class OtherMessageViewController: TableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
tableView.register(MessageActivitiesViewCell.self, forCellReuseIdentifier: "MessageActivitiesViewCell")
self.emptyDataSetDescription = "暂无活动消息!"
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? OtherMessageViewModel else { return }
let input = OtherMessageViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
modelSelected: tableView.rx.modelSelected(MessageSectionItem.self).asDriver(),
footerRefresh: footerRefreshTrigger)
let output = viewModel.transform(input: input)
let dataSource = PrivateMessageViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.modelSelected.drive { [weak self] messageSectionItem in
// switch messageSectionItem {
// case .customMessage(let customMessageType):
// self?.navigateToScreen(customMessageType: customMessageType)
// case .messageItem(let message): break
// case .activitiesItem(let message): break
//
// }
}.disposed(by: rx.disposeBag)
}
}
extension OtherMessageViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MessageSection> {
return RxTableViewSectionedReloadDataSource<MessageSection>(
configureCell: { dataSource, tableView, indexPath, item in
switch dataSource[indexPath] {
case .customMessage(let customMessageType):
let cell: MessageCellView = tableView.dequeueReusableCell(withIdentifier: "MessageCellView", for: indexPath) as! MessageCellView
cell.customMessageType = customMessageType
return cell
case .messageItem(let message):
let cell: MessageCellView = tableView.dequeueReusableCell(withIdentifier: "MessageCellView", for: indexPath) as! MessageCellView
cell.message = message
return cell
case .activitiesItem(let message):
let cell: MessageActivitiesViewCell = tableView.dequeueReusableCell(withIdentifier: "MessageActivitiesViewCell", for: indexPath) as! MessageActivitiesViewCell
cell.message = message
return cell
}
}
)
}
}

@ -0,0 +1,216 @@
//
// PrivateMessageViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/3/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import FSPopoverView
class PrivateMessageViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let modelSelected: Driver<MessageSectionItem>
let footerRefresh: Observable<Void>
}
struct Output {
let items: BehaviorRelay<[MessageSection]>
let modelSelected: Driver<MessageSectionItem>
}
let items = BehaviorRelay<[MessageSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { _ in
self.requestMessageList().subscribe { messageList in
var items = [messageList.comment, messageList.thumbup, messageList.follow]
let comment = MessageSectionItem.customMessage(customMessageType: .comment(messageList.comment?.sendUserNickName ?? ""))
let thumbup = MessageSectionItem.customMessage(customMessageType: .like(messageList.thumbup?.sendUserNickName ?? ""))
let follow = MessageSectionItem.customMessage(customMessageType: .follow(messageList.follow?.sendUserNickName ?? ""))
self.items.accept([MessageSection.message(items: [comment, thumbup, follow])])
} onError: { error in
}.disposed(by: self.rx.disposeBag)
}.disposed(by: rx.disposeBag)
return Output.init(items: items,
modelSelected: input.modelSelected)
}
func requestMessageList() -> Observable<MessageList> {
return self.provider.messageList()
.trackActivity(loading)
.trackError(error)
}
}
class PrivateMessageViewController: TableViewController {
private let menuView: PopoverListView = {
let menuView = PopoverListView.init(scrollDirection: .horizontal)
do {
let features: [PopoverMenu] = [.blockList, .delete]
let items: [FSPopoverListItem] = features.map { feature in
let item = FSPopoverListTextItem(scrollDirection: .horizontal)
item.title = feature.description
item.titleFont = UIFont.systemFont(ofSize: 12)
item.isSeparatorHidden = false
item.titleColor = .white
item.contentInset = .init(top: 9, left: 15, bottom: 9, right: 15)
item.selectedHandler = { item in
guard let item = item as? FSPopoverListTextItem else {
return
}
print(item.title ?? "")
}
item.updateLayout()
return item
}
items.last?.isSeparatorHidden = true
menuView.shadowOpacity = 0
menuView.shadowRadius = 0
menuView.shadowColor = .clear
menuView.items = items
menuView.cornerRadius = 3
menuView.transitioningDelegate = nil
menuView.arrowSize = CGSize.init(width: 18, height: 5)
menuView.backgroundColor = .primaryText()
}
return menuView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
tableView.register(MessageCellView.self, forCellReuseIdentifier: "MessageCellView")
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? PrivateMessageViewModel else { return }
let input = PrivateMessageViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
modelSelected: tableView.rx.modelSelected(MessageSectionItem.self).asDriver(),
footerRefresh: footerRefreshTrigger)
let output = viewModel.transform(input: input)
let dataSource = PrivateMessageViewController.dataSource()
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.modelSelected.drive { [weak self] messageSectionItem in
switch messageSectionItem {
case .customMessage(let customMessageType):
self?.navigateToScreen(customMessageType: customMessageType)
case .messageItem(let message): break
case .activitiesItem(let message): break
}
}.disposed(by: rx.disposeBag)
}
func navigateToScreen(customMessageType: CustomMessageType) {
guard let viewModel = viewModel as? PrivateMessageViewModel else { return }
switch customMessageType {
case .comment:
let myCommentListViewModel = MyCommentListViewModel(provider: viewModel.provider)
self.navigator.show(segue: .myCommentList(viewModel: myCommentListViewModel), sender: self)
case .like:
let myLikeListViewModel = MyLikeListViewModel(provider: viewModel.provider)
self.navigator.show(segue: .myLikeList(viewModel: myLikeListViewModel), sender: self)
case .follow:
let followersViewModel = FollowersViewModel(provider: viewModel.provider)
self.navigator.show(segue: .followers(viewModel: followersViewModel), sender: self)
}
}
}
extension PrivateMessageViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<MessageSection> {
return RxTableViewSectionedReloadDataSource<MessageSection>(
configureCell: { dataSource, tableView, indexPath, item in
switch dataSource[indexPath] {
case .customMessage(let customMessageType):
let cell: MessageCellView = tableView.dequeueReusableCell(withIdentifier: "MessageCellView", for: indexPath) as! MessageCellView
cell.customMessageType = customMessageType
return cell
case .messageItem(let message):
let cell: MessageCellView = tableView.dequeueReusableCell(withIdentifier: "MessageCellView", for: indexPath) as! MessageCellView
cell.message = message
return cell
case .activitiesItem(let message):
let cell: MessageActivitiesViewCell = tableView.dequeueReusableCell(withIdentifier: "MessageActivitiesViewCell", for: indexPath) as! MessageActivitiesViewCell
cell.message = message
return cell
}
}
)
}
}

@ -42,7 +42,7 @@ class MineViewController: TableViewController {
if let tabbar = self.tabBarController as? HomeTabBarController { if let tabbar = self.tabBarController as? HomeTabBarController {
tabbar.showAllBar(true, animated: true) tabbar.toggleBars(showTabBar: true, showPlayerBar: true, animated: true)
} }
if AudioManager.sharedInstance.playlist.value.count > 0 { if AudioManager.sharedInstance.playlist.value.count > 0 {

@ -0,0 +1,218 @@
//
// BlackListViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/3/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import FSPopoverView
class BlackListViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let headerRefresh: Observable<Void>
let footerRefresh: Observable<Void>
let modelSelected: Driver<User>
}
struct Output {
let items: BehaviorRelay<[FollowersSection]>
let modelSelected: Driver<User>
}
let items = BehaviorRelay<[FollowersSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { _ in
}.disposed(by: rx.disposeBag)
input.headerRefresh
.flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in
guard let self = self else { return Observable.just([]) }
self.page = 1
return self.requestBlockList(page: page, size: 10)
.trackActivity(self.headerLoading)
})
.subscribe(onNext: { (items) in
self.items.accept([FollowersSection.init(items: items)])
}).disposed(by: rx.disposeBag)
input.footerRefresh
.flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in
guard let self = self else { return Observable.just([]) }
self.page += 1
return self.requestBlockList(page: page, size: 10)
.trackActivity(self.headerLoading)
})
.subscribe(onNext: { (items) in
var arr = self.items.value.first?.items
arr?.append(contentsOf: items)
self.items.accept([FollowersSection.init(items: arr ?? [])])
}).disposed(by: rx.disposeBag)
return Output.init(items: items,
modelSelected: input.modelSelected)
}
func requestBlockList(page: Int, size: Int) -> Observable<[User]> {
return self.provider.blackList(page: page, size: size)
.trackActivity(loading)
.trackError(error)
}
func requestLike(objectId: String, collectType: LikeType) -> Observable<Void> {
return self.provider.like(objectId: objectId, collectType: collectType.rawValue)
.trackActivity(loading)
.trackError(error)
}
func requestCancelLike(objectId: String, collectType: LikeType) -> Observable<Void> {
return self.provider.cancelLike(objectId: objectId, collectType: collectType.rawValue)
.trackActivity(loading)
.trackError(error)
}
}
class BlackListViewController: TableViewController {
private let menuView: PopoverListView = {
let menuView = PopoverListView.init(scrollDirection: .horizontal)
do {
let features: [PopoverMenu] = [.blockList, .delete]
let items: [FSPopoverListItem] = features.map { feature in
let item = FSPopoverListTextItem(scrollDirection: .horizontal)
item.title = feature.description
item.titleFont = UIFont.systemFont(ofSize: 12)
item.isSeparatorHidden = false
item.titleColor = .white
item.contentInset = .init(top: 9, left: 15, bottom: 9, right: 15)
item.selectedHandler = { item in
guard let item = item as? FSPopoverListTextItem else {
return
}
print(item.title ?? "")
}
item.updateLayout()
return item
}
items.last?.isSeparatorHidden = true
menuView.shadowOpacity = 0
menuView.shadowRadius = 0
menuView.shadowColor = .clear
menuView.items = items
menuView.cornerRadius = 3
menuView.transitioningDelegate = nil
menuView.arrowSize = CGSize.init(width: 18, height: 5)
menuView.backgroundColor = .primaryText()
}
return menuView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
tableView.register(FollowingViewCell.self, forCellReuseIdentifier: "FollowingViewCell")
emptyDataSetDescription = "你还没有把人拉黑!"
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? BlackListViewModel else { return }
let input = BlackListViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
headerRefresh: headerRefreshTrigger,
footerRefresh: footerRefreshTrigger, modelSelected: tableView.rx.modelSelected(User.self).asDriver())
let output = viewModel.transform(input: input)
let dataSource = BlackListViewController.dataSource { cell, user in
}
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.modelSelected.drive { [weak self] messageSectionItem in
}.disposed(by: rx.disposeBag)
}
}
extension BlackListViewController {
//TODO
static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, User) -> Void) -> RxTableViewSectionedReloadDataSource<FollowersSection> {
return RxTableViewSectionedReloadDataSource<FollowersSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: FollowingViewCell = tableView.dequeueReusableCell(withIdentifier: "FollowingViewCell", for: indexPath) as! FollowingViewCell
cell.user = item
cell.followingButton.setTitle("取消", for: .normal)
cell.followingButton.setTitle("添加", for: .selected)
if item.relation == .mutualFollowing {
cell.followingButton.isSelected = true
}
cell.buttonTapCallback = {audioTrack in
buttonTapHandler(cell, audioTrack)
}
return cell
}
)
}
}

@ -11,6 +11,11 @@ import RxCocoa
import RxDataSources import RxDataSources
class FollowersViewController: ViewController, UIScrollViewDelegate { class FollowersViewController: ViewController, UIScrollViewDelegate {
var pageViewController: UIPageViewController!
var pages = [UIViewController]()
let currentPageIndex = BehaviorRelay<Int>(value: 0)
let followersTopView: FollowersTopView = { let followersTopView: FollowersTopView = {
@ -18,21 +23,6 @@ class FollowersViewController: ViewController, UIScrollViewDelegate {
return followersTopView return followersTopView
}() }()
var tableView: UITableView = {
let tableView = UITableView.init()
tableView.register(FollowingViewCell.self, forCellReuseIdentifier: "FollowingViewCell")
return tableView
}()
let followersType = BehaviorRelay<FollowersType>.init(value: .followers)
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 viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -42,21 +32,36 @@ class FollowersViewController: ViewController, UIScrollViewDelegate {
override func makeUI() { override func makeUI() {
super.makeUI() super.makeUI()
self.navigationItem.title = "粉丝"
followersTopView.segmentControl.titleBtnOnClick = { [weak self] (label, index) in followersTopView.segmentControl.titleBtnOnClick = { [weak self] (label, index) in
if index == 0 { if index == 0 {
self?.followersType.accept(.followers) self?.goToNextPage()
} else { } else {
self?.followersType.accept(.blackList) self?.goToPreviousPage()
} }
} }
self.navigationItem.title = "粉丝"
tableView.rx.setDelegate(self).disposed(by: rx.disposeBag) guard let viewModel = viewModel as? FollowersViewModel else { return }
let myFollowersViewModel = MyFollowersViewModel.init(provider: viewModel.provider)
let myFollowers = MyFollowersViewController.init(viewModel: myFollowersViewModel, navigator: self.navigator)
let blackListViewModel = BlackListViewModel.init(provider: viewModel.provider)
let blackList = BlackListViewController.init(viewModel: blackListViewModel, navigator: self.navigator)
pages.append(myFollowers)
pages.append(blackList)
setupPageViewController()
view.addSubview(followersTopView) view.addSubview(followersTopView)
view.addSubview(tableView) view.backgroundColor = .white
} }
@ -66,33 +71,24 @@ class FollowersViewController: ViewController, UIScrollViewDelegate {
guard let viewModel = viewModel as? FollowersViewModel else { return } guard let viewModel = viewModel as? FollowersViewModel else { return }
let refresh = Observable.of(Observable.just(()), headerRefreshTrigger).merge()
let input = FollowersViewModel.Input.init(viewWillAppear: rx.viewWillAppear, let input = FollowersViewModel.Input.init(viewWillAppear: rx.viewWillAppear)
headerRefresh: refresh,
footerRefresh: footerRefreshTrigger,
followersType: self.followersType,
modelSelected: tableView.rx.modelSelected(User.self).asDriver())
let output = viewModel.transform(input: input) let output = viewModel.transform(input: input)
let dataSource = FollowersViewController.dataSource { [weak self] cell, user in pageViewController.rx.didFinishAnimating.subscribe { [weak self] (isFinished, previousViewControllers, completed) in
viewModel.itemSelected.onNext(user)
}
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.modelSelected.drive { [weak self] user in
let personalViewModel = PersonalViewModel.init(userID: user.id, provider: viewModel.provider) if let myFollowers = self?.pageViewController.viewControllers?.first as? MyFollowersViewController {
self?.navigator.show(segue: .personal(viewModel: personalViewModel), sender: self) self?.followersTopView.segmentControl.selectedIndex(0, animated: true)
} else {
self?.followersTopView.segmentControl.selectedIndex(1, animated: true)
}
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
} }
@ -108,16 +104,45 @@ class FollowersViewController: ViewController, UIScrollViewDelegate {
} }
tableView.snp.makeConstraints { make in pageViewController.view.snp.remakeConstraints { make in
make.top.equalTo(followersTopView.snp.bottom)
make.left.equalTo(view) make.left.equalTo(view)
make.right.equalTo(view) make.right.equalTo(view)
make.top.equalTo(followersTopView.snp.bottom)
make.bottom.equalTo(view) make.bottom.equalTo(view)
} }
}
private func setupPageViewController() {
pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
pageViewController.dataSource = self
if let firstViewController = pages.first {
pageViewController.setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)
}
addChild(pageViewController)
view.addSubview(pageViewController.view)
pageViewController.didMove(toParent: self)
} }
func goToNextPage() {
guard let currentViewController = pageViewController?.viewControllers?.first,
let nextPage = pages.first else {
return
}
pageViewController?.setViewControllers([nextPage], direction: .reverse, animated: true, completion: nil)
}
func goToPreviousPage() {
guard let currentViewController = pageViewController?.viewControllers?.first,
let previousPage = pages.last else {
return
}
pageViewController?.setViewControllers([previousPage], direction: .forward, animated: true, completion: nil)
}
} }
@ -131,18 +156,9 @@ extension FollowersViewController {
cell.user = item cell.user = item
if dataSource[indexPath.row].followersType == .followers {
cell.followingButton.setTitle("回关", for: .normal)
cell.followingButton.setTitle("互相关注", for: .selected)
if item.relation == .mutualFollowing {
cell.followingButton.isSelected = true
}
} else {
cell.followingButton.setTitle("取消", for: .normal) cell.followingButton.setTitle("取消", for: .normal)
cell.followingButton.setTitle("添加", for: .selected) cell.followingButton.setTitle("添加", for: .selected)
}
cell.buttonTapCallback = {audioTrack in cell.buttonTapCallback = {audioTrack in
@ -155,6 +171,49 @@ extension FollowersViewController {
} }
} }
extension FollowersViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.firstIndex(of: viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else {
return nil
}
guard pages.count > previousIndex else {
return nil
}
return pages[previousIndex]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = pages.firstIndex(of: viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let pagesCount = pages.count
guard pagesCount != nextIndex else {
return nil
}
guard pagesCount > nextIndex else {
return nil
}
return pages[nextIndex]
}
}
class FollowersTopView: UIView { class FollowersTopView: UIView {
lazy var segmentControl: ScrollSegmentView = { lazy var segmentControl: ScrollSegmentView = {

@ -13,30 +13,14 @@ class FollowersViewModel: ViewModel, ViewModelType {
struct Input { struct Input {
let viewWillAppear: ControlEvent<Bool> let viewWillAppear: ControlEvent<Bool>
let headerRefresh: Observable<Void>
let footerRefresh: Observable<Void>
let followersType: BehaviorRelay<FollowersType>
let modelSelected: Driver<User>
} }
struct Output { struct Output {
let followersItems: BehaviorRelay<[FollowersSection]>
let blocklistItems: BehaviorRelay<[FollowersSection]>
let items: BehaviorRelay<[FollowersSection]>
let modelSelected: Driver<User>
} }
let followersItems = BehaviorRelay<[FollowersSection]>.init(value: [])
let blocklistItems = BehaviorRelay<[FollowersSection]>.init(value: [])
let items = BehaviorRelay<[FollowersSection]>.init(value: [])
let itemSelected = PublishSubject<User>()
let followersType = BehaviorRelay<FollowersType>.init(value: .followers)
func transform(input: Input) -> Output { func transform(input: Input) -> Output {
@ -44,29 +28,24 @@ class FollowersViewModel: ViewModel, ViewModelType {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
input.followersType.subscribe { [weak self] followersType in
guard let self = self else { return }
self.followersType.accept(followersType)
}.disposed(by: rx.disposeBag)
// input.headerRefresh.withLatestFrom(input.followersType)
input.headerRefresh.withLatestFrom(input.followersType) // .flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in
.flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in // guard let self = self else { return Observable.just([]) }
guard let self = self else { return Observable.just([]) } // self.page = 1
self.page = 1 //
// if followersType == .followers {
if followersType == .followers { // return self.requestFollowersList(userId: UserDefaults.AccountInfo.string(forKey: .userID) ?? "", page: self.page, size: 10)
return self.requestFollowersList(userId: UserDefaults.AccountInfo.string(forKey: .userID) ?? "", page: self.page, size: 10) // .trackActivity(self.headerLoading)
.trackActivity(self.headerLoading) // } else {
} else { // return self.requestBlockList(page: self.page, size: 10)
return self.requestBlockList(page: self.page, size: 10) // .trackActivity(self.headerLoading)
.trackActivity(self.headerLoading) // }
} //
// })
}) // .subscribe(onNext: { (items) in
.subscribe(onNext: { (items) in // self.items.accept([FollowersSection.init(followersType: self.followersType.value, items: items)])
self.items.accept([FollowersSection.init(followersType: self.followersType.value, items: items)]) // }).disposed(by: rx.disposeBag)
}).disposed(by: rx.disposeBag)
// input.footerRefresh.withLatestFrom(input.followersType) // input.footerRefresh.withLatestFrom(input.followersType)
// .flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in // .flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in
@ -202,18 +181,10 @@ class FollowersViewModel: ViewModel, ViewModelType {
return Output.init(followersItems: followersItems, return Output.init()
blocklistItems: blocklistItems,
items: self.items,
modelSelected: input.modelSelected)
} }
func requestFollowersList(userId: String, page: Int, size: Int) -> Observable<[User]> {
return self.provider.followerList(userId: userId, page: page, size: size)
.trackActivity(loading)
.trackError(error)
}
func requestBlockList(page: Int, size: Int) -> Observable<[User]> { func requestBlockList(page: Int, size: Int) -> Observable<[User]> {

@ -0,0 +1,237 @@
//
// MyFollowersViewController.swift
// IndieMusic
//
// Created by WenLei on 2024/3/2.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import FSPopoverView
class MyFollowersViewModel: ViewModel, ViewModelType {
struct Input {
let viewWillAppear: ControlEvent<Bool>
let headerRefresh: Observable<Void>
let footerRefresh: Observable<Void>
let modelSelected: Driver<User>
}
struct Output {
let items: BehaviorRelay<[FollowersSection]>
let modelSelected: Driver<User>
}
let items = BehaviorRelay<[FollowersSection]>.init(value: [])
func transform(input: Input) -> Output {
input.viewWillAppear.subscribe { _ in
self.requestFollowersList(page: self.page, size: 10)
.subscribe { users in
self.items.accept([FollowersSection.init(items: users)])
} onError: { error in
}.disposed(by: self.rx.disposeBag)
}.disposed(by: rx.disposeBag)
input.headerRefresh
.flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in
guard let self = self else { return Observable.just([]) }
self.page = 1
return self.requestFollowersList(page: page, size: 10)
.trackActivity(self.headerLoading)
})
.subscribe(onNext: { (items) in
self.items.accept([FollowersSection.init(items: items)])
}).disposed(by: rx.disposeBag)
input.footerRefresh
.flatMapLatest({ [weak self] (followersType) -> Observable<[User]> in
guard let self = self else { return Observable.just([]) }
self.page += 1
return self.requestFollowersList(page: page, size: 10)
.trackActivity(self.headerLoading)
})
.subscribe(onNext: { (items) in
var arr = self.items.value.first?.items
arr?.append(contentsOf: items)
self.items.accept([FollowersSection.init(items: arr ?? [])])
}).disposed(by: rx.disposeBag)
return Output.init(items: items,
modelSelected: input.modelSelected)
}
func requestFollowersList(page: Int, size: Int) -> Observable<[User]> {
return self.provider.followerList(userId: UserDefaults.AccountInfo.string(forKey: .userID) ?? "", page: page, size: size)
.trackActivity(loading)
.trackError(error)
}
func requestLike(objectId: String, collectType: LikeType) -> Observable<Void> {
return self.provider.like(objectId: objectId, collectType: collectType.rawValue)
.trackActivity(loading)
.trackError(error)
}
func requestCancelLike(objectId: String, collectType: LikeType) -> Observable<Void> {
return self.provider.cancelLike(objectId: objectId, collectType: collectType.rawValue)
.trackActivity(loading)
.trackError(error)
}
}
class MyFollowersViewController: TableViewController {
private let menuView: PopoverListView = {
let menuView = PopoverListView.init(scrollDirection: .horizontal)
do {
let features: [PopoverMenu] = [.blockList, .delete]
let items: [FSPopoverListItem] = features.map { feature in
let item = FSPopoverListTextItem(scrollDirection: .horizontal)
item.title = feature.description
item.titleFont = UIFont.systemFont(ofSize: 12)
item.isSeparatorHidden = false
item.titleColor = .white
item.contentInset = .init(top: 9, left: 15, bottom: 9, right: 15)
item.selectedHandler = { item in
guard let item = item as? FSPopoverListTextItem else {
return
}
print(item.title ?? "")
}
item.updateLayout()
return item
}
items.last?.isSeparatorHidden = true
menuView.shadowOpacity = 0
menuView.shadowRadius = 0
menuView.shadowColor = .clear
menuView.items = items
menuView.cornerRadius = 3
menuView.transitioningDelegate = nil
menuView.arrowSize = CGSize.init(width: 18, height: 5)
menuView.backgroundColor = .primaryText()
}
return menuView
}()
override func viewDidLoad() {
super.viewDidLoad()
}
override func makeUI() {
super.makeUI()
tableView.register(FollowingViewCell.self, forCellReuseIdentifier: "FollowingViewCell")
emptyDataSetDescription = "还没有人关注你噢!"
}
override func bindViewModel() {
super.bindViewModel()
guard let viewModel = viewModel as? MyFollowersViewModel else { return }
let input = MyFollowersViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
headerRefresh: headerRefreshTrigger,
footerRefresh: footerRefreshTrigger, modelSelected: tableView.rx.modelSelected(User.self).asDriver())
let output = viewModel.transform(input: input)
let dataSource = MyFollowersViewController.dataSource { cell, user in
}
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
output.modelSelected.drive { [weak self] user in
let personalViewModel = PersonalViewModel.init(userID: user.id, provider: viewModel.provider)
self?.navigator.show(segue: .personal(viewModel: personalViewModel), sender: self)
}.disposed(by: rx.disposeBag)
}
}
extension MyFollowersViewController {
//TODO
static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, User) -> Void) -> RxTableViewSectionedReloadDataSource<FollowersSection> {
return RxTableViewSectionedReloadDataSource<FollowersSection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell: FollowingViewCell = tableView.dequeueReusableCell(withIdentifier: "FollowingViewCell", for: indexPath) as! FollowingViewCell
cell.user = item
cell.followingButton.setTitle("回关", for: .normal)
cell.followingButton.setTitle("互相关注", for: .selected)
if item.relation == .mutualFollowing {
cell.followingButton.isSelected = true
}
// if dataSource[indexPath.row].followersType == .followers {
//
//
// } else {
// cell.followingButton.setTitle("", for: .normal)
// cell.followingButton.setTitle("", for: .selected)
// }
cell.buttonTapCallback = {audioTrack in
buttonTapHandler(cell, audioTrack)
}
return cell
}
)
}
}

@ -10,9 +10,9 @@ import MarqueeLabel
class PlayerTabBar: UIControl { class PlayerTabBar: UIControl {
var blurEffectView: BlurEffectView = { var blurEffectView: BlurEffectView = {
let blurEffectView = BlurEffectView.init() let blurEffectView = BlurEffectView.init(style: .systemMaterial, frame: .zero)
blurEffectView.imageView.isHidden = true // blurEffectView.isHidden = true
blurEffectView.backgroundColor = .white
return blurEffectView return blurEffectView
}() }()
@ -27,7 +27,6 @@ class PlayerTabBar: UIControl {
private var containerView: UIView = { private var containerView: UIView = {
var containerView = UIView.init() var containerView = UIView.init()
containerView.backgroundColor = .white
return containerView return containerView
}() }()
@ -85,10 +84,6 @@ class PlayerTabBar: UIControl {
super.init(frame: frame) super.init(frame: frame)
makeUI() makeUI()
// titleLabel.text = ""
// artistLabel.text = ""
// progressView.progress = 0
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
@ -97,8 +92,9 @@ class PlayerTabBar: UIControl {
func makeUI() { func makeUI() {
// backgroundColor = .white
addSubview(blurEffectView)
containerView.addSubview(titleLabel) containerView.addSubview(titleLabel)
containerView.addSubview(artistLabel) containerView.addSubview(artistLabel)
@ -113,17 +109,24 @@ class PlayerTabBar: UIControl {
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
coverView.snp.remakeConstraints { make in blurEffectView.snp.makeConstraints { make in
make.left.equalTo(self)
make.right.equalTo(self)
make.bottom.equalTo(self)
make.top.equalTo(self).offset(12)
}
coverView.snp.makeConstraints { make in
make.left.equalTo(self).offset(30) make.left.equalTo(self).offset(30)
make.top.equalTo(self).offset(0) make.top.equalTo(self).offset(0)
make.size.equalTo(CGSize.init(width: 52, height: 52)) make.size.equalTo(CGSize.init(width: 52, height: 52))
make.bottom.equalTo(self).offset(-14)
} }
containerView.snp.makeConstraints { make in containerView.snp.makeConstraints { make in
make.left.equalTo(self) make.left.equalTo(self)
make.right.equalTo(self) make.right.equalTo(self)
make.bottom.equalTo(self) make.top.equalTo(self).offset(12)
make.height.equalTo(54) make.height.equalTo(54)
} }
@ -154,7 +157,7 @@ class PlayerTabBar: UIControl {
progressView.snp.makeConstraints { make in progressView.snp.makeConstraints { make in
make.left.equalTo(self).offset(30) make.left.equalTo(self).offset(30)
make.right.equalTo(self).offset(-30) make.right.equalTo(self).offset(-30)
make.bottom.equalTo(self) make.top.equalTo(containerView.snp.bottom)
make.height.equalTo(2) make.height.equalTo(2)
} }

@ -101,8 +101,8 @@ class PlayerControlView: UIView {
var playButton: UIButton = { var playButton: UIButton = {
let playButton = UIButton.init() let playButton = UIButton.init()
playButton.setImage(UIImage.init(named: "play_pause_btn"), for: .normal) playButton.setImage(UIImage.init(named: "play_pause_btn"), for: .selected)
playButton.setImage(UIImage.init(named: "play_play_btn"), for: .selected) playButton.setImage(UIImage.init(named: "play_play_btn"), for: .normal)
return playButton return playButton
}() }()

@ -129,14 +129,18 @@ class PlayerViewController: ViewController {
viewModel.isPlaying // viewModel.isPlaying
.bind(to: self.playerControlView.playButton.rx.isSelected) // .bind(to: self.playerControlView.playButton.rx.isSelected)
.disposed(by: rx.disposeBag) // .disposed(by: rx.disposeBag)
//
// viewModel.isPlaying.subscribe { [weak self] isPlaying in
// self?.playerControlView.playButton.isSelected = isPlaying
//
// } .disposed(by: rx.disposeBag)
//
viewModel.isPlaying.subscribe { [weak self] isPlaying in AudioManager.sharedInstance.isPlayingState.bind(to: self.playerControlView.playButton.rx.isSelected).disposed(by: rx.disposeBag)
self?.playerControlView.playButton.isSelected = isPlaying
} .disposed(by: rx.disposeBag)
output.currentAudioTrack.subscribe { [weak self] audioTrack in output.currentAudioTrack.subscribe { [weak self] audioTrack in
@ -162,25 +166,6 @@ class PlayerViewController: ViewController {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
// output.progress.subscribe { [weak self] progress in
// guard let self = self else { return }
//
// if !self.playerScrollView.playerInfoView.playerSlider.isDrop {
// self.playerScrollView.playerInfoView.playerSlider.slider.value = progress
// }
// }.disposed(by: rx.disposeBag)
//
// output.duration.subscribe { [weak self] duration in
// guard let self = self else { return }
//
// self.playerScrollView.playerInfoView.playerSlider.totalSec = duration
// }.disposed(by: rx.disposeBag)
//
// output.time.subscribe { [weak self] time in
// guard let self = self else { return }
//
// self.playerScrollView.playerInfoView.playerSlider.updateTimeLabel(currentTime: time)
// }.disposed(by: rx.disposeBag)
output.isPlaying.bind(to: self.playerControlView.playButton.rx.isSelected).disposed(by: rx.disposeBag) output.isPlaying.bind(to: self.playerControlView.playButton.rx.isSelected).disposed(by: rx.disposeBag)

@ -188,19 +188,6 @@ class PlayerViewModel: ViewModel, ViewModelType {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
input.notiPlayPause.subscribe { [weak self] noti in
guard let self = self else { return }
self.isPlaying.accept(true)
}.disposed(by: rx.disposeBag)
input.notiPlayResume.subscribe { [weak self] noti in
guard let self = self else { return }
self.isPlaying.accept(false)
}.disposed(by: rx.disposeBag)
return Output.init(items: items, return Output.init(items: items,
shuffle: shuffle, shuffle: shuffle,

@ -185,7 +185,6 @@ class SongResultsViewController: CollectionViewController {
return singleColumnSection return singleColumnSection
} }
let collectionView = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: layout)
collectionView.register(JournalViewCell.self, forCellWithReuseIdentifier: "JournalViewCell") collectionView.register(JournalViewCell.self, forCellWithReuseIdentifier: "JournalViewCell")
collectionView.register(JournalAudioCollectionViewCell.self, forCellWithReuseIdentifier: "JournalAudioCollectionViewCell") collectionView.register(JournalAudioCollectionViewCell.self, forCellWithReuseIdentifier: "JournalAudioCollectionViewCell")
collectionView.collectionViewLayout = layout collectionView.collectionViewLayout = layout

@ -53,7 +53,7 @@ class SearchViewController: ViewController, UIScrollViewDelegate {
if let tabbar = self.tabBarController as? HomeTabBarController { if let tabbar = self.tabBarController as? HomeTabBarController {
tabbar.showAllBar(true, animated: true) tabbar.toggleBars(showTabBar: true, showPlayerBar: true, animated: true)
} }
self.navigationController?.setNavigationBarHidden(true, animated: false) self.navigationController?.setNavigationBarHidden(true, animated: false)

Loading…
Cancel
Save