diff --git a/IndieMusic/IndieMusic.xcodeproj/project.pbxproj b/IndieMusic/IndieMusic.xcodeproj/project.pbxproj index a9158ec..626f78b 100644 --- a/IndieMusic/IndieMusic.xcodeproj/project.pbxproj +++ b/IndieMusic/IndieMusic.xcodeproj/project.pbxproj @@ -87,6 +87,7 @@ 77620D942B68E65300798861 /* EditDateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77620D932B68E65300798861 /* EditDateViewController.swift */; }; 77620D962B68E96C00798861 /* DateItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77620D952B68E96C00798861 /* DateItem.swift */; }; 77620D9A2B69DA1A00798861 /* EditSignatureViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77620D992B69DA1A00798861 /* EditSignatureViewController.swift */; }; + 776A1F762B7A18F000F613EB /* ChinaLocalizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 776A1F782B7A18F000F613EB /* ChinaLocalizable.strings */; }; 778638942B4D123D00B00AF9 /* CommentDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778638932B4D123D00B00AF9 /* CommentDetailViewModel.swift */; }; 778B8A212AF8E36D0034AFD4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778B8A202AF8E36D0034AFD4 /* AppDelegate.swift */; }; 778B8A232AF8E36D0034AFD4 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778B8A222AF8E36D0034AFD4 /* SceneDelegate.swift */; }; @@ -325,6 +326,10 @@ 77620D932B68E65300798861 /* EditDateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDateViewController.swift; sourceTree = ""; }; 77620D952B68E96C00798861 /* DateItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateItem.swift; sourceTree = ""; }; 77620D992B69DA1A00798861 /* EditSignatureViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditSignatureViewController.swift; sourceTree = ""; }; + 776A1F742B7A184F00F613EB /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; }; + 776A1F752B7A184F00F613EB /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = ""; }; + 776A1F772B7A18F000F613EB /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/ChinaLocalizable.strings"; sourceTree = ""; }; + 776A1F7A2B7A192000F613EB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/ChinaLocalizable.strings; sourceTree = ""; }; 778638932B4D123D00B00AF9 /* CommentDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentDetailViewModel.swift; sourceTree = ""; }; 778B8A1D2AF8E36D0034AFD4 /* IndieMusic.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IndieMusic.app; sourceTree = BUILT_PRODUCTS_DIR; }; 778B8A202AF8E36D0034AFD4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -605,6 +610,14 @@ path = EditInfo; sourceTree = ""; }; + 776A1F712B7A165500F613EB /* Localizable */ = { + isa = PBXGroup; + children = ( + 776A1F782B7A18F000F613EB /* ChinaLocalizable.strings */, + ); + path = Localizable; + sourceTree = ""; + }; 778B8A142AF8E36D0034AFD4 = { isa = PBXGroup; children = ( @@ -664,6 +677,7 @@ 778B8A512AF8EA2A0034AFD4 /* Resources */ = { isa = PBXGroup; children = ( + 776A1F712B7A165500F613EB /* Localizable */, 77620D7D2B67332600798861 /* font */, 775100A12B63442900F46109 /* Json */, 778B8A292AF8E36E0034AFD4 /* Assets.xcassets */, @@ -1131,6 +1145,7 @@ knownRegions = ( en, Base, + "zh-Hans", ); mainGroup = 778B8A142AF8E36D0034AFD4; productRefGroup = 778B8A1E2AF8E36D0034AFD4 /* Products */; @@ -1149,6 +1164,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 776A1F762B7A18F000F613EB /* ChinaLocalizable.strings in Resources */, 775100A42B6344C700F46109 /* img_0.png in Resources */, 77620D832B67332600798861 /* Alibaba PuHuiTi 2.0.ttf in Resources */, 778B8A2D2AF8E36E0034AFD4 /* LaunchScreen.storyboard in Resources */, @@ -1520,10 +1536,20 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 776A1F782B7A18F000F613EB /* ChinaLocalizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 776A1F772B7A18F000F613EB /* zh-Hans */, + 776A1F7A2B7A192000F613EB /* en */, + ); + name = ChinaLocalizable.strings; + sourceTree = ""; + }; 778B8A262AF8E36D0034AFD4 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 778B8A272AF8E36D0034AFD4 /* Base */, + 776A1F742B7A184F00F613EB /* zh-Hans */, ); name = Main.storyboard; sourceTree = ""; @@ -1532,6 +1558,7 @@ isa = PBXVariantGroup; children = ( 778B8A2C2AF8E36E0034AFD4 /* Base */, + 776A1F752B7A184F00F613EB /* zh-Hans */, ); name = LaunchScreen.storyboard; sourceTree = ""; @@ -1544,6 +1571,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -1591,7 +1619,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -1607,6 +1635,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -1648,7 +1677,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; diff --git a/IndieMusic/IndieMusic/Application/Navigator.swift b/IndieMusic/IndieMusic/Application/Navigator.swift index 7a7805c..b8e693a 100644 --- a/IndieMusic/IndieMusic/Application/Navigator.swift +++ b/IndieMusic/IndieMusic/Application/Navigator.swift @@ -277,7 +277,7 @@ class Navigator { DispatchQueue.main.async { let nav = NavigationController(rootViewController: target) nav.setNavigationBarHidden(true, animated: true) - nav.isPullToDismissEnabled = true +// nav.isPullToDismissEnabled = true nav.modalPresentationStyle = .custom nav.modalPresentationCapturesStatusBarAppearance = true diff --git a/IndieMusic/IndieMusic/Common/BlurEffectView.swift b/IndieMusic/IndieMusic/Common/BlurEffectView.swift index 4722cce..fc63831 100644 --- a/IndieMusic/IndieMusic/Common/BlurEffectView.swift +++ b/IndieMusic/IndieMusic/Common/BlurEffectView.swift @@ -12,7 +12,8 @@ class BlurEffectView: UIView { var blurView: UIVisualEffectView = { let blurEffect = UIBlurEffect(style: .systemThickMaterialDark) let blurView = UIVisualEffectView(effect: blurEffect) - + blurView.isUserInteractionEnabled = true + return blurView }() diff --git a/IndieMusic/IndieMusic/Common/TableViewController.swift b/IndieMusic/IndieMusic/Common/TableViewController.swift index 537ac26..c25b0d2 100644 --- a/IndieMusic/IndieMusic/Common/TableViewController.swift +++ b/IndieMusic/IndieMusic/Common/TableViewController.swift @@ -49,13 +49,13 @@ class TableViewController: ViewController, UIScrollViewDelegate { } - tableView.rx.refresh.subscribe { refreshType in + tableView.rx.refresh.subscribe { [weak self] refreshType in switch refreshType.element { case .refresh: - self.headerRefreshTrigger.onNext(()) + self?.headerRefreshTrigger.onNext(()) case .loadMore where AuthManager.shared.token?.isValid == true: - self.footerRefreshTrigger.onNext(()) + self?.footerRefreshTrigger.onNext(()) default: break } diff --git a/IndieMusic/IndieMusic/Models/AudioMoreAction.swift b/IndieMusic/IndieMusic/Models/AudioMoreAction.swift index bc0cb36..26d2944 100644 --- a/IndieMusic/IndieMusic/Models/AudioMoreAction.swift +++ b/IndieMusic/IndieMusic/Models/AudioMoreAction.swift @@ -8,11 +8,18 @@ import Foundation import RxDataSources -struct AudioMoreAction: Codable { +struct AudioMoreAction: Codable, IdentifiableType, Equatable { let icon: String let title: String let detail: String + var identity: String { + return title + } + + static func == (lhs: AudioMoreAction, rhs: AudioMoreAction) -> Bool { + return lhs.title == rhs.title + } } struct AudioMoreActionSection { diff --git a/IndieMusic/IndieMusic/Models/AudioTrack.swift b/IndieMusic/IndieMusic/Models/AudioTrack.swift index a389e5c..f5f611f 100644 --- a/IndieMusic/IndieMusic/Models/AudioTrack.swift +++ b/IndieMusic/IndieMusic/Models/AudioTrack.swift @@ -6,9 +6,10 @@ // import Foundation +import RxDataSources -struct AudioTrack: Codable { - let id: String? +struct AudioTrack: Codable, IdentifiableType, Equatable { + let id: String let title: String? let artist: String? let album: String? @@ -21,21 +22,15 @@ struct AudioTrack: Codable { var haveCollect: Bool? var isPlaying: Bool? - -// enum CodingKeys: String, CodingKey { -// case album -// case artists -// case availableMarkets = "available_markets" -// case discNumber = "disc_number" -// case durationMs = "duration_ms" -// case explicit -// case externalUrls = "external_urls" -// case id -// case name -// case previewUrl = "preview_url" -// -// case isPlaying -// } + + var identity: String { + return id + } + + static func == (lhs: AudioTrack, rhs: AudioTrack) -> Bool { + return lhs.id == rhs.id + } + } struct TracksResponse: Codable { diff --git a/IndieMusic/IndieMusic/Models/Comment.swift b/IndieMusic/IndieMusic/Models/Comment.swift index 107b875..691d00e 100644 --- a/IndieMusic/IndieMusic/Models/Comment.swift +++ b/IndieMusic/IndieMusic/Models/Comment.swift @@ -8,22 +8,12 @@ import Foundation import RxDataSources -struct MyCommentList { - let avatar: String - let audioTrackImage: String - let name: String - let date: Int - let comment: String - let myComment: String -} - - struct MyCommentListSection { - var items: [MyCommentList] + var items: [Comment] } extension MyCommentListSection: SectionModelType { - typealias Item = MyCommentList + typealias Item = Comment init(original: MyCommentListSection, items: [Item]) { self = original @@ -50,7 +40,7 @@ enum CommentListType { -struct Comment: Codable { +struct Comment: Codable, IdentifiableType, Equatable { let journalId: String? let avatar: String? let state: Int? @@ -58,14 +48,17 @@ struct Comment: Codable { let content: String? let commentCount: Int? let nickName: String? -// let publishTime: Int? + let publishTime: String? let location: String? let parentId: String? - let id: String? - let thumbupCount: Int? + let id: String + let thumbupCountString: String? + let journalImage: String? + let haveThumbup: Bool? // 自定义父评论个数 var parentCommentCount: Int? + private enum CodingKeys: String, CodingKey { case journalId @@ -75,14 +68,25 @@ struct Comment: Codable { case content case commentCount case nickName -// case publishTime + case publishTime case location case parentId case id = "_id" - case thumbupCount + case thumbupCountString + case journalImage + case haveThumbup + case parentCommentCount + + } + + var identity: String { + return id } + static func == (lhs: Comment, rhs: Comment) -> Bool { + return lhs.id == rhs.id + } } @@ -103,3 +107,9 @@ extension CommentSection: SectionModelType { self.items = items } } + + +struct CommentThumbState: Codable { + let thumbState: Bool +} + diff --git a/IndieMusic/IndieMusic/Models/Home.swift b/IndieMusic/IndieMusic/Models/Home.swift index 87a1c60..07f7a87 100644 --- a/IndieMusic/IndieMusic/Models/Home.swift +++ b/IndieMusic/IndieMusic/Models/Home.swift @@ -10,21 +10,8 @@ import RxSwift import RxCocoa import RxDataSources -struct Journal: Codable { -// let id: String? -// let journalNo: String? -// let title: String? -// let image: String? -// let tags: [String]? -// let content: String? -// let editor: String? -// let date: String? -// var haveCollect: Bool? -// let ipLocation: String? -// -// let commentArray: [String]? - - let id: String? +struct Journal: Codable, IdentifiableType, Equatable { + let id: String var haveCollect: Bool? let commentList: [Comment]? let tags: [String]? @@ -36,10 +23,18 @@ struct Journal: Codable { let editor: String? let title: String? let ipLocation: String? - var isExpand: Bool? var trackCount: Int? + + + var identity: String { + return id + } + + static func == (lhs: Journal, rhs: Journal) -> Bool { + return lhs.id == rhs.id && lhs.haveCollect == rhs.haveCollect + } } diff --git a/IndieMusic/IndieMusic/Models/Like.swift b/IndieMusic/IndieMusic/Models/Like.swift index a5e5d4b..b1b206a 100644 --- a/IndieMusic/IndieMusic/Models/Like.swift +++ b/IndieMusic/IndieMusic/Models/Like.swift @@ -8,19 +8,12 @@ import Foundation import RxDataSources -struct Like { - let avatar: String - let name: String - let content: String - let date: Int -} - struct LikeSection { - var items: [Like] + var items: [MineThumbup] } extension LikeSection: SectionModelType { - typealias Item = Like + typealias Item = MineThumbup init(original: LikeSection, items: [Item]) { self = original diff --git a/IndieMusic/IndieMusic/Models/Message.swift b/IndieMusic/IndieMusic/Models/Message.swift index 8363245..043004e 100644 --- a/IndieMusic/IndieMusic/Models/Message.swift +++ b/IndieMusic/IndieMusic/Models/Message.swift @@ -13,9 +13,48 @@ enum MessageType: Codable { case activities } +enum CustomMessageType: Codable { + case comment(String) + case like(String) + case follow(String) + + var description: String { + switch self { + case .comment: + return "评论" + case .like: + return "点赞" + case .follow: + return "关注" + } + } + + var image: String { + switch self { + case .comment: + return "message_comment_icon" + case .like: + return "message_like_icon" + case .follow: + return "message_follow_icon" + } + } + + var detail: String { + switch self { + case .comment(let user): + return "\(user) 回复了你的评论" + case .like(let user): + return "\(user) 点赞了你的评论" + case .follow(let user): + return "\(user) 关注了你" + } + } + +} -struct Message: Codable { +struct Message: Codable, IdentifiableType, Equatable { let sendTime: String? let title: String? let sendUserAvatar: String? @@ -23,13 +62,49 @@ struct Message: Codable { let type: Int? let content: String? let userId: String? - let messageId: String? + let messageId: String let sendUserNickName: String? let haveRead: Int? let messageType: MessageType? + + + + init(sendTime: String? = nil, + title: String? = nil, + sendUserAvatar: String? = nil, + sendUserId: String? = nil, + type: Int? = nil, + content: String? = nil, + userId: String? = nil, + messageId: String = "", + sendUserNickName: String? = nil, + haveRead: Int? = nil, + messageType: MessageType? = nil) { + self.sendTime = sendTime + self.title = title + self.sendUserAvatar = sendUserAvatar + self.sendUserId = sendUserId + self.type = type + self.content = content + self.userId = userId + self.messageId = messageId + self.sendUserNickName = sendUserNickName + self.haveRead = haveRead + self.messageType = messageType + } + + + var identity: String { + return messageId + } + + static func == (lhs: Message, rhs: Message) -> Bool { + return lhs.messageId == rhs.messageId + } + } @@ -41,9 +116,9 @@ enum MessageSection { } enum MessageSectionItem { + case customMessage(customMessageType: CustomMessageType) case messageItem(model: Message) case activitiesItem(model: Message) - } diff --git a/IndieMusic/IndieMusic/Models/Mine.swift b/IndieMusic/IndieMusic/Models/Mine.swift index 8c94146..2d0f2af 100644 --- a/IndieMusic/IndieMusic/Models/Mine.swift +++ b/IndieMusic/IndieMusic/Models/Mine.swift @@ -8,11 +8,19 @@ import Foundation import RxDataSources -struct Mine: Codable { +struct Mine: Codable, IdentifiableType, Equatable { let icon: String let title: String let detail: String let isShowPlay: Bool + + var identity: String { + return title + } + + static func == (lhs: Mine, rhs: Mine) -> Bool { + return lhs.title == rhs.title + } } struct MineSection { @@ -88,3 +96,29 @@ extension MineDownloadSection: SectionModelType { self.items = items } } + + + +struct MineThumbup: Codable { + let id: String? + let type: Int? + let likedItemId: String? + let thumbupAt: String? + let commentContent: String? + let avatar: String? + let nickName: String? + let userId: String? + let createTime: String? + + private enum CodingKeys: String, CodingKey { + case id = "_id" + case type + case likedItemId + case thumbupAt + case commentContent + case avatar + case nickName + case userId + case createTime + } +} diff --git a/IndieMusic/IndieMusic/Models/Player.swift b/IndieMusic/IndieMusic/Models/Player.swift index 107dcd6..09921de 100644 --- a/IndieMusic/IndieMusic/Models/Player.swift +++ b/IndieMusic/IndieMusic/Models/Player.swift @@ -60,8 +60,18 @@ extension PlayerShuffleType { } -struct PlayerLyrics: Codable { - let lyrics: String? +struct PlayerLyrics: Codable, IdentifiableType, Equatable { + let lyrics: String + + + var identity: String { + return lyrics + } + + + static func == (lhs: PlayerLyrics, rhs: PlayerLyrics) -> Bool { + return lhs.lyrics == rhs.lyrics + } } diff --git a/IndieMusic/IndieMusic/Models/Setting.swift b/IndieMusic/IndieMusic/Models/Setting.swift index 5c44934..98db34e 100644 --- a/IndieMusic/IndieMusic/Models/Setting.swift +++ b/IndieMusic/IndieMusic/Models/Setting.swift @@ -8,10 +8,18 @@ import Foundation import RxDataSources -struct Setting: Codable { +struct Setting: Codable, IdentifiableType, Equatable { let title: String let detail: String let arrowIcon: String + + var identity: String { + return title + } + + static func == (lhs: Setting, rhs: Setting) -> Bool { + return lhs.title == rhs.title + } } enum SettingType { diff --git a/IndieMusic/IndieMusic/Models/User.swift b/IndieMusic/IndieMusic/Models/User.swift index 94b1989..267112d 100644 --- a/IndieMusic/IndieMusic/Models/User.swift +++ b/IndieMusic/IndieMusic/Models/User.swift @@ -6,6 +6,7 @@ // import Foundation +import RxDataSources enum UserRelationStatus: Int, Codable { case no = 0 @@ -45,14 +46,14 @@ enum SexType: Int, Codable { } -struct User: Codable { +struct User: Codable, IdentifiableType, Equatable { let avatar: String? let badge: String? let birthDay: String? let commentReplyCount: Int? let fansCount: Int? let followCount: Int? - let id: String? + let id: String let ipLocation: String? let journalCount: Int? let nickName: String? @@ -61,4 +62,12 @@ struct User: Codable { let signature: String? let songCount: Int? let thumbUpCount: Int? + + var identity: String { + return id + } + + static func == (lhs: User, rhs: User) -> Bool { + return lhs.id == rhs.id + } } diff --git a/IndieMusic/IndieMusic/Modules/Home/FilterViewModel.swift b/IndieMusic/IndieMusic/Modules/Home/FilterViewModel.swift index 7cd88f8..300a93b 100644 --- a/IndieMusic/IndieMusic/Modules/Home/FilterViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Home/FilterViewModel.swift @@ -42,7 +42,7 @@ class FilterViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - self.fetchFilterData().subscribe { filterMenu in + self.fetchFilterData().subscribe { [weak self] filterMenu in let journalNoList = filterMenu.journalNoList?.map({ journalNo in @@ -54,10 +54,10 @@ class FilterViewModel: ViewModel, ViewModelType { let selection1 = FilterSection.style(header: "语言", items: filterMenu.languageList ?? []) let selection2 = FilterSection.journalNo(header: "期刊", items: journalNoList ?? []) - self.items.accept([selection0, selection1, selection2]) + self?.items.accept([selection0, selection1, selection2]) - if let filter = self.filter.value { - self.selectItem(selectedFilter: filter) + if let filter = self?.filter.value { + self?.selectItem(selectedFilter: filter) } } onError: { error in diff --git a/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift b/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift index 5915ecc..c1f414f 100644 --- a/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift +++ b/IndieMusic/IndieMusic/Modules/Home/HomeTabBarController.swift @@ -169,7 +169,7 @@ class HomeTabBarController: UITabBarController, Navigatable { output.tabBarItems.delay(.milliseconds(50)).drive(onNext: { [weak self] (tabBarItems) in if let strongSelf = self { let controllers = tabBarItems.map { $0.getController(with: viewModel.viewModel(for: $0), navigator: strongSelf.navigator) } - strongSelf.showAllBar(true, animated: false) +// strongSelf.showAllBar(true, animated: false) strongSelf.setViewControllers(controllers, animated: false) } }).disposed(by: rx.disposeBag) @@ -185,14 +185,18 @@ class HomeTabBarController: UITabBarController, Navigatable { - playerTabBar.listButton.rx.tap.subscribe { _ in + playerTabBar.listButton.rx.tap.subscribe { [weak self] _ in + guard let self = self else { return } + let audioTrackListViewModel = AudioTrackListViewModel.init(provider: viewModel.provider) self.navigator.show(segue: .audioTrackList(viewModel: audioTrackListViewModel), sender: self, transition: .navigationPresent(type: .audioTrackList)) }.disposed(by: rx.disposeBag) - playerTabBar.rx.controlEvent(.touchUpInside).subscribe { _ in + playerTabBar.rx.controlEvent(.touchUpInside).subscribe { [weak self] _ in + guard let self = self else { return } + guard let track = AudioManager.sharedInstance.currentTrack else { return } let playerViewModel = PlayerViewModel.init(track: track, provider: viewModel.provider) @@ -216,8 +220,8 @@ class HomeTabBarController: UITabBarController, Navigatable { }.disposed(by: rx.disposeBag) - output.progress.subscribe { progress in - self.playerTabBar.progressView.progress = progress + output.progress.subscribe { [weak self] progress in + self?.playerTabBar.progressView.progress = progress }.disposed(by: rx.disposeBag) @@ -291,25 +295,21 @@ class HomeTabBarController: UITabBarController, Navigatable { animationDuration = 0 } - UIView.animate(withDuration: animationDuration, - delay: 0, - usingSpringWithDamping: 0.7, - initialSpringVelocity: 0.25, - options: .curveEaseInOut, - animations: { - - if isShowing { - self.customeTabBar.alpha = 1 - self.playerTabBar.alpha = 1 + + UIView.animate(withDuration: animationDuration) { + if isShowing { + self.customeTabBar.alpha = 1 + self.playerTabBar.alpha = 1 - } else { - self.customeTabBar.alpha = 0 - self.playerTabBar.alpha = 0 + } else { + self.customeTabBar.alpha = 0 + self.playerTabBar.alpha = 0 - } - - self.view.layoutIfNeeded() - }) { (completed) in + } + + self.view.layoutIfNeeded() + + } completion: { completed in self.isTabBarShowing = isShowing self.isPlayerBarShowing = isShowing self.customeTabBar.isHidden = !isShowing @@ -319,7 +319,19 @@ class HomeTabBarController: UITabBarController, Navigatable { self.isAnimating = false + } + + +// UIView.animate(withDuration: animationDuration, +// delay: 0, +// usingSpringWithDamping: 0.7, +// initialSpringVelocity: 0, +// options: .curveEaseInOut, +// animations: { +// +// }) { (completed) in +// } } open func showTabBar(_ isShowing: Bool, animated: Bool) { diff --git a/IndieMusic/IndieMusic/Modules/Home/HomeTabBarViewModel.swift b/IndieMusic/IndieMusic/Modules/Home/HomeTabBarViewModel.swift index afdaece..f8fa2b6 100644 --- a/IndieMusic/IndieMusic/Modules/Home/HomeTabBarViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Home/HomeTabBarViewModel.swift @@ -114,8 +114,9 @@ class HomeTabBarViewModel: ViewModel, ViewModelType { let appVersion = infoDic?["CFBundleShortVersionString"] ?? "" guard let appVersion = infoDic?["CFBundleShortVersionString"] as? String else { return } - self.provider.checkVersion(platform: "0", deviceId: AuthManager.shared.getUUID(), appVersion: appVersion).subscribe { _ in - + self.provider.checkVersion(platform: "0", deviceId: AuthManager.shared.getUUID(), appVersion: appVersion).subscribe { [weak self] _ in + guard let self = self else { return } + self.showUpdateAlert.accept(()) } onFailure: { error in diff --git a/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift b/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift index f82f9ef..710c02e 100644 --- a/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Home/HomeViewController.swift @@ -131,16 +131,17 @@ class HomeViewController: TableViewController { }.disposed(by: rx.disposeBag) - output.footerState.subscribe { footerState in - self.tableView.mj_footer?.rx.refreshFooterState.onNext(footerState) - self.tableView.reloadData() + output.footerState.subscribe { [weak self] footerState in + self?.tableView.mj_footer?.rx.refreshFooterState.onNext(footerState) + self?.tableView.reloadData() }.disposed(by: rx.disposeBag) - output.carouselItems.subscribe { carouselItems in + output.carouselItems.subscribe { [weak self] carouselItems in guard let carouselItems = carouselItems.element else { return } - + guard let self = self else { return } + self.carouselItems = carouselItems self.homePagerView.pageControl.numberOfPages = self.carouselItems.count self.homePagerView.pagerView.reloadData() @@ -153,12 +154,12 @@ class HomeViewController: TableViewController { }.disposed(by: rx.disposeBag) - output.randomAudioTrack.subscribe { audioTrackArray in + output.randomAudioTrack.subscribe { [weak self] audioTrackArray in guard let audioTrackArray = audioTrackArray.element, let audioTrack = audioTrackArray.first else { return } let playerViewModel = PlayerViewModel.init(track: audioTrack, provider: viewModel.provider) - self.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal) + self?.navigator.show(segue: .player(viewModel: playerViewModel), sender: self, transition: .modal) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { // 这里放置延迟执行的代码 @@ -170,12 +171,10 @@ class HomeViewController: TableViewController { - viewModel.filter.subscribe { filter in + viewModel.filter.subscribe { [weak self] filter in guard let filter = filter.element else { return } - self.headerView?.filterButton.filter = filter - - + self?.headerView?.filterButton.filter = filter }.disposed(by: rx.disposeBag) @@ -189,7 +188,12 @@ class HomeViewController: TableViewController { make.left.equalTo(view) make.right.equalTo(view) make.top.equalTo(view).offset(-BaseDimensions.statusBarHeight) - make.bottom.equalTo(view) + + if AudioManager.sharedInstance.playlist?.count ?? 0 > 0 { + make.bottom.equalTo(view).offset(-66) + } else { + make.bottom.equalTo(view) + } } } diff --git a/IndieMusic/IndieMusic/Modules/Home/HomeViewModel.swift b/IndieMusic/IndieMusic/Modules/Home/HomeViewModel.swift index ce1e3da..a31d9fe 100644 --- a/IndieMusic/IndieMusic/Modules/Home/HomeViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Home/HomeViewModel.swift @@ -110,8 +110,12 @@ class HomeViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - input.randomAudioTrackTrigger.subscribe { _ in - self.requestRandomAudioTrack().subscribe { audioTrackArray in + input.randomAudioTrackTrigger.subscribe { [weak self] _ in + guard let self = self else { return } + + self.requestRandomAudioTrack().subscribe { [weak self] audioTrackArray in + guard let self = self else { return } + self.randomAudioTrack.accept(audioTrackArray) } onError: { error in @@ -120,7 +124,8 @@ class HomeViewModel: ViewModel, ViewModelType { - filter.subscribe { filter in + filter.subscribe { [weak self] filter in + guard let self = self else { return } guard let filter = filter.element else { return } self.page = 1 diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionController.swift index 3eff27a..f5ef3b0 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionController.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionController.swift @@ -82,11 +82,9 @@ class AudioMoreActionController: ViewController, UIScrollViewDelegate { }.disposed(by: rx.disposeBag) - output.audioTrack.subscribe { audioTrack in + output.audioTrack.subscribe { [weak self] audioTrack in + guard let self = self else { return } self.audioMoreActionView.audioTrack = audioTrack - - - }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift index 09c64ee..fad3a4f 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/AudioMoreActionViewModel.swift @@ -78,7 +78,9 @@ class AudioMoreActionViewModel: ViewModel, ViewModelType { return (indexPath, audioTrack) } - .subscribe(onNext: { (indexPath, audioTrack) in + .subscribe(onNext: { [weak self] (indexPath, audioTrack) in + guard let self = self else { return } + switch indexPath.row { case 0://分享 diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift index 92b2c2b..53c964a 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentView.swift @@ -150,7 +150,10 @@ class CommentViewCell: UITableViewCell { commentLabel.text = comment.content - likeButton.setTitle("\(comment.thumbupCount ?? 0)", for: .normal) + likeButton.setTitle("\(comment.thumbupCountString ?? "0")", for: .normal) + + likeButton.isSelected = comment.haveThumbup == true ? true : false + } } diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift index 1a88beb..4f42caa 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewController.swift @@ -108,14 +108,15 @@ class CommentViewController: ViewController { }.disposed(by: self.rx.disposeBag) cell.likeButton.rx.tap.subscribe { _ in - guard let commentID = comment.id else { return } - viewModel.likeSelected.onNext(commentID) + viewModel.likeSelected.onNext(comment.id) }.disposed(by: self.rx.disposeBag) cell.rx.longPressGesture().when(.recognized) - .subscribe { tap in + .subscribe { [weak self] tap in + guard let self = self else { return } + if comment.userId == UserDefaults.AccountInfo.string(forKey: .userID) { self.menuView.items = self.setupMenuItems(features: [.copy, .report, .delete]) } else { diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift index 8797916..d3b2f52 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/CommentViewModel.swift @@ -51,7 +51,9 @@ class CommentViewModel: ViewModel, ViewModelType { input.viewWillAppear.subscribe { _ in self.requestHotCommentListData(journalID: self.journalID, page: self.page, size: 10) - .subscribe { commentArray in + .subscribe { [weak self] commentArray in + guard let self = self else { return } + self.handleReceivedComments(comments: commentArray) } onError: { error in @@ -60,13 +62,15 @@ class CommentViewModel: ViewModel, ViewModelType { - input.currentCommentListType.subscribe { commentListType in - + input.currentCommentListType.subscribe { [weak self] commentListType in + guard let self = self else { return } + switch commentListType { case .hot: self.requestHotCommentListData(journalID: self.journalID, page: self.page, size: 10) - .subscribe { comments in - + .subscribe { [weak self] comments in + guard let self = self else { return } + self.handleReceivedComments(comments: comments) @@ -77,8 +81,9 @@ class CommentViewModel: ViewModel, ViewModelType { case .latest: self.requestLatestCommentListData(journalID: self.journalID, page: self.page, size: 10) - .subscribe { comments in - + .subscribe { [weak self] comments in + guard let self = self else { return } + self.handleReceivedComments(comments: comments) @@ -111,7 +116,18 @@ class CommentViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - likeSelected.subscribe { _ in + likeSelected.subscribe { [weak self] commentID in + guard let self = self else { return } + + + self.requestCommentLike(commentID: commentID) + .subscribe(onNext: { commentThumbState in + + }, onError: { error in + + }).disposed(by: self.rx.disposeBag) + + }.disposed(by: rx.disposeBag) @@ -126,7 +142,7 @@ class CommentViewModel: ViewModel, ViewModelType { self.sendCommentData(content: comment, journalId: self.journalID, parentId: nil, journalImage: nil) .subscribe { comment in - + //TODO 更新cell的点赞状态 @@ -152,9 +168,11 @@ class CommentViewModel: ViewModel, ViewModelType { self.items.accept(commentSections) for (index, commentType) in commentTypes.enumerated() { - if case let .comment(comment) = commentType, comment.commentCount != 0, let commentID = comment.id { - self.requestSubCommentData(parentId: commentID, page: 1, size: 1) - .subscribe { subCommentArray in + if case let .comment(comment) = commentType, comment.commentCount != 0 { + self.requestSubCommentData(parentId: comment.id, page: 1, size: 1) + .subscribe { [weak self] subCommentArray in + guard let self = self else { return } + self.handleReceivedSubComments(parentCommentCount: comment.commentCount ?? 0, subComments: subCommentArray, mainCommentIndex: index) } onError: { error in print(error) @@ -207,7 +225,7 @@ class CommentViewModel: ViewModel, ViewModelType { - func requestCommentLike(commentID: String) -> Observable { + func requestCommentLike(commentID: String) -> Observable { return self.provider.commentLike(commentId: commentID) .trackError(error) } diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailController.swift index 6a65c87..e4befdc 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailController.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailController.swift @@ -171,8 +171,9 @@ class JournalDetailController: ViewController, UIScrollViewDelegate { resuableView.journal = section?.header - resuableView.saveButton.rx.tap.subscribe { _ in - + resuableView.saveButton.rx.tap.subscribe { [weak self] _ in + guard let self = self else { return } + resuableView.titleImageView.image?.saveImageToPhotoLibrary() .subscribe(onNext: { _ in SVProgressHUD.showText(withStatus: "保存成功") @@ -333,24 +334,37 @@ class JournalDetailController: ViewController, UIScrollViewDelegate { }.disposed(by: rx.disposeBag) - output.isLike.subscribe { isLike in + output.isLike.subscribe { [weak self] isLike in + guard let self = self else { return } self.audioHeaderView?.journalAudioSectionView.likeButton.isSelected = isLike }.disposed(by: rx.disposeBag) + output.journalDetail.subscribe { [weak self] journal in + guard let self = self else { return } + self.commentToolView.commentCountButton.commentCountLabel.text = "\(journal)" + } onError: { error in + + }.disposed(by: rx.disposeBag) + commentToolView.containerView.rx.tapGesture().when(.recognized) - .subscribe { tap in - guard let journalID = viewModel.journal.id else { return } - let commentViewModel = CommentViewModel.init(journalID: journalID, provider: viewModel.provider) + .subscribe { [weak self] tap in + guard let self = self else { return } + + let commentViewModel = CommentViewModel.init(journalID: viewModel.journal.id, provider: viewModel.provider) self.navigator.show(segue: .comment(viewModel: commentViewModel), sender: self) }.disposed(by: rx.disposeBag) + + + + } diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift index f874e62..2631572 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailView.swift @@ -248,15 +248,16 @@ class JournalAudioHeaderView: UICollectionReusableView { popoverView.dataSource = self titleImageView.rx.tapGesture().when(.recognized) - .subscribe { tap in - + .subscribe { [weak self] tap in + guard let self = self else { return } + self.popoverView.present(fromPoint: self.titleImageView.center, in: self, displayIn: self) }.disposed(by: rx.disposeBag) - saveButton.rx.tap.subscribe { _ in + saveButton.rx.tap.subscribe { [weak self] _ in + guard let self = self else { return } self.popoverView.dismiss() - }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailViewModel.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailViewModel.swift index b837591..fd4d042 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/JournalDetailViewModel.swift @@ -72,13 +72,15 @@ class JournalDetailViewModel: ViewModel, ViewModelType { let isLike = BehaviorRelay.init(value: false) - input.viewWillAppear.subscribe { (_) in + input.viewWillAppear.subscribe { _ in }.disposed(by: rx.disposeBag) - input.viewDidLoad.subscribe { (_) in - guard let journalNo = self.journal.journalNo, let journalID = self.journal.id else { return } + input.viewDidLoad.subscribe { [weak self] _ in + guard let self = self else { return } + + guard let journalNo = self.journal.journalNo else { return } // 追踪接口返回的数据 var audioSection: JournalSection? @@ -98,7 +100,9 @@ class JournalDetailViewModel: ViewModel, ViewModelType { // 处理音乐请求 self.requestMusic(journalNo: journalNo) - .subscribe(onNext: { audioTrackArray in + .subscribe(onNext: { [weak self] audioTrackArray in + guard let self = self else { return } + let audioArray = audioTrackArray.map { JournalItem.audioItem(model: $0) } self.journal.trackCount = audioArray.count isLike.accept(self.journal.haveCollect ?? false) @@ -109,8 +113,10 @@ class JournalDetailViewModel: ViewModel, ViewModelType { }).disposed(by: self.rx.disposeBag) // 处理期刊推荐请求 - self.requestJournalRecommend(journalID: journalID) - .subscribe(onNext: { journals in + self.requestJournalRecommend(journalID: self.journal.id) + .subscribe(onNext: { [weak self] journals in + guard let self = self else { return } + let journalArray = journals.map { JournalItem.journaItem(model: $0) } journalSection = JournalSection.journal(header: nil, items: journalArray) updateElements() @@ -123,14 +129,18 @@ class JournalDetailViewModel: ViewModel, ViewModelType { - input.selection.drive { indexPath in + input.selection.drive { [weak self] indexPath in + guard let self = self else { return } + let sectionItem = elements.value[indexPath.section].items[indexPath.row] self.itemSelected.onNext(sectionItem) }.disposed(by: rx.disposeBag) - isExpand.subscribe { isExpand in + isExpand.subscribe { [weak self] isExpand in + guard let self = self else { return } + var new = elements.value if var header = new.first?.header { header.isExpand = isExpand @@ -157,14 +167,12 @@ class JournalDetailViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - likeButtonTapped.subscribe { _ in - guard let id = self.journal.id else { return } - print("2222 likeButtonTapObservable") - - + likeButtonTapped.subscribe { [weak self] _ in + guard let self = self else { return } + if isLike.value { - self.requestCancelLike(journalNo: id) - .subscribe { _ in + self.requestCancelLike(journalNo: self.journal.id) + .subscribe { [weak self] _ in var new = elements.value if var header = new.first?.header { @@ -182,8 +190,8 @@ class JournalDetailViewModel: ViewModel, ViewModelType { }.disposed(by: self.rx.disposeBag) } else { - self.requestLike(journalNo: id) - .subscribe { _ in + self.requestLike(journalNo: self.journal.id) + .subscribe { [weak self] _ in var new = elements.value if var header = new.first?.header { @@ -206,12 +214,14 @@ class JournalDetailViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - shareButtonTrigger.subscribe { _ in + shareButtonTrigger.subscribe { [weak self] _ in + guard let self = self else { return } + self.toShare.onNext(()) }.disposed(by: rx.disposeBag) - item.subscribe { audioTrack in + item.subscribe { [weak self] audioTrack in guard let audioTrack = audioTrack.element else { return } diff --git a/IndieMusic/IndieMusic/Modules/JournalDetail/Share/ShareCardViewController.swift b/IndieMusic/IndieMusic/Modules/JournalDetail/Share/ShareCardViewController.swift index 56098cb..68796c1 100644 --- a/IndieMusic/IndieMusic/Modules/JournalDetail/Share/ShareCardViewController.swift +++ b/IndieMusic/IndieMusic/Modules/JournalDetail/Share/ShareCardViewController.swift @@ -84,7 +84,8 @@ class ShareCardViewController: ViewController { let output = viewModel.transform(input: input) - output.audioTrack.subscribe { audioTrack in + output.audioTrack.subscribe { [weak self] audioTrack in + guard let self = self else { return } guard let audioTrack = audioTrack.element, audioTrack != nil else { return } self.shareSingleView.isHidden = false @@ -93,7 +94,8 @@ class ShareCardViewController: ViewController { }.disposed(by: rx.disposeBag) - output.journal.subscribe { journal in + output.journal.subscribe { [weak self] journal in + guard let self = self else { return } guard let journal = journal.element, journal != nil else { return } self.shareJournalView.isHidden = false @@ -103,7 +105,9 @@ class ShareCardViewController: ViewController { - saveButton.rx.tap.subscribe { _ in + saveButton.rx.tap.subscribe { [weak self] _ in + guard let self = self else { return } + if let image = self.shareSingleView.snapshot(), self.shareSingleView.isHidden == false { UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) SVProgressHUD.showText(withStatus: "保存成功") @@ -115,11 +119,6 @@ class ShareCardViewController: ViewController { SVProgressHUD.showText(withStatus: "保存成功") self.navigator.dismiss(sender: self) } - - - - - } .disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Login/InternationalNumberViewModel.swift b/IndieMusic/IndieMusic/Modules/Login/InternationalNumberViewModel.swift index 76776b7..59a50e0 100644 --- a/IndieMusic/IndieMusic/Modules/Login/InternationalNumberViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Login/InternationalNumberViewModel.swift @@ -38,7 +38,9 @@ class InternationalNumberViewModel: ViewModel, ViewModelType { input.viewWillAppear.subscribe { [weak self] (_) in guard let self = self else { return } - self.requestSMSData().subscribe { array in + self.requestSMSData().subscribe { [weak self] array in + guard let self = self else { return } + guard let array = array.element else { return } let internationalNumberSection = InternationalNumberSection.init(items: array) diff --git a/IndieMusic/IndieMusic/Modules/Main/zh-Hans.lproj/LaunchScreen.strings b/IndieMusic/IndieMusic/Modules/Main/zh-Hans.lproj/LaunchScreen.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Main/zh-Hans.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/IndieMusic/IndieMusic/Modules/Main/zh-Hans.lproj/Main.strings b/IndieMusic/IndieMusic/Modules/Main/zh-Hans.lproj/Main.strings new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/IndieMusic/IndieMusic/Modules/Main/zh-Hans.lproj/Main.strings @@ -0,0 +1 @@ + diff --git a/IndieMusic/IndieMusic/Modules/Message/MessageViewController.swift b/IndieMusic/IndieMusic/Modules/Message/MessageViewController.swift index aa05057..c4d2bd1 100644 --- a/IndieMusic/IndieMusic/Modules/Message/MessageViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Message/MessageViewController.swift @@ -188,6 +188,14 @@ extension MessageViewController { return RxTableViewSectionedReloadDataSource( 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 @@ -199,6 +207,8 @@ extension MessageViewController { cell.message = message return cell + + } } ) @@ -348,6 +358,18 @@ class MessageCellView: UITableViewCell { } + var customMessageType: CustomMessageType? { + didSet { + guard let customMessageType = customMessageType else { return } + + avatarView.image = UIImage.init(named: customMessageType.image) + nameLabel.text = customMessageType.description + detailLabel.text = customMessageType.detail + + } + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) diff --git a/IndieMusic/IndieMusic/Modules/Message/MessageViewModel.swift b/IndieMusic/IndieMusic/Modules/Message/MessageViewModel.swift index 1915145..83535e2 100644 --- a/IndieMusic/IndieMusic/Modules/Message/MessageViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Message/MessageViewModel.swift @@ -44,7 +44,10 @@ class MessageViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.messageType.subscribe { followersType in + + + input.messageType.subscribe { [weak self] followersType in + guard let self = self else { return } self.messageType.accept(followersType) }.disposed(by: rx.disposeBag) @@ -64,11 +67,8 @@ class MessageViewModel: ViewModel, ViewModelType { }) .subscribe(onNext: { (items) in - - - if self.messageType.value == .message { - var new = items.map { message in + let new = items.map { message in MessageSectionItem.messageItem(model: message) } @@ -99,9 +99,6 @@ class MessageViewModel: ViewModel, ViewModelType { } }) .subscribe(onNext: { (items) in - - - if self.messageType.value == .message { var arr = self.items.value.first?.items var new = items.map { message in @@ -120,31 +117,45 @@ class MessageViewModel: ViewModel, ViewModelType { self.items.accept([MessageSection.activities(items: new)]) } }).disposed(by: rx.disposeBag) - + input.messageType.subscribe { [weak self] messageType in + guard let self = self else { return } - - - - input.messageType.subscribe { messageType in - print("messageType \(messageType)") self.page = 1 switch messageType { case .message: - self.requestMessageList(page: self.page, size: 10) - .subscribe { messageArray in - var new = messageArray.map { message in - MessageSectionItem.messageItem(model: message) - } - - self.messageItems.accept([MessageSection.message(items: new)]) - } onError: { error in - - }.disposed(by: self.rx.disposeBag) + let comment = CustomMessageType.comment("测试") + let like = CustomMessageType.like("测试1") + let follow = CustomMessageType.follow("测试2") + + let commentMessage = MessageSectionItem.customMessage(customMessageType: comment) + let likeMessage = MessageSectionItem.customMessage(customMessageType: like) + let followMessage = MessageSectionItem.customMessage(customMessageType: follow) + + + + + self.messageItems.accept([MessageSection.message(items: [commentMessage, likeMessage, followMessage])]) + + + + +// self.requestMessageList(page: self.page, size: 10) +// .subscribe { messageArray in +// var new = messageArray.map { message in +// MessageSectionItem.messageItem(model: message) +// } +// +// self.messageItems.accept([MessageSection.message(items: new)]) +// } onError: { error in +// +// }.disposed(by: self.rx.disposeBag) case .activities: self.requestMessageList(page: self.page, size: 10) - .subscribe { messageArray in + .subscribe { [weak self] messageArray in + guard let self = self else { return } + var new = messageArray.map { message in MessageSectionItem.activitiesItem(model: message) } @@ -153,9 +164,6 @@ class MessageViewModel: ViewModel, ViewModelType { } onError: { error in }.disposed(by: self.rx.disposeBag) - - default: break - } @@ -166,10 +174,9 @@ class MessageViewModel: ViewModel, ViewModelType { let cuttentItems = Observable.merge(messageItems.asObservable(), activitiesItems.asObservable()) - cuttentItems.subscribe { followersSections in - + cuttentItems.subscribe { [weak self] followersSections in + guard let self = self else { return } self.items.accept(followersSections) - }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineDownloadViewModel.swift b/IndieMusic/IndieMusic/Modules/Mine/MineDownloadViewModel.swift index 83295ad..20fb09d 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineDownloadViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineDownloadViewModel.swift @@ -46,8 +46,8 @@ class MineDownloadViewModel: ViewModel, ViewModelType { self.isEditing.accept(!self.isEditing.value) }.disposed(by: rx.disposeBag) - isEditing.subscribe { isEditing in - guard var currentItems = self.items.value.first?.items else { return } + isEditing.subscribe { [weak self] isEditing in + guard var currentItems = self?.items.value.first?.items else { return } currentItems = currentItems.map { item in var modifiedItem = item @@ -55,7 +55,7 @@ class MineDownloadViewModel: ViewModel, ViewModelType { return modifiedItem } - self.items.accept([MineDownloadSection.init(items: currentItems)]) + self?.items.accept([MineDownloadSection.init(items: currentItems)]) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineJournalViewController.swift b/IndieMusic/IndieMusic/Modules/Mine/MineJournalViewController.swift index 9e02c6a..fc9863a 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineJournalViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineJournalViewController.swift @@ -64,13 +64,13 @@ class MineJournalViewController: ViewController { - collectionView.rx.refresh.subscribe { refreshType in + collectionView.rx.refresh.subscribe { [weak self] refreshType in switch refreshType.element { case .refresh: - self.headerRefreshTrigger.onNext(()) + self?.headerRefreshTrigger.onNext(()) case .loadMore where AuthManager.shared.token?.isValid == true: - self.footerRefreshTrigger.onNext(()) + self?.footerRefreshTrigger.onNext(()) default: break } diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift b/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift index 89a1b36..2788133 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineSingleController.swift @@ -61,18 +61,15 @@ class MineSingleController: ViewController { view.addSubview(headerView) view.addSubview(tableView) - tableView.rx.refresh.subscribe { refreshType in - + tableView.rx.refresh.subscribe { [weak self] refreshType in switch refreshType.element { case .refresh: - self.headerRefreshTrigger.onNext(()) + self?.headerRefreshTrigger.onNext(()) case .loadMore where AuthManager.shared.token?.isValid == true: - self.footerRefreshTrigger.onNext(()) + self?.footerRefreshTrigger.onNext(()) default: break } - - }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift b/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift index a4ab9e0..12f8766 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineViewController.swift @@ -90,13 +90,11 @@ class MineViewController: TableViewController { selection: tableView.rx.itemSelected.asDriver()) let output = viewModel.transform(input: input) - headerView.nameButton.rx.tap.subscribe { _ in + headerView.nameButton.rx.tap.subscribe { [weak self] _ in guard AuthManager.shared.token?.isValid == false else { return } let loginViewModel = LoginViewModel.init(provider: viewModel.provider) - self.navigator.show(segue: .login(viewModel: loginViewModel), sender: self) - - + self?.navigator.show(segue: .login(viewModel: loginViewModel), sender: self) }.disposed(by: rx.disposeBag) @@ -169,15 +167,27 @@ class MineViewController: TableViewController { }.disposed(by: rx.disposeBag) - output.user.subscribe { user in - self.headerView.user = user - + output.user.subscribe { [weak self] user in + self?.headerView.user = user }.disposed(by: rx.disposeBag) } - + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + tableView.snp.remakeConstraints { make in + make.edges.equalTo(view) + if AudioManager.sharedInstance.playlist?.count ?? 0 > 0 { + make.bottom.equalTo(view).offset(-66 - BaseDimensions.tabBarHeight) + } else { + make.bottom.equalTo(view) + } + } + + + } } diff --git a/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift b/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift index e537aa7..8dab063 100644 --- a/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Mine/MineViewModel.swift @@ -32,7 +32,7 @@ class MineViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.viewWillAppear.subscribe { (_) in + input.viewWillAppear.subscribe { _ in self.requestUserInfoData().subscribe { user in self.user.accept(user) diff --git a/IndieMusic/IndieMusic/Modules/Personal/FollowersViewController.swift b/IndieMusic/IndieMusic/Modules/Personal/FollowersViewController.swift index ad62da0..586a65d 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/FollowersViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/FollowersViewController.swift @@ -66,7 +66,8 @@ class FollowersViewController: ViewController, UIScrollViewDelegate { view.addSubview(tableView) view.addSubview(noDataView) - tableView.rx.refresh.subscribe { refreshType in + tableView.rx.refresh.subscribe { [weak self] refreshType in + guard let self = self else { return } switch refreshType.element { case .refresh: @@ -107,9 +108,8 @@ class FollowersViewController: ViewController, UIScrollViewDelegate { output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) output.modelSelected.drive { [weak self] user in - guard let userID = user.id else { return } - let personalViewModel = PersonalViewModel.init(userID: userID, provider: viewModel.provider) + let personalViewModel = PersonalViewModel.init(userID: user.id, provider: viewModel.provider) self?.navigator.show(segue: .personal(viewModel: personalViewModel), sender: self) diff --git a/IndieMusic/IndieMusic/Modules/Personal/FollowersViewModel.swift b/IndieMusic/IndieMusic/Modules/Personal/FollowersViewModel.swift index a40634b..1735d31 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/FollowersViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/FollowersViewModel.swift @@ -44,7 +44,8 @@ class FollowersViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - input.followersType.subscribe { followersType in + input.followersType.subscribe { [weak self] followersType in + guard let self = self else { return } self.followersType.accept(followersType) }.disposed(by: rx.disposeBag) @@ -93,14 +94,17 @@ class FollowersViewModel: ViewModel, ViewModelType { - input.followersType.subscribe { followersType in - + input.followersType.subscribe { [weak self] followersType in + guard let self = self else { return } + print("followersType \(followersType)") switch followersType.element { case .followers: self.requestFollowersList(userId: UserDefaults.AccountInfo.string(forKey: .userID) ?? "", page: self.page, size: 10) - .subscribe { follows in + .subscribe { [weak self] follows in + guard let self = self else { return } + self.followersItems.accept([FollowersSection.init(followersType: .followers, items: follows)]) } onError: { error in @@ -108,7 +112,9 @@ class FollowersViewModel: ViewModel, ViewModelType { case .blackList: self.requestBlockList(page: self.page, size: 10) - .subscribe { follows in + .subscribe { [weak self] follows in + guard let self = self else { return } + self.blocklistItems.accept([FollowersSection.init(followersType: .blackList, items: follows)]) } onError: { error in @@ -126,8 +132,9 @@ class FollowersViewModel: ViewModel, ViewModelType { let cuttentItems = Observable.merge(followersItems.asObservable(), blocklistItems.asObservable()) - cuttentItems.subscribe { followersSections in - + cuttentItems.subscribe { [weak self] followersSections in + guard let self = self else { return } + self.items.accept(followersSections) }.disposed(by: rx.disposeBag) @@ -137,9 +144,9 @@ class FollowersViewModel: ViewModel, ViewModelType { return (user, followersType) } - .subscribe { (user, followersType) in - guard let userID = user.id else { return } - + .subscribe { [weak self] (user, followersType) in + guard let self = self else { return } + guard let index = self.items.value.first?.items.firstIndex(where: { $0.id == user.id }) else { return } var updatedUsers = self.items.value var updatedUser = updatedUsers.first?.items[index] @@ -148,8 +155,10 @@ class FollowersViewModel: ViewModel, ViewModelType { switch user.relation { case .notFollowing, .no: - self.requestLike(objectId: userID, collectType: followersType == .followers ? .following : .addBlockList) - .subscribe { _ in + self.requestLike(objectId: user.id, collectType: followersType == .followers ? .following : .addBlockList) + .subscribe { [weak self] _ in + guard let self = self else { return } + updatedUsers[0].items[index].relation = .mutualFollowing if let items = updatedUsers.first?.items { @@ -162,9 +171,10 @@ class FollowersViewModel: ViewModel, ViewModelType { case .following, .mutualFollowing: - self.requestCancelLike(objectId: userID, collectType: followersType == .followers ? .following : .addBlockList) - .subscribe { _ in - + self.requestCancelLike(objectId: user.id, collectType: followersType == .followers ? .following : .addBlockList) + .subscribe { [weak self] _ in + guard let self = self else { return } + updatedUsers[0].items[index].relation = .notFollowing if let items = updatedUsers.first?.items { diff --git a/IndieMusic/IndieMusic/Modules/Personal/FollowingViewController.swift b/IndieMusic/IndieMusic/Modules/Personal/FollowingViewController.swift index 7ae830d..a678c6b 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/FollowingViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/FollowingViewController.swift @@ -75,11 +75,10 @@ class FollowingViewController: TableViewController { }.disposed(by: rx.disposeBag) - output.selection.drive { [weak self] selection in - guard let sectionItem = output.items.value.first?.items[selection.row] else { return } - guard let userID = sectionItem.id else { return } + output.selection.drive { [weak self] indexPath in + guard let user = output.items.value.first?.items[indexPath.row] else { return } - let personalViewModel = PersonalViewModel.init(userID: userID, provider: viewModel.provider) + let personalViewModel = PersonalViewModel.init(userID: user.id, provider: viewModel.provider) self?.navigator.show(segue: .personal(viewModel: personalViewModel), sender: self) diff --git a/IndieMusic/IndieMusic/Modules/Personal/FollowingViewModel.swift b/IndieMusic/IndieMusic/Modules/Personal/FollowingViewModel.swift index 8919c1c..c8f5f5a 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/FollowingViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/FollowingViewModel.swift @@ -33,9 +33,12 @@ class FollowingViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.viewWillAppear.subscribe { (_) in + input.viewWillAppear.subscribe { [weak self] _ in + guard let self = self else { return } + self.requestFollowingList(userId: UserDefaults.AccountInfo.string(forKey: .userID) ?? "", page: self.page, size: 10) - .subscribe { array in + .subscribe { [weak self] array in + guard let self = self else { return } self.items.accept([FollowingSection.init(items: array)]) } onError: { error in @@ -73,9 +76,8 @@ class FollowingViewModel: ViewModel, ViewModelType { - itemSelected.subscribe { user in - guard let user = user.element, - let userID = user.id else { return } + itemSelected.subscribe { [weak self] user in + guard let self = self, let user = user.element else { return } guard let index = self.items.value.first?.items.firstIndex(where: { $0.id == user.id }) else { return } var updatedUsers = self.items.value @@ -85,8 +87,10 @@ class FollowingViewModel: ViewModel, ViewModelType { switch user.relation { case .notFollowing: - self.requestLike(journalNo: userID) - .subscribe { _ in + self.requestLike(journalNo: user.id) + .subscribe { [weak self] _ in + guard let self = self else { return } + updatedUsers[0].items[index].relation = .mutualFollowing if let items = updatedUsers.first?.items { @@ -99,9 +103,10 @@ class FollowingViewModel: ViewModel, ViewModelType { case .following, .mutualFollowing: - self.requestCancelLike(journalNo: userID) - .subscribe { _ in - + self.requestCancelLike(journalNo: user.id) + .subscribe { [weak self] _ in + guard let self = self else { return } + updatedUsers[0].items[index].relation = .notFollowing if let items = updatedUsers.first?.items { diff --git a/IndieMusic/IndieMusic/Modules/Personal/MyCommentListController.swift b/IndieMusic/IndieMusic/Modules/Personal/MyCommentListController.swift index 786d333..beaf979 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/MyCommentListController.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/MyCommentListController.swift @@ -43,7 +43,12 @@ class MyCommentListController: TableViewController { guard let viewModel = viewModel as? MyCommentListViewModel else { return } - let input = MyCommentListViewModel.Input.init(viewWillAppear: rx.viewWillAppear) + let refresh = Observable.of(Observable.just(()), headerRefreshTrigger).merge() + + let input = MyCommentListViewModel.Input.init(viewWillAppear: rx.viewWillAppear, + headerRefresh: refresh, + footerRefresh: footerRefreshTrigger + ) let output = viewModel.transform(input: input) @@ -74,13 +79,13 @@ class MyCommentListController: TableViewController { extension MyCommentListController { //TODO - static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, Like) -> Void) -> RxTableViewSectionedReloadDataSource { + static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, MineThumbup) -> Void) -> RxTableViewSectionedReloadDataSource { return RxTableViewSectionedReloadDataSource( configureCell: { dataSource, tableView, indexPath, item in let cell: CommentListViewCell = tableView.dequeueReusableCell(withIdentifier: "CommentListViewCell", for: indexPath) as! CommentListViewCell - cell.myCommentList = item + cell.comment = item return cell } @@ -175,16 +180,16 @@ class CommentListViewCell: UITableViewCell { var buttonTapCallback: ((User) -> ())? - var myCommentList: MyCommentList? { + var comment: Comment? { didSet { - guard let myCommentList = myCommentList else { return } - avatarView.kf.setImage(with: URL.init(string: myCommentList.avatar)) - audioTrackView.kf.setImage(with: URL.init(string: myCommentList.audioTrackImage)) + guard let comment = comment else { return } + avatarView.kf.setImage(with: URL.init(string: comment.avatar ?? "")) + audioTrackView.kf.setImage(with: URL.init(string: comment.journalImage ?? "")) - nameLabel.text = myCommentList.name - dateLabel.text = "\(myCommentList.date)" - commentLabel.text = myCommentList.comment - myCommentLabel.text = "我的评论:\(myCommentList.myComment)" + nameLabel.text = comment.nickName + dateLabel.text = "\(comment.publishTime)" + commentLabel.text = comment.content +// myCommentLabel.text = "我的评论:\(comment.comm)" } } diff --git a/IndieMusic/IndieMusic/Modules/Personal/MyCommentListViewModel.swift b/IndieMusic/IndieMusic/Modules/Personal/MyCommentListViewModel.swift index 67b95d1..c499430 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/MyCommentListViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/MyCommentListViewModel.swift @@ -14,6 +14,8 @@ class MyCommentListViewModel: ViewModel, ViewModelType { struct Input { let viewWillAppear: ControlEvent + let headerRefresh: Observable + let footerRefresh: Observable } @@ -25,18 +27,52 @@ class MyCommentListViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.viewWillAppear.subscribe { (_) in - + input.viewWillAppear.subscribe { [weak self] _ in + guard let self = self else { return } + + self.requestCommentList(page: self.page, size: 10) + .subscribe { [weak self] commentArray in + guard let self = self else { return } + + + + } onError: { error in + + }.disposed(by: self.rx.disposeBag) + + }.disposed(by: rx.disposeBag) - let name = MyCommentList.init(avatar: "", audioTrackImage: "", name: "123", date: 1000, comment: "这就是生活,也是理想,也是你我的未来", myComment: "太多了,还有草东我也很") + input.headerRefresh.flatMapLatest({ [weak self] () -> Observable<[Comment]> in + guard let self = self else { return Observable.just([]) } + self.page = 1 + + return self.requestCommentList(page: self.page, size: 10) + .trackActivity(self.headerLoading) + }) + .subscribe(onNext: { (items) in + self.items.accept([MyCommentListSection.init(items: items)]) + }).disposed(by: rx.disposeBag) - - items.accept([MyCommentListSection.init(items: [name, name, name, name])]) + input.footerRefresh.flatMapLatest({ [weak self] () -> Observable<[Comment]> in + guard let self = self else { return Observable.just([]) } + self.page += 1 + return self.requestCommentList(page: self.page, size: 10) + .trackActivity(self.footerLoading) + }) + .subscribe(onNext: { (items) in + self.items.accept([MyCommentListSection.init(items: (self.items.value.first?.items ?? []) + items)]) + }).disposed(by: rx.disposeBag) return Output.init(items: items) } + + func requestCommentList(page: Int, size: Int) -> Observable<[Comment]> { + self.provider.myCommentList(page: page, size: size) + .trackActivity(loading) + .trackError(error) + } } diff --git a/IndieMusic/IndieMusic/Modules/Personal/MyLikeListController.swift b/IndieMusic/IndieMusic/Modules/Personal/MyLikeListController.swift index 4d509a1..f6106ae 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/MyLikeListController.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/MyLikeListController.swift @@ -44,12 +44,20 @@ class MyLikeListController: TableViewController { guard let viewModel = viewModel as? MyLikeListViewModel else { return } - let input = MyLikeListViewModel.Input.init(viewWillAppear: rx.viewWillAppear) + let refresh = Observable.of(Observable.just(()), headerRefreshTrigger).merge() + + let input = MyLikeListViewModel.Input.init(viewWillAppear: rx.viewWillAppear, + headerRefresh: refresh, + footerRefresh: footerRefreshTrigger + ) let output = viewModel.transform(input: input) - let dataSource = MyLikeListController.dataSource { cell, like in + let dataSource = MyLikeListController.dataSource { [weak self] cell, mineThumbup in + guard let userID = mineThumbup.userId else { return } + let personalViewModel = PersonalViewModel.init(userID: userID, provider: viewModel.provider) + self?.navigator.show(segue: .personal(viewModel: personalViewModel), sender: self) } output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) @@ -73,15 +81,15 @@ class MyLikeListController: TableViewController { extension MyLikeListController { //TODO - static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, Like) -> Void) -> RxTableViewSectionedReloadDataSource { + static func dataSource(_ buttonTapHandler: @escaping (UITableViewCell, MineThumbup) -> Void) -> RxTableViewSectionedReloadDataSource { return RxTableViewSectionedReloadDataSource( configureCell: { dataSource, tableView, indexPath, item in let cell: LikeViewCell = tableView.dequeueReusableCell(withIdentifier: "LikeViewCell", for: indexPath) as! LikeViewCell - cell.like = item + cell.mineThumbup = item - cell.buttonTapCallback = { like in - buttonTapHandler(cell, like) + cell.buttonTapCallback = { mineThumbup in + buttonTapHandler(cell, mineThumbup) } return cell @@ -108,6 +116,10 @@ class LikeViewCell: UITableViewCell { nameLabel.font = UIFont.systemFont(ofSize: 15, weight: .medium) nameLabel.textColor = .primaryText() + + nameLabel.setContentHuggingPriority(.required, for: .horizontal) + nameLabel.setContentCompressionResistancePriority(.required, for: .horizontal) + return nameLabel }() @@ -151,20 +163,22 @@ class LikeViewCell: UITableViewCell { }() - var like: Like? { + var mineThumbup: MineThumbup? { didSet { - guard let like = like else { return } + guard let mineThumbup = mineThumbup else { return } + + avatarView.kf.setImage(with: URL.init(string: mineThumbup.avatar ?? "")) + nameLabel.text = mineThumbup.nickName + detailLabel.text = mineThumbup.commentContent - avatarView.image = UIImage.init(named: like.avatar) - nameLabel.text = like.name - detailLabel.text = like.content + let date = Date.init(dateString: mineThumbup.createTime ?? "", format: "yyyy-MM-dd HH:mm:ss") - dateLabel.text = "\(like.date)" + dateLabel.text = date.timeAgoSinceNow } } - var buttonTapCallback: ((Like) -> ())? + var buttonTapCallback: ((MineThumbup) -> ())? @@ -175,6 +189,18 @@ class LikeViewCell: UITableViewCell { makeUI() + avatarView.rx.tapGesture().when(.recognized) + .subscribe { [weak self] tap in + guard let self = self else { return } + + if let buttonTapCallback = self.buttonTapCallback, + let mineThumbup = self.mineThumbup { + buttonTapCallback(mineThumbup) + } + + }.disposed(by: rx.disposeBag) + + } required init?(coder: NSCoder) { diff --git a/IndieMusic/IndieMusic/Modules/Personal/MyLikeListViewModel.swift b/IndieMusic/IndieMusic/Modules/Personal/MyLikeListViewModel.swift index 59a8964..7eec76f 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/MyLikeListViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/MyLikeListViewModel.swift @@ -13,6 +13,8 @@ class MyLikeListViewModel: ViewModel, ViewModelType { struct Input { let viewWillAppear: ControlEvent + let headerRefresh: Observable + let footerRefresh: Observable } @@ -28,14 +30,40 @@ class MyLikeListViewModel: ViewModel, ViewModelType { }.disposed(by: rx.disposeBag) - let name = Like(avatar: "", name: "用户名", content: "签名", date: 10000) - - items.accept([LikeSection.init(items: [name, name, name, name])]) + input.headerRefresh.flatMapLatest({ [weak self] () -> Observable<[MineThumbup]> in + guard let self = self else { return Observable.just([]) } + self.page = 1 + + return self.requestLikeList(page: self.page, size: 10) + .trackActivity(self.headerLoading) + }) + .subscribe(onNext: { (items) in + self.items.accept([LikeSection.init(items: items)]) + }).disposed(by: rx.disposeBag) + + input.footerRefresh.flatMapLatest({ [weak self] () -> Observable<[MineThumbup]> in + guard let self = self else { return Observable.just([]) } + self.page += 1 + return self.requestLikeList(page: self.page, size: 10) + .trackActivity(self.footerLoading) + }) + .subscribe(onNext: { (items) in + self.items.accept([LikeSection.init(items: (self.items.value.first?.items ?? []) + items)]) + + }).disposed(by: rx.disposeBag) return Output.init(items: items) } + + + func requestLikeList(page: Int, size: Int) -> Observable<[MineThumbup]> { + self.provider.myThumbupList(page: page, size: size) + .trackActivity(loading) + .trackError(error) + + } } diff --git a/IndieMusic/IndieMusic/Modules/Personal/PersonalViewController.swift b/IndieMusic/IndieMusic/Modules/Personal/PersonalViewController.swift index e032696..7f5197c 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/PersonalViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/PersonalViewController.swift @@ -18,9 +18,14 @@ class PersonalViewController: ViewController { let layout = UICollectionViewCompositionalLayout { (sectionIndex, environment) -> NSCollectionLayoutSection? in let viewModel = self.viewModel as? PersonalViewModel + if viewModel?.personInfoLikeType.value == .audio { + return self.createSingleColumnSection() + } else { + return self.createDoubleColumnSection() + + } - return self.createSingleColumnSection() } @@ -84,13 +89,13 @@ class PersonalViewController: ViewController { view.addSubview(noDataView) - collectionView.rx.refresh.subscribe { refreshType in + collectionView.rx.refresh.subscribe { [weak self] refreshType in switch refreshType.element { case .refresh: - self.headerRefreshTrigger.onNext(()) + self?.headerRefreshTrigger.onNext(()) case .loadMore where AuthManager.shared.token?.isValid == true: - self.footerRefreshTrigger.onNext(()) + self?.footerRefreshTrigger.onNext(()) default: break } @@ -98,6 +103,8 @@ class PersonalViewController: ViewController { }.disposed(by: rx.disposeBag) + + } @@ -152,6 +159,16 @@ class PersonalViewController: ViewController { let resuableView: PersonalHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: "UICollectionElementKindSectionHeader", withReuseIdentifier: "PersonalHeaderView", for: indexPath) as! PersonalHeaderView self.personalHeaderView = resuableView + personalHeaderView?.segmentControl.titleBtnOnClick = { [weak self] (label, index) in + if index == 0 { + self?.personInfoLikeType.accept(.audio) + } else { + self?.personInfoLikeType.accept(.journal) + } + + } + + let section = dataSource.sectionModels.first.value // resuableView.user = viewModel.us @@ -175,12 +192,12 @@ class PersonalViewController: ViewController { // }.disposed(by: rx.disposeBag) - resuableView.followingButton.rx.tap.subscribe { _ in + resuableView.followingButton.rx.tap.subscribe { [weak self] _ in viewModel.followingButtonTrigger.accept(()) }.disposed(by: rx.disposeBag) - resuableView.messageButton.rx.tap.subscribe { _ in + resuableView.messageButton.rx.tap.subscribe { [weak self] _ in viewModel.messageButtonTrigger.accept(()) }.disposed(by: rx.disposeBag) @@ -193,13 +210,12 @@ class PersonalViewController: ViewController { } ) -// let collectionViewDataSource = person.collectionViewDataSource() -// -// output.items.bind(to: collectionView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) + + output.items.bind(to: collectionView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag) // - output.user.subscribe { user in - self.personalHeaderView?.user = user + output.user.subscribe { [weak self] user in + self?.personalHeaderView?.user = user }.disposed(by: rx.disposeBag) @@ -285,188 +301,12 @@ extension PersonalViewController { let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top) doubleColumnSection.boundarySupplementaryItems = [header] - doubleColumnSection.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 18, bottom: 0, trailing: 18) return doubleColumnSection } } -extension PersonalViewController { - //TODO -// static func tableViewDataSource(_ buttonTapHandler: @escaping (UITableViewCell, AudioTrack) -> Void) -> RxTableViewSectionedReloadDataSource { -// return RxTableViewSectionedReloadDataSource( -// configureCell: { dataSource, tableView, indexPath, item in -// let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell -// -//// cell.audioTrack = item -// -// cell.buttonTapCallback = {audioTrack in -// buttonTapHandler(cell, audioTrack) -// } -// -// return cell -// } -// ) -// } -} - - - -extension PersonalViewController { - -// static func collectionViewDataSource() -> RxCollectionViewSectionedReloadDataSource { -// return RxCollectionViewSectionedReloadDataSource( -// configureCell: { dataSource, collectionView, indexPath, item in -// // 配置和返回 cell -// let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "JournalViewCell", for: indexPath) as! JournalViewCell -// // 配置 cell -// cell.titleLabel.text = item.title -// cell.volLabel.text = item.subTitle -// -// return cell -// } -// ) -// } -} - - - - - - - - -class PersonalView: UIView { - lazy var segmentControl: ScrollSegmentView = { - - var style = SegmentStyle() - style.showLine = true - style.normalTitleColor = UIColor.secondaryText() - style.selectedTitleColor = UIColor.primaryText() - style.backgroundColor = UIColor.white - style.titleSelectFont = UIFont.systemFont(ofSize: 15, weight: .medium) - style.titleFont = UIFont.systemFont(ofSize: 15) - - style.scrollLineHeight = 2 - style.scrollLineColor = .primary() - style.coverBackgroundColor = .init(hex: 0x0d0d0d) - style.normalborderColor = UIColor.tertiaryText() - style.scrollTitle = false - style.showCover = false - style.normalborderColor = .clear - -// style.scrollTitle = true - style.lineSpace = 0 - - - - let segmentControl = ScrollSegmentView.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 32), segmentStyle: style, titles: ["喜欢的单曲", "收藏期刊"]) - -// segmentControl.scrollView.backgroundColor = .red - - return segmentControl - }() - - - let tableView: UITableView = { - let tableView = UITableView.init() - - return tableView - }() - - let collectionView: UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.minimumInteritemSpacing = 15 - layout.minimumLineSpacing = 24 - - layout.sectionInset = UIEdgeInsets.init(top: 0, left: 18, bottom: 0, right: 18) - - layout.itemSize = CGSize(width: (BaseDimensions.screenWidth - 18 * 2 - 15) / 2, height: 147) - - let collectionView = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: layout) - - collectionView.register(JournalViewCell.self, forCellWithReuseIdentifier: "JournalViewCell") - - return collectionView - }() - - - - var currentSearchType: SearchType = .audio { - didSet { - switch currentSearchType { - case .audio: - collectionView.isHidden = true - tableView.isHidden = false - case .journal: - collectionView.isHidden = false - tableView.isHidden = true - } - } - } - - - override init(frame: CGRect) { - super.init(frame: frame) - - makeUI() - - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func makeUI() { - segmentControl.titleBtnOnClick = { [weak self] (label, index) in - if index == 0 { - self?.currentSearchType = .audio - } else { - self?.currentSearchType = .journal - } - - } - - backgroundColor = .white - - addSubview(segmentControl) - addSubview(tableView) - addSubview(collectionView) - - } - - override func layoutSubviews() { - super.layoutSubviews() - - segmentControl.snp.makeConstraints { make in - make.left.equalTo(self).offset(18) - make.top.equalTo(self).offset(0) - make.height.equalTo(32) - make.width.equalTo(200) - } - - tableView.snp.makeConstraints { make in - make.left.equalTo(self) - make.right.equalTo(self) - make.top.equalTo(segmentControl.snp.bottom).offset(24) - make.bottom.equalTo(self) - } - - collectionView.snp.makeConstraints { make in - make.left.equalTo(self) - make.right.equalTo(self) - make.top.equalTo(segmentControl.snp.bottom).offset(24) - make.bottom.equalTo(self) - } - - - - } - - -} - class PersonalHeaderView: UICollectionReusableView { diff --git a/IndieMusic/IndieMusic/Modules/Personal/PersonalViewModel.swift b/IndieMusic/IndieMusic/Modules/Personal/PersonalViewModel.swift index 4f12fb8..236df38 100644 --- a/IndieMusic/IndieMusic/Modules/Personal/PersonalViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Personal/PersonalViewModel.swift @@ -58,14 +58,16 @@ class PersonalViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.viewWillAppear.subscribe { (_) in + input.viewWillAppear.subscribe { [weak self] _ in + guard let self = self else { return } + + self.requestUserData(userID: self.userID) .subscribe { user in self.user.accept(user) } onError: { error in }.disposed(by: self.rx.disposeBag) - }.disposed(by: rx.disposeBag) @@ -118,17 +120,22 @@ class PersonalViewModel: ViewModel, ViewModelType { + - - input.personInfoLikeType.subscribe { personInfoLikeType in + input.personInfoLikeType.subscribe { [weak self] personInfoLikeType in + guard let self = self, let personInfoLikeType = personInfoLikeType.element else { return } + self.personInfoLikeType.accept(personInfoLikeType) + print("personInfoLikeType \(personInfoLikeType)") - switch personInfoLikeType.element { + switch personInfoLikeType { case .audio: self.requestCollectSongList(userId: self.userID, page: self.page, size: 10) - .subscribe { items in + .subscribe { [weak self] items in + guard let self = self else { return } + self.items.accept([PersonInfoSection.audio(personInfoLikeType: self.personInfoLikeType.value, items: items)]) } onError: { error in @@ -136,14 +143,12 @@ class PersonalViewModel: ViewModel, ViewModelType { // case .journal: self.requestJournalCollectList(userId: self.userID, page: self.page, size: 10) - .subscribe { items in + .subscribe { [weak self] items in + guard let self = self else { return } self.items.accept([PersonInfoSection.audio(personInfoLikeType: self.personInfoLikeType.value, items: items)]) } onError: { error in }.disposed(by: self.rx.disposeBag) - - default: break - } @@ -154,9 +159,9 @@ class PersonalViewModel: ViewModel, ViewModelType { let cuttentItems = Observable.merge(audioItems.asObservable(), journalItems.asObservable()) - cuttentItems.subscribe { personInfoSection in + cuttentItems.subscribe { [weak self] personInfoSection in - self.items.accept(personInfoSection) + self?.items.accept(personInfoSection) }.disposed(by: rx.disposeBag) @@ -165,8 +170,8 @@ class PersonalViewModel: ViewModel, ViewModelType { followingButtonTrigger - .subscribe { _ in - guard let userID = self.user.value?.id else { return } + .subscribe { [weak self] _ in + guard let self = self, let userID = self.user.value?.id else { return } switch self.user.value?.relation { case .notFollowing: @@ -212,9 +217,9 @@ class PersonalViewModel: ViewModel, ViewModelType { case .blockedByMe: self.requestCancelLike(objectId: userID, collectType: .addBlockList) - .subscribe { _ in + .subscribe { [weak self] _ in - self.updateUserRelationStatus(relation: .following) + self?.updateUserRelationStatus(relation: .following) } onError: { error in diff --git a/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift index 70068d9..8c12833 100644 --- a/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewController.swift @@ -85,14 +85,16 @@ class AudioTrackListViewController: ViewController { }.disposed(by: rx.disposeBag) - output.reloadData.subscribe { audioTrack in - + output.reloadData.subscribe { [weak self] audioTrack in + guard let self = self else { return } + self.tableView.reloadData() }.disposed(by: rx.disposeBag) - self.audioMoreActionBottomView.closeButton.rx.tap.subscribe { _ in - + self.audioMoreActionBottomView.closeButton.rx.tap.subscribe { [weak self] _ in + guard let self = self else { return } + self.navigator.dismiss(sender: self) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift index 1c16f83..52d4c3e 100644 --- a/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Player/AudioTrackListViewModel.swift @@ -34,7 +34,9 @@ class AudioTrackListViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.viewWillAppear.subscribe { isViewWillAppear in + input.viewWillAppear.subscribe { [weak self] isViewWillAppear in + guard let self = self else { return } + if let playlist = AudioManager.sharedInstance.playlist { let arr = playlist.map { audioTrack in return JournalItem.audioItem(model: audioTrack) @@ -60,7 +62,9 @@ class AudioTrackListViewModel: ViewModel, ViewModelType { - input.notiPlayAudioTrack.subscribe { noti in + input.notiPlayAudioTrack.subscribe { [weak self] noti in + guard let self = self else { return } + guard let track = noti.element?.object as? AudioTrack else { return } self.reloadData.accept(track) diff --git a/IndieMusic/IndieMusic/Modules/Player/PlayerView.swift b/IndieMusic/IndieMusic/Modules/Player/PlayerView.swift index 1c36c1c..0734885 100644 --- a/IndieMusic/IndieMusic/Modules/Player/PlayerView.swift +++ b/IndieMusic/IndieMusic/Modules/Player/PlayerView.swift @@ -288,9 +288,17 @@ class PlayerScrollView: UIScrollView { return playerInfoView.playerSlider.slider } - if self.bounds.contains(point) { - return self - } + +// let playerInfoPoint = convert(point, to: playerInfoView) +// if playerInfoView.point(inside: playerInfoPoint, with: event) { +// return playerInfoView +// } + + + +// if self.bounds.contains(point) { +// return self +// } return super.hitTest(point, with: event) @@ -573,13 +581,10 @@ class PlayerInfoView: UIView { makeUI() -// numberLabel.text = "VOL 1092" -// titleLabel.text = "fdsfds" -// artistLabel.text = "1233321" -// startTimeLabel.text = "00:00" -// endTimeLabel.text = "00:00" -// -// coverView.backgroundColor = .gray + likeButton.addTarget(self, action: #selector(likeButtonClick), for: .touchUpInside) + } + + @objc func likeButtonClick() { } @@ -606,6 +611,8 @@ class PlayerInfoView: UIView { coverView.kf.setImage(with: URL.init(string: audioTrack.pic ?? "")) numberLabel.text = "VOL \(audioTrack.journalNo ?? "")" + likeButton.isSelected = audioTrack.haveCollect ?? false + } @@ -656,7 +663,6 @@ class PlayerInfoView: UIView { make.left.equalTo(self).offset(18) make.right.equalTo(self).offset(-18) make.top.equalTo(artistLabel.snp.bottom).offset(8) - make.height.equalTo(30) make.bottom.equalTo(self) } @@ -678,7 +684,12 @@ class PlayerInfoView: UIView { return shareButton } - if self.bounds.contains(point) { + let likePoint = convert(point, to: likeButton) + if likeButton.point(inside: likePoint, with: event) { + return likeButton + } + + if self.bounds.contains(point) { return self } diff --git a/IndieMusic/IndieMusic/Modules/Player/PlayerViewController.swift b/IndieMusic/IndieMusic/Modules/Player/PlayerViewController.swift index 06cda70..45d41bd 100644 --- a/IndieMusic/IndieMusic/Modules/Player/PlayerViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Player/PlayerViewController.swift @@ -117,13 +117,13 @@ class PlayerViewController: ViewController { }.disposed(by: rx.disposeBag) - viewModel.isLike - .bind(to: self.playerScrollView.playerInfoView.likeButton.rx.isSelected) - .disposed(by: rx.disposeBag) +// viewModel.isLike +// .bind(to: self.playerScrollView.playerInfoView.likeButton.rx.isSelected) +// .disposed(by: rx.disposeBag) - viewModel.isLike.subscribe { [weak self] isLike in - self?.playerScrollView.playerInfoView.likeButton.isSelected = isLike - }.disposed(by: rx.disposeBag) +// viewModel.isLike.subscribe { [weak self] isLike in +// self?.playerScrollView.playerInfoView.likeButton.isSelected = isLike +// }.disposed(by: rx.disposeBag) output.toShare.subscribe { [weak self] _ in @@ -153,6 +153,7 @@ class PlayerViewController: ViewController { self?.playerScrollView.audioTrack = audioTrack self?.blurEffectView.imageView.kf.setImage(with: URL.init(string: audioTrack.pic ?? "")) + }.disposed(by: rx.disposeBag) @@ -165,8 +166,9 @@ class PlayerViewController: ViewController { }.disposed(by: rx.disposeBag) - output.progress.subscribe { progress in - + output.progress.subscribe { [weak self] progress in + guard let self = self else { return } + if !self.playerScrollView.playerInfoView.playerSlider.isDrop { @@ -180,11 +182,15 @@ class PlayerViewController: ViewController { }.disposed(by: rx.disposeBag) - output.duration.subscribe { duration in + 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 { time in + output.time.subscribe { [weak self] time in + guard let self = self else { return } + self.playerScrollView.playerInfoView.playerSlider.updateTimeLabel(currentTime: time) }.disposed(by: rx.disposeBag) @@ -193,7 +199,8 @@ class PlayerViewController: ViewController { - self.playerControlView.listButton.rx.tap.subscribe { _ in + self.playerControlView.listButton.rx.tap.subscribe { [weak self] _ in + guard let self = self else { return } let audioTrackListViewModel = AudioTrackListViewModel.init(provider: viewModel.provider) self.navigator.show(segue: .audioTrackList(viewModel: audioTrackListViewModel), sender: self, transition: .navigationPresent(type: .audioTrackList)) diff --git a/IndieMusic/IndieMusic/Modules/Player/PlayerViewModel.swift b/IndieMusic/IndieMusic/Modules/Player/PlayerViewModel.swift index 85088c2..3ea7f1b 100644 --- a/IndieMusic/IndieMusic/Modules/Player/PlayerViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Player/PlayerViewModel.swift @@ -32,7 +32,6 @@ class PlayerViewModel: ViewModel, ViewModelType { struct Output { let items: BehaviorRelay<[PlayerLyricsSection]> -// let isLike: BehaviorRelay let shuffle: BehaviorRelay let audioTrack: PublishSubject let toShare: PublishSubject @@ -48,7 +47,6 @@ class PlayerViewModel: ViewModel, ViewModelType { let items = BehaviorRelay<[PlayerLyricsSection]>.init(value: []) - let isLike = BehaviorRelay.init(value: false) let isPlaying = BehaviorRelay.init(value: false) let shuffle = BehaviorRelay.init(value: false) let audioTrack = PublishSubject.init() @@ -85,11 +83,38 @@ class PlayerViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.likeButtonTrigger.drive { [weak self] _ in - guard let self = self else { return } - self.isLike.accept(!self.isLike.value) - }.disposed(by: rx.disposeBag) + + input.likeButtonTrigger.asObservable() + .withLatestFrom(audioTrack) // 使用 withLatestFrom 获取 audioTrack 的最新值 + .subscribe(onNext: { [weak self] latestAudioTrack in + guard let self = self else { return } + if latestAudioTrack.haveCollect == false { + self.requestLike(objectId: latestAudioTrack.id) + .subscribe { [weak self] _ in + guard let self = self else { return } + + var new = latestAudioTrack + new.haveCollect = true + + self.updateAudioTrack(audioTrack: new) + } onError: { error in + + }.disposed(by: self.rx.disposeBag) + } else { + self.requestCancelLike(objectId: latestAudioTrack.id) + .subscribe { [weak self] _ in + guard let self = self else { return } + var new = latestAudioTrack + new.haveCollect = false + + self.updateAudioTrack(audioTrack: new) + } onError: { error in + + }.disposed(by: self.rx.disposeBag) + } + }) + .disposed(by: rx.disposeBag) let lyrics = PlayerLyrics.init(lyrics: "1233211232") @@ -154,24 +179,29 @@ class PlayerViewModel: ViewModel, ViewModelType { AudioManager.sharedInstance.changeShuffle() }.disposed(by: rx.disposeBag) - input.notiPlayShuffle.subscribe { _ in + input.notiPlayShuffle.subscribe { [weak self] _ in + guard let self = self else { return } + self.playShuffleType.accept(AudioManager.sharedInstance.playerShuffleType) }.disposed(by: rx.disposeBag) - input.notiPlayPause.subscribe { noti in + input.notiPlayPause.subscribe { [weak self] noti in + guard let self = self else { return } + self.isPlaying.accept(true) }.disposed(by: rx.disposeBag) - input.notiPlayResume.subscribe { noti in + 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, -// isLike: isLike, shuffle: shuffle, audioTrack: audioTrack, toShare: toShare, @@ -183,6 +213,34 @@ class PlayerViewModel: ViewModel, ViewModelType { isPlaying: isPlaying) } + + func updateAudioTrack(audioTrack: AudioTrack) { + self.audioTrack.onNext(audioTrack) + + + if let index = AudioManager.sharedInstance.playlist?.firstIndex(where: { $0.id == audioTrack.id }) { + // 使用新的 AudioTrack 实例替换旧的 + AudioManager.sharedInstance.playlist?[index] = audioTrack + } + } + + + func requestLike(objectId: String) -> Observable { + return self.provider.like(objectId: objectId, collectType: LikeType.track.rawValue) + .trackActivity(loading) + .trackError(error) + + } + + + func requestCancelLike(objectId: String) -> Observable { + return self.provider.cancelLike(objectId: objectId, collectType: LikeType.track.rawValue) + .trackActivity(loading) + .trackError(error) + + } + + } extension PlayerViewModel { diff --git a/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift b/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift index b44f6a1..8861c10 100644 --- a/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Search/MusicStyleViewController.swift @@ -24,13 +24,12 @@ class MusicStyleViewController: ViewController { let doubleColumnSection = NSCollectionLayoutSection(group: doubleColumnGroup) -// doubleColumnSection.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 18, bottom: 0, trailing: 18) - let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(viewModel?.headerHeight ?? 100)) let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top) doubleColumnSection.boundarySupplementaryItems = [header] + doubleColumnSection.interGroupSpacing = 24 return doubleColumnSection @@ -88,13 +87,13 @@ class MusicStyleViewController: ViewController { view.addSubview(collectionView) - collectionView.rx.refresh.subscribe { refreshType in + collectionView.rx.refresh.subscribe { [weak self] refreshType in switch refreshType.element { case .refresh: - self.headerRefreshTrigger.onNext(()) + self?.headerRefreshTrigger.onNext(()) case .loadMore: - self.footerRefreshTrigger.onNext(()) + self?.footerRefreshTrigger.onNext(()) default: break } diff --git a/IndieMusic/IndieMusic/Modules/Search/SearchResultsViewModel.swift b/IndieMusic/IndieMusic/Modules/Search/SearchResultsViewModel.swift index 914ba55..35ca8df 100644 --- a/IndieMusic/IndieMusic/Modules/Search/SearchResultsViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Search/SearchResultsViewModel.swift @@ -46,7 +46,7 @@ class SearchResultsViewModel: ViewModel, ViewModelType { input.searchText.debounce(.milliseconds(500)) .drive { searchText in self.fetchSearchData(keyword: searchText ?? "") - .subscribe { searchResults in + .subscribe { [weak self] searchResults in let audioTrackArray = searchResults.songs?.map({ audioTrack in return SearchResultsItem.single(item: audioTrack) @@ -56,11 +56,9 @@ class SearchResultsViewModel: ViewModel, ViewModelType { return SearchResultsItem.journal(item: journal) }) - self.audioTrackItems.accept(audioTrackArray ?? []) - - self.journalItems.accept(journalArray ?? []) - + self?.audioTrackItems.accept(audioTrackArray ?? []) + self?.journalItems.accept(journalArray ?? []) } onError: { error in }.disposed(by: self.rx.disposeBag) @@ -69,7 +67,9 @@ class SearchResultsViewModel: ViewModel, ViewModelType { - input.searchType.subscribe { searchType in + input.searchType.subscribe { [weak self] searchType in + guard let self = self else { return } + self.searchType.accept(searchType.element ?? .audio) switch searchType.element { @@ -85,7 +85,9 @@ class SearchResultsViewModel: ViewModel, ViewModelType { let cuttentItems = Observable.merge(audioTrackItems.asObservable(), journalItems.asObservable()) - cuttentItems.subscribe { searchResultsItems in + cuttentItems.subscribe { [weak self] searchResultsItems in + guard let self = self else { return } + switch self.searchType.value { case .audio: self.items.accept([SearchResultsSection.single(title: "", items: self.audioTrackItems.value)]) diff --git a/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift b/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift index b95e449..f97c383 100644 --- a/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Search/SearchViewController.swift @@ -22,13 +22,12 @@ class SearchViewController: ViewController, UIScrollViewDelegate { let verticalGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(88)) let verticalGroup = NSCollectionLayoutGroup.horizontal(layoutSize: verticalGroupSize, subitem: item, count: 2) verticalGroup.interItemSpacing = .fixed(15) - verticalGroup.contentInsets = .init(top: 15, leading: 0, bottom: 0, trailing: 0) // 创建分区 let section = NSCollectionLayoutSection(group: verticalGroup) section.interGroupSpacing = 15 - section.contentInsets = .init(top: 0, leading: 18, bottom: 0, trailing: 18) + section.contentInsets = .init(top: 15, leading: 18, bottom: 15, trailing: 18) let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(104 + BaseDimensions.statusBarHeight)) let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top) @@ -123,11 +122,16 @@ class SearchViewController: ViewController, UIScrollViewDelegate { override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - collectionView.snp.makeConstraints { make in + collectionView.snp.remakeConstraints { make in make.left.equalTo(view) make.right.equalTo(view) make.top.equalTo(view).offset(-BaseDimensions.navBarHeight) + if AudioManager.sharedInstance.playlist?.count ?? 0 > 0 { + make.bottom.equalTo(view).offset(-66 - BaseDimensions.tabBarHeight) + } else { make.bottom.equalTo(view).offset(-BaseDimensions.tabBarHeight) + } + } } diff --git a/IndieMusic/IndieMusic/Modules/Search/SearchViewModel.swift b/IndieMusic/IndieMusic/Modules/Search/SearchViewModel.swift index 0afc10e..17415ba 100644 --- a/IndieMusic/IndieMusic/Modules/Search/SearchViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Search/SearchViewModel.swift @@ -32,8 +32,8 @@ class SearchViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { input.viewWillAppear.subscribe { _ in - self.fetchSearchCategoryData().subscribe { searchCategoryArray in - self.items.accept([SearchCategorySection.init(items: searchCategoryArray)]) + self.fetchSearchCategoryData().subscribe { [weak self] searchCategoryArray in + self?.items.accept([SearchCategorySection.init(items: searchCategoryArray)]) } onError: { error in }.disposed(by: self.rx.disposeBag) @@ -45,7 +45,9 @@ class SearchViewModel: ViewModel, ViewModelType { - input.selection.drive { indexPath in + input.selection.drive { [weak self] indexPath in + guard let self = self else { return } + guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return } self.itemSelected.onNext(sectionItem) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditDateViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditDateViewController.swift index 7f21c00..72cf094 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditDateViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditDateViewController.swift @@ -70,10 +70,10 @@ class EditDateViewModel: ViewModel, ViewModelType { - input.viewWillAppear.subscribe { (_) in - + input.viewWillAppear.subscribe { [weak self] _ in + guard let self = self else { return } + self.updateDays(forMonth: 1, year: self.selectedYear.value) - }.disposed(by: rx.disposeBag) @@ -236,14 +236,12 @@ class EditDateViewController: ViewController { - cancelButton.rx.tap.subscribe { _ in - self.navigator.dismiss(sender: self) + cancelButton.rx.tap.subscribe { [weak self] _ in + self?.navigator.dismiss(sender: self) }.disposed(by: rx.disposeBag) - saveButton.rx.tap.subscribe { _ in - print("日期\(viewModel.selectedYear.value)年\(viewModel.selectedMonth.value)月\(viewModel.selectedDay.value)日") - - self.navigator.dismiss(sender: self) + saveButton.rx.tap.subscribe { [weak self] _ in + self?.navigator.dismiss(sender: self) }.disposed(by: rx.disposeBag) } diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewController.swift index fa1c8dd..35a5963 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewController.swift @@ -87,16 +87,14 @@ class EditInfoViewController: TableViewController { }.disposed(by: rx.disposeBag) - output.user.subscribe { user in + output.user.subscribe { [weak self] user in guard let user = user.element else { return } - self.headerView.avatarView.kf.setImage(with: URL.init(string: user.avatar ?? "")) - - + self?.headerView.avatarView.kf.setImage(with: URL.init(string: user.avatar ?? "")) }.disposed(by: rx.disposeBag) - output.avatar.subscribe { url in - self.headerView.avatarView.kf.setImage(with: URL.init(string: url)) + output.avatar.subscribe { [weak self] url in + self?.headerView.avatarView.kf.setImage(with: URL.init(string: url)) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewModel.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewModel.swift index 3e425c2..3d60553 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewModel.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditInfoViewModel.swift @@ -43,8 +43,10 @@ class EditInfoViewModel: ViewModel, ViewModelType { func transform(input: Input) -> Output { - input.viewWillAppear.subscribe { (_) in - self.requestUserInfoData().subscribe { user in + input.viewWillAppear.subscribe { _ in + self.requestUserInfoData().subscribe { [weak self] user in + guard let self = self else { return } + self.user.onNext(user) self.updateItems(with: user) @@ -110,9 +112,9 @@ class EditInfoViewModel: ViewModel, ViewModelType { editAvatar.subscribe { imageData in self.editAvatar(imageData: imageData) - .subscribe { url in + .subscribe { [weak self] url in - self.avatar.onNext(url) + self?.avatar.onNext(url) } onError: { error in print("error: \(error)") }.disposed(by: self.rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditNameController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditNameController.swift index a8b36d4..a742829 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditNameController.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditNameController.swift @@ -140,8 +140,8 @@ class EditNameController: ViewController { .bind(to: self.editNameTextFieldView.textFieldView.rx.text) .disposed(by: rx.disposeBag) - output.dismiss.subscribe { _ in - self.navigator.pop(sender: self) + output.dismiss.subscribe { [weak self] _ in + self?.navigator.pop(sender: self) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSexViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSexViewController.swift index 9234b8e..8ebec05 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSexViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSexViewController.swift @@ -132,12 +132,12 @@ class EditSexViewController: ViewController, UIScrollViewDelegate { - output.popView.subscribe { _ in - self.navigator.pop(sender: self) + output.popView.subscribe { [weak self] _ in + self?.navigator.pop(sender: self) }.disposed(by: rx.disposeBag) - dismissButton.rx.tap.subscribe { _ in - self.navigator.dismiss(sender: self) + dismissButton.rx.tap.subscribe { [weak self] _ in + self?.navigator.dismiss(sender: self) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSignatureViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSignatureViewController.swift index 05c1ead..9fa4201 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSignatureViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/EditInfo/EditSignatureViewController.swift @@ -140,8 +140,8 @@ class EditSignatureViewController: ViewController { .bind(to: self.editNameTextFieldView.textFieldView.rx.text) .disposed(by: rx.disposeBag) - output.dismiss.subscribe { _ in - self.navigator.pop(sender: self) + output.dismiss.subscribe { [weak self] _ in + self?.navigator.pop(sender: self) }.disposed(by: rx.disposeBag) diff --git a/IndieMusic/IndieMusic/Modules/Setting/PhotoConfirmViewController.swift b/IndieMusic/IndieMusic/Modules/Setting/PhotoConfirmViewController.swift index bfe9796..14a7b08 100644 --- a/IndieMusic/IndieMusic/Modules/Setting/PhotoConfirmViewController.swift +++ b/IndieMusic/IndieMusic/Modules/Setting/PhotoConfirmViewController.swift @@ -41,8 +41,8 @@ class PhotoConfirmViewController: UIViewController { }.disposed(by: rx.disposeBag) cancelControl.rx.controlEvent(.touchUpInside) - .subscribe { _ in - self.dismiss(animated: true) + .subscribe { [weak self] _ in + self?.dismiss(animated: true) }.disposed(by: rx.disposeBag) } diff --git a/IndieMusic/IndieMusic/Networking/Api.swift b/IndieMusic/IndieMusic/Networking/Api.swift index dc2a6c7..0d61ea8 100644 --- a/IndieMusic/IndieMusic/Networking/Api.swift +++ b/IndieMusic/IndieMusic/Networking/Api.swift @@ -74,7 +74,7 @@ protocol IndieMusicAPI { /// 子评论列表 func subCommentList(parentId: String, page: Int, size: Int) -> Single<[Comment]> /// 评论点赞 - func commentLike(commentId: String) -> Single + func commentLike(commentId: String) -> Single /// 发送评论 func sendComment(content: String, journalId: String?, parentId: String?, journalImage: String?) -> Single @@ -90,5 +90,10 @@ protocol IndieMusicAPI { /// 随机播放 func randomAudioTrack(limit: Int) -> Single<[AudioTrack]> + /// 我的获赞 + func myThumbupList(page: Int, size: Int) -> Single<[MineThumbup]> + /// 我的评论 + func myCommentList(page: Int, size: Int) -> Single<[Comment]> + } diff --git a/IndieMusic/IndieMusic/Networking/Rest/APIConfig.swift b/IndieMusic/IndieMusic/Networking/Rest/APIConfig.swift index d9e5418..092befe 100644 --- a/IndieMusic/IndieMusic/Networking/Rest/APIConfig.swift +++ b/IndieMusic/IndieMusic/Networking/Rest/APIConfig.swift @@ -56,6 +56,9 @@ enum APIConfig { case randomAudioTrack(Int) + case myThumbupList(Int, Int) + case myCommentReplyList(Int, Int) + } extension APIConfig: TargetType { @@ -136,12 +139,16 @@ extension APIConfig: TargetType { case .randomAudioTrack(let limit): return "luoo-music/song/random/\(limit)" + case .myThumbupList(let page, let size): + return "luoo-user/my/myThumbupList/\(page)/\(size)" + case .myCommentReplyList(let page, let size): + return "luoo-user/my/myCommentReplyList/\(page)/\(size)" } } 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, .serach, .randomAudioTrack: + case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .serach, .randomAudioTrack, .myThumbupList, .myCommentReplyList: return .get case .sendsms, .login, .autoLogin, .editAvatar, .like, .checkVersion, .logout, .sendComment: return .post @@ -155,7 +162,7 @@ extension APIConfig: TargetType { 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, .serach, .randomAudioTrack: + 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, .serach, .randomAudioTrack, .myThumbupList, .myCommentReplyList: return URLEncoding.default case .autoLogin, .editUserInfo, .editAvatar, .checkVersion, .logout, .commentLike, .sendComment: @@ -167,7 +174,7 @@ extension APIConfig: TargetType { var task: Task { var parameters: [String: Any] = [:] switch self { - case .wechatAccessToken, .countryCode, .journalMusic, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .serach, .randomAudioTrack: + case .wechatAccessToken, .countryCode, .journalMusic, .imageCheckCode, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .serach, .randomAudioTrack, .myThumbupList, .myCommentReplyList: 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): @@ -196,7 +203,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, .serach, .randomAudioTrack, .sendComment: + 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, .serach, .randomAudioTrack, .sendComment, .myThumbupList, .myCommentReplyList: return ["Authorization": AuthManager.shared.token?.basicToken ?? ""] default: return nil diff --git a/IndieMusic/IndieMusic/Networking/Rest/RestApi.swift b/IndieMusic/IndieMusic/Networking/Rest/RestApi.swift index b66106e..58b4bfc 100644 --- a/IndieMusic/IndieMusic/Networking/Rest/RestApi.swift +++ b/IndieMusic/IndieMusic/Networking/Rest/RestApi.swift @@ -254,8 +254,8 @@ extension RestApi { return requestObject(.subCommentList(parentId, page, size), with: "data.rows", type: [Comment].self) } - func commentLike(commentId: String) -> Single { - return requestWithoutMapping(.commentLike(commentId, ["":""])).map{ _ in } + func commentLike(commentId: String) -> Single { + return requestObject(.commentLike(commentId, ["": ""]), with: "data", type: CommentThumbState.self) } @@ -274,7 +274,7 @@ extension RestApi { let dic = ["commentVo": commentVo] - return requestObject(.sendComment(dic), with: "data", type: Comment.self) + return requestObject(.sendComment(commentVo), with: "data", type: Comment.self) } func filterMenu() -> Single { @@ -298,4 +298,13 @@ extension RestApi { return requestObject(.randomAudioTrack(limit), with: "data", type: [AudioTrack].self) } + func myThumbupList(page: Int, size: Int) -> Single<[MineThumbup]> { + return requestObject(.myThumbupList(page, size), with: "data.rows", type: [MineThumbup].self) + } + + func myCommentList(page: Int, size: Int) -> Single<[Comment]> { + return requestObject(.myCommentReplyList(page, size), with: "data.rows", type: [Comment].self) + } + + } diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_comment_icon.imageset/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_comment_icon.imageset/Contents.json new file mode 100644 index 0000000..f32a641 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_comment_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "message_comment_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_comment_icon.imageset/message_comment_icon.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_comment_icon.imageset/message_comment_icon.svg new file mode 100644 index 0000000..4b12237 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_comment_icon.imageset/message_comment_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_follow_icon.imageset/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_follow_icon.imageset/Contents.json new file mode 100644 index 0000000..ab5247d --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_follow_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "message_follow_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_follow_icon.imageset/message_follow_icon.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_follow_icon.imageset/message_follow_icon.svg new file mode 100644 index 0000000..1a1b28a --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_follow_icon.imageset/message_follow_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_like_icon.imageset/Contents.json b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_like_icon.imageset/Contents.json new file mode 100644 index 0000000..27dc55d --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_like_icon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "message_like_icon.svg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_like_icon.imageset/message_like_icon.svg b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_like_icon.imageset/message_like_icon.svg new file mode 100644 index 0000000..cefcaf1 --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Assets.xcassets/message/message_like_icon.imageset/message_like_icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/IndieMusic/IndieMusic/Resources/Localizable/en.lproj/ChinaLocalizable.strings b/IndieMusic/IndieMusic/Resources/Localizable/en.lproj/ChinaLocalizable.strings new file mode 100644 index 0000000..e3b7c4c --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Localizable/en.lproj/ChinaLocalizable.strings @@ -0,0 +1,7 @@ +/* + ChinaLocalizable.strings + IndieMusic + + Created by WenLei on 2024/2/12. + +*/ diff --git a/IndieMusic/IndieMusic/Resources/Localizable/zh-Hans.lproj/ChinaLocalizable.strings b/IndieMusic/IndieMusic/Resources/Localizable/zh-Hans.lproj/ChinaLocalizable.strings new file mode 100644 index 0000000..e3b7c4c --- /dev/null +++ b/IndieMusic/IndieMusic/Resources/Localizable/zh-Hans.lproj/ChinaLocalizable.strings @@ -0,0 +1,7 @@ +/* + ChinaLocalizable.strings + IndieMusic + + Created by WenLei on 2024/2/12. + +*/