Home refresh component optimization

dev
wenlei 7 months ago
parent d3ffe765bf
commit 64bae0a657

@ -1924,7 +1924,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 15; CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = AY569L2R6W; DEVELOPMENT_TEAM = AY569L2R6W;
ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
@ -1965,7 +1965,7 @@
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 15; CURRENT_PROJECT_VERSION = 18;
DEVELOPMENT_TEAM = AY569L2R6W; DEVELOPMENT_TEAM = AY569L2R6W;
ENABLE_USER_SCRIPT_SANDBOXING = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;

@ -60,7 +60,7 @@ class CollectionViewController: ViewController {
make.edges.equalTo(view) make.edges.equalTo(view)
} }
collectionView.mj_header = MJRefreshNormalHeader.init(refreshingBlock: {[weak self] in collectionView.mj_header = RefreshHeader.init(refreshingBlock: {[weak self] in
self?.headerRefreshTrigger.onNext(()) self?.headerRefreshTrigger.onNext(())
}) })
collectionView.mj_footer = MJRefreshAutoStateFooter.init(refreshingBlock: {[weak self] in collectionView.mj_footer = MJRefreshAutoStateFooter.init(refreshingBlock: {[weak self] in

@ -155,20 +155,7 @@ class HomeRefreshHeader: MJRefreshStateHeader {
return refreshLoadingView return refreshLoadingView
}() }()
let tipsLabel: PaddingLabel = {
let tipsLabel = PaddingLabel.init(padding: .init(top: 5, left: 15, bottom: 5, right: 15), frame: .zero)
tipsLabel.font = UIFont.systemFont(ofSize: 15)
tipsLabel.textColor = .tertiaryText()
tipsLabel.text = "已刷新完成"
tipsLabel.backgroundColor = .red
tipsLabel.textColor = .primaryText()
tipsLabel.alpha = 1
tipsLabel.isHidden = true
return tipsLabel
}()
override init(frame: CGRect) { override init(frame: CGRect) {
@ -177,7 +164,6 @@ class HomeRefreshHeader: MJRefreshStateHeader {
stateLabel?.isHidden = true stateLabel?.isHidden = true
addSubview(self.gifLoadingView) addSubview(self.gifLoadingView)
addSubview(tipsLabel)
} }
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
@ -214,7 +200,7 @@ class HomeRefreshHeader: MJRefreshStateHeader {
override func placeSubviews() { override func placeSubviews() {
super.placeSubviews() super.placeSubviews()
backgroundColor = .red
gifLoadingView.backgroundColor = .blue gifLoadingView.backgroundColor = .blue
gifLoadingView.frame = CGRect.init(x: 0, y: 0, width: 60, height: 60) gifLoadingView.frame = CGRect.init(x: 0, y: 0, width: 60, height: 60)
@ -224,12 +210,7 @@ class HomeRefreshHeader: MJRefreshStateHeader {
let centerY = mj_h + 18 let centerY = mj_h + 18
gifLoadingView.center = CGPoint(x: centerX, y: centerY) gifLoadingView.center = CGPoint(x: centerX, y: centerY)
tipsLabel.snp.makeConstraints { make in
make.centerX.equalTo(gifLoadingView)
make.centerY.equalTo(gifLoadingView)
}
// tipsLabel.sizeToFit() // tipsLabel.sizeToFit()
// tipsLabel.center = CGPoint(x: centerX, y: centerY)
} }
override func scrollViewContentOffsetDidChange(_ change: [AnyHashable : Any]?) { override func scrollViewContentOffsetDidChange(_ change: [AnyHashable : Any]?) {
@ -280,6 +261,20 @@ class RefreshHeader: MJRefreshStateHeader {
return refreshLoadingView return refreshLoadingView
}() }()
let tipsLabel: PaddingLabel = {
let tipsLabel = PaddingLabel.init(padding: .init(top: 5, left: 15, bottom: 5, right: 15), frame: .zero)
tipsLabel.font = UIFont.systemFont(ofSize: 15)
tipsLabel.textColor = .tertiaryText()
tipsLabel.text = "已刷新完成"
// tipsLabel.backgroundColor = .red
tipsLabel.textAlignment = .center
tipsLabel.textColor = .primaryText()
tipsLabel.isHidden = true
tipsLabel.alpha = 0
return tipsLabel
}()
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
@ -287,6 +282,8 @@ class RefreshHeader: MJRefreshStateHeader {
stateLabel?.isHidden = true stateLabel?.isHidden = true
addSubview(self.gifLoadingView) addSubview(self.gifLoadingView)
addSubview(self.tipsLabel)
} }
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
@ -331,6 +328,9 @@ class RefreshHeader: MJRefreshStateHeader {
let centerY = mj_h * 0.5 let centerY = mj_h * 0.5
gifLoadingView.center = CGPoint(x: centerX, y: centerY) gifLoadingView.center = CGPoint(x: centerX, y: centerY)
tipsLabel.frame = CGRect.init(x: 0, y: 0, width: mj_w, height: 60)
tipsLabel.center = CGPoint(x: centerX, y: centerY)
} }
func calculateOpacity(withOffset offset: CGFloat) -> CGFloat { func calculateOpacity(withOffset offset: CGFloat) -> CGFloat {
@ -401,5 +401,27 @@ class RefreshHeader: MJRefreshStateHeader {
// Implement the initialization state logic here // Implement the initialization state logic here
} }
func endRefreshingWithMessage(_ message: String) {
tipsLabel.isHidden = false
tipsLabel.text = message
gifLoadingView.isHidden = true
UIView.animate(withDuration: 0.3) {
self.tipsLabel.alpha = 1
}
}
func hidenTipsLabel() {
UIView.animate(withDuration: 1) {
self.tipsLabel.alpha = 0
} completion: { _ in
self.gifLoadingView.isHidden = false
self.tipsLabel.isHidden = true
}
}
} }

@ -17,16 +17,17 @@ extension EnvironmentType {
var baseUrl: String { var baseUrl: String {
switch self { switch self {
case .production: case .production:
return "http://39.103.180.196:9012" return "http://api.indie.cn:9012"
case .development: case .development:
return "http://testapi.indie.cn:9012" return "http://39.103.180.196:9012"
// return "http://testapi.indie.cn:9012"
} }
} }
} }
struct Configs { struct Configs {
struct App { struct App {
static let environmentType: EnvironmentType = .production static let environmentType: EnvironmentType = .development
static let aggrementUrl = environmentType.baseUrl + "" static let aggrementUrl = environmentType.baseUrl + ""
static let universalLink = "" static let universalLink = ""
static let bundleIdentifier = "cn.indie.queyue" static let bundleIdentifier = "cn.indie.queyue"

@ -38,6 +38,29 @@ extension UIImage {
UIGraphicsEndImageContext(); UIGraphicsEndImageContext();
return img! return img!
} }
func resizeImage(targetSize: CGSize) -> UIImage {
let size = self.size
let widthRatio = targetSize.width / size.width
let heightRatio = targetSize.height / size.height
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
} else {
newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
}
let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
self.draw(in: rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage ?? self
}
} }
extension UIImageView { extension UIImageView {
@ -53,4 +76,9 @@ extension UIImageView {
currentURL = url // URL currentURL = url // URL
self.kf.setImage(with: url) self.kf.setImage(with: url)
} }
} }

@ -62,14 +62,24 @@ extension SearchResultsSection: SectionModelType {
struct SearchCategory: Codable { struct SearchCategory: Codable, IdentifiableType, Equatable {
let id: String? let id: String
let nameCh: String? let nameCh: String?
let nameEn: String? let nameEn: String?
let image: String? let image: String?
let description: String? let description: String?
let thumbnail: String?
var isExpand: Bool? var isExpand: Bool?
var identity: String {
return id
}
static func == (lhs: SearchCategory, rhs: SearchCategory) -> Bool {
return lhs.id == rhs.id && lhs.nameCh == rhs.nameCh && lhs.nameEn == rhs.nameEn && lhs.image == rhs.image && lhs.description == rhs.description && lhs.thumbnail == rhs.thumbnail && lhs.isExpand == rhs.isExpand
}
} }

@ -382,8 +382,28 @@ class HomeTabBarController: UITabBarController, Navigatable {
extension HomeTabBarController: UITabBarControllerDelegate { extension HomeTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if tabBarController.selectedViewController === viewController && viewController is UINavigationController {
if let navigationController = viewController as? UINavigationController,
let topViewController = navigationController.viewControllers.first as? TableViewController {
topViewController.tableView.mj_header?.beginRefreshing()
let feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
feedbackGenerator.impactOccurred()
} else if let navigationController = viewController as? UINavigationController,
let topViewController = navigationController.viewControllers.first as? CollectionViewController {
topViewController.collectionView.mj_header?.beginRefreshing()
let feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
feedbackGenerator.impactOccurred()
}
}
return viewController != tabBarController.selectedViewController return viewController != tabBarController.selectedViewController
} }
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
}
} }

@ -46,26 +46,12 @@ class HomeTabBarViewModel: ViewModel, ViewModelType {
func transform(input: Input) -> Output { func transform(input: Input) -> Output {
let tabBarItems = Observable.just([HomeTabBarItem.home, HomeTabBarItem.search, HomeTabBarItem.mine]).asDriver(onErrorJustReturn: []) let tabBarItems = Observable.just([HomeTabBarItem.home, HomeTabBarItem.search, HomeTabBarItem.mine]).asDriver(onErrorJustReturn: [])
//
//
// if authorized { if authorized {
// renewalToken() renewalToken()
// } }
//
//
//
//
// AudioManager.sharedInstance.progressObserver.subscribe { (time, duration, progress) in
//
// }.disposed(by: rx.disposeBag)
//
//
// input.notiPlayAudioTrack.subscribe { [weak self] noti in
// guard let track = noti.element?.object as? AudioTrack else { return }
//
// }.disposed(by: rx.disposeBag)
//
return Output.init(tabBarItems: tabBarItems, return Output.init(tabBarItems: tabBarItems,
notiPlayAudioTrack: input.notiPlayAudioTrack, notiPlayAudioTrack: input.notiPlayAudioTrack,
@ -93,15 +79,23 @@ class HomeTabBarViewModel: ViewModel, ViewModelType {
func renewalToken() { func renewalToken() {
self.provider.autoLogin().subscribe { token in self.provider.autoLogin(deviceId: AuthManager.shared.getUUID(), deviceBrand: AuthManager.shared.getDevice()).subscribe { token in
print("autoLogin: success") print("autoLogin: success")
AuthManager.setToken(token: Token.init(isValid: true, basicToken: token)) if token != "" {
AuthManager.setToken(token: Token.init(isValid: true, basicToken: token))
} else {
AuthManager.removeToken()
}
} onFailure: { error in } onFailure: { error in
print("autoLogin: error") print("autoLogin: error")
// if case HTTPServiceError.errorJudge(let err) = error { if case HTTPServiceError.errorJudge(let err) = error, err.code == 200 {
// SVProgressHUD.showText(withStatus: err.message) AuthManager.removeToken()
// } } else if case MoyaError.objectMapping(let err, let response) = error {
AuthManager.removeToken()
}
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
} }

@ -255,8 +255,31 @@ class HomeViewController: TableViewController, ScrollableNavBar {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
viewModel.showReFreshTips.subscribe { [weak self] tips in
if let header = self?.tableView.mj_header as? RefreshHeader {
header.endRefreshingWithMessage("数据刷新完毕")
print("state123 :\(header.state)")
if header.state == .idle {
header.hidenTipsLabel()
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
viewModel.endHeaderRefresh.accept(false)
header.hidenTipsLabel()
}
}
}
}.disposed(by: rx.disposeBag)
} }
override func viewDidLayoutSubviews() { override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews() super.viewDidLayoutSubviews()

@ -50,6 +50,8 @@ class HomeViewModel: ViewModel, ViewModelType {
let loginTrigger: PublishRelay<Void> = .init() let loginTrigger: PublishRelay<Void> = .init()
let showReFreshTips: PublishRelay<String> = .init()
func transform(input: Input) -> Output { func transform(input: Input) -> Output {
let carouselItems = BehaviorRelay<[Carousel]>(value: []) let carouselItems = BehaviorRelay<[Carousel]>(value: [])
@ -105,7 +107,9 @@ class HomeViewModel: ViewModel, ViewModelType {
} }
self.endHeaderRefresh.accept(false) self.showReFreshTips.accept("刷新完毕")
// self.endHeaderRefresh.accept(false)
}).disposed(by: rx.disposeBag) }).disposed(by: rx.disposeBag)

@ -63,12 +63,6 @@ class SongViewCell: UITableViewCell {
return musicIndicator return musicIndicator
}() }()
var downloadButton: DownloadButton = {
let downloadButton = DownloadButton.init()
return downloadButton
}()
var buttonTapCallback: ((AudioTrack) -> ())? var buttonTapCallback: ((AudioTrack) -> ())?
@ -101,9 +95,7 @@ class SongViewCell: UITableViewCell {
}.disposed(by: disposeBag) }.disposed(by: disposeBag)
downloadButton.changeDownloadState(to: audioTrack.downloadState ?? .no)
updateDownloadButton()
} }
} }
@ -134,7 +126,6 @@ class SongViewCell: UITableViewCell {
contentView.addSubview(detailLabel) contentView.addSubview(detailLabel)
contentView.addSubview(moreButtin) contentView.addSubview(moreButtin)
contentView.addSubview(musicIndicator) contentView.addSubview(musicIndicator)
contentView.addSubview(downloadButton)
contentView.addSubview(lineView) contentView.addSubview(lineView)
@ -164,35 +155,13 @@ class SongViewCell: UITableViewCell {
make.bottom.equalTo(coverView.snp.centerY).offset(-2) make.bottom.equalTo(coverView.snp.centerY).offset(-2)
make.right.equalTo(moreButtin.snp.left).offset(-10) make.right.equalTo(moreButtin.snp.left).offset(-10)
} }
//
// detailLabel.snp.makeConstraints { make in
// make.left.equalTo(coverView.snp.right).offset(15)
// make.top.equalTo(titleLabel.snp.bottom).offset(10)
// make.right.equalTo(musicIndicator.snp.left).offset(-6)
// }
downloadButton.snp.makeConstraints { make in detailLabel.snp.makeConstraints { make in
make.left.equalTo(coverView.snp.right).offset(15) make.left.equalTo(coverView.snp.right).offset(15)
make.top.equalTo(coverView.snp.centerY).offset(2) make.top.equalTo(coverView.snp.centerY).offset(2)
make.size.equalTo(CGSize.init(width: 24, height: 24)) make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
if downloadButton.isHidden {
detailLabel.snp.makeConstraints { make in
make.left.equalTo(downloadButton.snp.left)
make.centerY.equalTo(downloadButton)
make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
} else {
detailLabel.snp.makeConstraints { make in
make.left.equalTo(downloadButton.snp.right).offset(3)
make.centerY.equalTo(downloadButton)
make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
} }
lineView.snp.makeConstraints { make in lineView.snp.makeConstraints { make in
@ -210,26 +179,5 @@ class SongViewCell: UITableViewCell {
buttonTapCallback(audioTrack) buttonTapCallback(audioTrack)
} }
} }
func updateDownloadButton() {
if downloadButton.downloadState == DownloadState.no {
self.downloadButton.isHidden = true
detailLabel.snp.remakeConstraints { make in
make.left.equalTo(downloadButton.snp.left)
make.centerY.equalTo(downloadButton)
make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
} else {
self.downloadButton.isHidden = false
detailLabel.snp.remakeConstraints { make in
make.left.equalTo(downloadButton.snp.right).offset(3)
make.centerY.equalTo(downloadButton)
make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
}
}
} }

@ -298,6 +298,8 @@ class CommentViewController: TableViewController {
viewModel.selectedItem.subscribe { comment in viewModel.selectedItem.subscribe { comment in
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)

@ -108,14 +108,18 @@ class JournalDetailController: TableViewController {
.bind(to: viewModel.moreButtonTapped) .bind(to: viewModel.moreButtonTapped)
.disposed(by: cell.disposeBag) .disposed(by: cell.disposeBag)
cell.doubleTapGesture.rx.event.subscribe { tap in cell.doubleTapGesture.rx.event
.filter { _ in !tableView.isDragging }
.subscribe { tap in
if audioTrack.src == AudioManager.sharedInstance.currentTrack.value?.src { if audioTrack.src == AudioManager.sharedInstance.currentTrack.value?.src {
viewModel.doubleTapTrigger.accept(audioTrack) viewModel.doubleTapTrigger.accept(audioTrack)
} }
}.disposed(by: cell.disposeBag) }.disposed(by: cell.disposeBag)
cell.tapGesture.rx.event.subscribe { tap in cell.tapGesture.rx.event
.filter { _ in !tableView.isDragging }
.subscribe { tap in
guard let tap = tap.element else { return } guard let tap = tap.element else { return }
let location = tap.location(in: cell) let location = tap.location(in: cell)

@ -953,7 +953,7 @@ class JournalContainerViewCell: UITableViewCell {
disposeBag = DisposeBag() // DisposeBag disposeBag = DisposeBag() // DisposeBag
let dataSource = JournalContainerViewCell.dataSource() let dataSource = JournalContainerViewCell.dataSource()
let header = SearchCategory.init(id: nil, nameCh: nil, nameEn: nil, image: nil, description: nil) let header = SearchCategory.init(id: "", nameCh: nil, nameEn: nil, image: nil, description: nil, thumbnail: nil)
let sections = [MusicStyleSection.init(header: header, items: journals)] let sections = [MusicStyleSection.init(header: header, items: journals)]
let items = Driver.just(sections) let items = Driver.just(sections)

@ -154,13 +154,6 @@ class MineDownloadViewController: TableViewController {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
tableView.rx.willDisplayCell
.subscribe { [weak self] cell, indexPath in
guard let cell = cell as? MineDownloadViewCell else { return }
cell.downloadButton.changeDownloadState(to: .finished)
}.disposed(by: rx.disposeBag)
} }
@ -270,12 +263,6 @@ class MineDownloadViewCell: UITableViewCell {
return moreButton return moreButton
}() }()
var downloadButton: DownloadButton = {
let downloadButton = DownloadButton.init()
return downloadButton
}()
let musicIndicator: ESTMusicIndicatorView = { let musicIndicator: ESTMusicIndicatorView = {
let musicIndicator = ESTMusicIndicatorView.init() let musicIndicator = ESTMusicIndicatorView.init()
musicIndicator.tintColor = .primary() musicIndicator.tintColor = .primary()
@ -381,7 +368,6 @@ class MineDownloadViewCell: UITableViewCell {
contentView.addSubview(titleLabel) contentView.addSubview(titleLabel)
contentView.addSubview(detailLabel) contentView.addSubview(detailLabel)
contentView.addSubview(moreButton) contentView.addSubview(moreButton)
contentView.addSubview(downloadButton)
contentView.addSubview(musicIndicator) contentView.addSubview(musicIndicator)
@ -410,27 +396,13 @@ class MineDownloadViewCell: UITableViewCell {
make.bottom.equalTo(coverView.snp.centerY).offset(-2) make.bottom.equalTo(coverView.snp.centerY).offset(-2)
make.right.equalTo(moreButton.snp.left).offset(-10) make.right.equalTo(moreButton.snp.left).offset(-10)
} }
downloadButton.snp.makeConstraints { make in detailLabel.snp.makeConstraints { make in
make.left.equalTo(coverView.snp.right).offset(15) make.left.equalTo(coverView.snp.right).offset(15)
make.top.equalTo(coverView.snp.centerY).offset(2) make.top.equalTo(coverView.snp.centerY).offset(2)
make.size.equalTo(CGSize.init(width: 24, height: 24)) make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
if downloadButton.isHidden {
detailLabel.snp.makeConstraints { make in
make.left.equalTo(downloadButton.snp.left)
make.centerY.equalTo(downloadButton)
make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
} else {
detailLabel.snp.makeConstraints { make in
make.left.equalTo(downloadButton.snp.right).offset(3)
make.centerY.equalTo(downloadButton)
make.right.equalTo(musicIndicator.snp.left).offset(-6)
}
} }
} }

@ -188,13 +188,11 @@ class PersonalHeaderView: UIView, ShazamHeaderView {
} }
var blurEffectView: UIImageView = { var blurEffectView: BlurEffectView = {
let titleImageView = UIImageView.init() let titleImageView = BlurEffectView.init(style: .systemUltraThinMaterialDark, frame: CGRect.zero)
let blurEffect = UIBlurEffect(style: .regular) titleImageView.imageView.contentMode = .scaleAspectFill
let blurEffectView = UIVisualEffectView(effect: blurEffect) titleImageView.layer.masksToBounds = true
titleImageView.addSubview(blurEffectView)
return titleImageView return titleImageView
}() }()
@ -324,7 +322,7 @@ class PersonalHeaderView: UIView, ShazamHeaderView {
var user: User? { var user: User? {
didSet { didSet {
guard let user = user else { return } guard let user = user else { return }
blurEffectView.kf.setImage(with: URL.init(string: user.avatar ?? "")) blurEffectView.imageView.kf.setImage(with: URL.init(string: user.avatar ?? ""))
avatarView.kf.setImage(with: URL.init(string: user.avatar ?? "")) avatarView.kf.setImage(with: URL.init(string: user.avatar ?? ""))
nameLabel.text = user.nickName nameLabel.text = user.nickName

@ -204,7 +204,7 @@ class SearchViewCell: UICollectionViewCell {
var searchCategory: SearchCategory? { var searchCategory: SearchCategory? {
didSet { didSet {
guard let searchCategory = searchCategory else { return } guard let searchCategory = searchCategory else { return }
backgroudnView.kf.setImage(with: URL.init(string: searchCategory.image ?? "")) backgroudnView.kf.setImage(with: URL.init(string: searchCategory.thumbnail ?? ""))
titleLabel.text = searchCategory.nameCh titleLabel.text = searchCategory.nameCh
subTitleLabel.text = searchCategory.nameEn subTitleLabel.text = searchCategory.nameEn

@ -72,7 +72,7 @@ class CacheViewController: TableViewController {
case .file: case .file:
let mineDownloadViewModel = MineDownloadViewModel.init(provider: viewModel.provider) let mineDownloadViewModel = MineDownloadViewModel.init(provider: viewModel.provider)
self?.navigator.show(segue: .mineDownload(viewModel: mineDownloadViewModel), sender: self) self?.navigator.show(segue: .mineDownload(viewModel: mineDownloadViewModel), sender: self)
default: break default: break
} }

@ -46,7 +46,12 @@ class CacheViewModel: ViewModel, ViewModelType {
let cachePath = PINCacheAssetDataManager.Cache.diskCache.cacheURL.path let cachePath = PINCacheAssetDataManager.Cache.diskCache.cacheURL.path
FileManager.default.deleteContentsOfFolder(atPath: cachePath) FileManager.default.deleteContentsOfFolder(atPath: cachePath)
self.reloadData() self.reloadData()
case .other:
KingfisherManager.shared.cache.clearDiskCache {
print("磁盘缓存已清理完毕")
self.reloadData()
}
default: break default: break
} }
@ -91,7 +96,7 @@ class CacheViewModel: ViewModel, ViewModelType {
let cache = Cache.init(title: "听歌缓存", detail: "\(cacheSizeString)", buttonTitle: "清理") let cache = Cache.init(title: "听歌缓存", detail: "\(cacheSizeString)", buttonTitle: "清理")
let file = Cache.init(title: "音乐下载", detail: "\(downloadSizeString)", buttonTitle: "管理") let file = Cache.init(title: "音乐下载", detail: "\(downloadSizeString)", buttonTitle: "管理")
let other = Cache.init(title: "其他缓存(图片…)", detail: "\(otherSizeString)", buttonTitle: "") let other = Cache.init(title: "其他缓存(图片…)", detail: "\(otherSizeString)", buttonTitle: "清理")
self.items.accept([CacheSection.init(items: [.cache(cache), .file(file), .other(other)])]) self.items.accept([CacheSection.init(items: [.cache(cache), .file(file), .other(other)])])
@ -113,7 +118,7 @@ class CacheViewModel: ViewModel, ViewModelType {
let cache = Cache.init(title: "听歌缓存", detail: "\(cacheSizeString)", buttonTitle: "清理") let cache = Cache.init(title: "听歌缓存", detail: "\(cacheSizeString)", buttonTitle: "清理")
let file = Cache.init(title: "音乐下载", detail: "\(downloadSizeString)", buttonTitle: "管理") let file = Cache.init(title: "音乐下载", detail: "\(downloadSizeString)", buttonTitle: "管理")
let other = Cache.init(title: "其他缓存(图片…)", detail: "\(otherSizeString)", buttonTitle: "") let other = Cache.init(title: "其他缓存(图片…)", detail: "\(otherSizeString)", buttonTitle: "清理")
self.items.accept([CacheSection.init(items: [.cache(cache), .file(file), .other(other)])]) self.items.accept([CacheSection.init(items: [.cache(cache), .file(file), .other(other)])])

@ -12,6 +12,7 @@ import RxDataSources
import RxGesture import RxGesture
import PhotosUI import PhotosUI
import RxModal import RxModal
import RSKImageCropper
class EditInfoViewController: TableViewController { class EditInfoViewController: TableViewController {
let headerView: EditInfoHeaderView = { let headerView: EditInfoHeaderView = {
@ -100,6 +101,8 @@ class EditInfoViewController: TableViewController {
output.avatar.subscribe { [weak self] url in output.avatar.subscribe { [weak self] url in
self?.headerView.avatarView.kf.setImage(with: URL.init(string: url)) self?.headerView.avatarView.kf.setImage(with: URL.init(string: url))
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
let avatarViewTap = headerView.avatarView.rx.tapGesture().when(.recognized) let avatarViewTap = headerView.avatarView.rx.tapGesture().when(.recognized)
@ -109,6 +112,10 @@ class EditInfoViewController: TableViewController {
.subscribe { [weak self] gestureRecognizer in .subscribe { [weak self] gestureRecognizer in
guard let self = self else { return } guard let self = self else { return }
RxModal.photoPicker(presenter: .viewController(self)) { config in RxModal.photoPicker(presenter: .viewController(self)) { config in
config.filter = .images config.filter = .images
config.selectionLimit = 1 config.selectionLimit = 1
@ -120,7 +127,7 @@ class EditInfoViewController: TableViewController {
DispatchQueue.main.async { DispatchQueue.main.async {
if let image = image as? UIImage, if let image = image as? UIImage,
let imageData = image.pngData() { let imageData = image.pngData() {
viewModel.editAvatar.onNext(imageData) viewModel.showEditAvatar.onNext(imageData)
} }
} }
} }
@ -133,6 +140,18 @@ class EditInfoViewController: TableViewController {
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)
viewModel.showEditAvatar.subscribe { [weak self] imageData in
guard let image = UIImage.init(data: imageData) else { return }
let imageCropViewController = RSKImageCropViewController.init(image: image, cropMode: .circle)
imageCropViewController.delegate = self
self?.navigationController?.pushViewController(imageCropViewController, animated: true)
}.disposed(by: rx.disposeBag)
tableView.mj_header = nil tableView.mj_header = nil
tableView.mj_footer = nil tableView.mj_footer = nil
@ -141,6 +160,28 @@ class EditInfoViewController: TableViewController {
} }
extension EditInfoViewController: RSKImageCropViewControllerDelegate {
func imageCropViewControllerDidCancelCrop(_ controller: RSKImageCropViewController) {
self.navigationController?.popViewController(animated: true)
}
func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect, rotationAngle: CGFloat) {
guard let viewModel = self.viewModel as? EditInfoViewModel else { return }
if let data = croppedImage.resizeImage(targetSize: CGSize.init(width: 512, height: 512)).pngData() {
viewModel.editAvatar.onNext(data)
self.navigationController?.popViewController(animated: true)
}
}
func imageCropViewController(_ controller: RSKImageCropViewController, willCropImage originalImage: UIImage) {
}
}
extension EditInfoViewController { extension EditInfoViewController {
static func dataSource() -> RxTableViewSectionedReloadDataSource<SettingSection> { static func dataSource() -> RxTableViewSectionedReloadDataSource<SettingSection> {

@ -39,6 +39,7 @@ class EditInfoViewModel: ViewModel, ViewModelType {
let sexType = PublishRelay<SexType>() let sexType = PublishRelay<SexType>()
let editAvatar = PublishSubject<Data>() let editAvatar = PublishSubject<Data>()
let showEditAvatar = PublishSubject<Data>()
let avatar = PublishSubject<String>() let avatar = PublishSubject<String>()
func transform(input: Input) -> Output { func transform(input: Input) -> Output {
@ -111,11 +112,13 @@ class EditInfoViewModel: ViewModel, ViewModelType {
editAvatar.subscribe { imageData in editAvatar.subscribe { imageData in
SVProgressHUD.show()
self.editAvatar(imageData: imageData) self.editAvatar(imageData: imageData)
.subscribe { [weak self] url in .subscribe { [weak self] url in
SVProgressHUD.showText(withStatus: "上传成功")
self?.avatar.onNext(url) self?.avatar.onNext(url)
} onError: { error in } onError: { error in
SVProgressHUD.showText(withStatus: "上传失败")
print("error: \(error)") print("error: \(error)")
}.disposed(by: self.rx.disposeBag) }.disposed(by: self.rx.disposeBag)
}.disposed(by: rx.disposeBag) }.disposed(by: rx.disposeBag)

@ -23,7 +23,7 @@ protocol IndieMusicAPI {
/// 退 /// 退
func logout() -> Single<Void> func logout() -> Single<Void>
/// Token /// Token
func autoLogin() -> Single<String> func autoLogin(deviceId: String, deviceBrand: String) -> Single<String>
/// ///
func getUserInfo() -> Single<User> func getUserInfo() -> Single<User>
/// ///

@ -206,10 +206,10 @@ extension APIConfig: TargetType {
var parameterEncoding: ParameterEncoding { var parameterEncoding: ParameterEncoding {
switch self { switch self {
case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .sendsms, .imageCheckCode, .login, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .like, .cancelLike, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .searchSong, .searchJournal, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .suggestions, .commentReport, .deleteComment, .thanks, .collectJournalSongList, .otherMessageList, .otherMessageDetail, .checkVersion, .journalDetail, .commentDetail, .lastJournalCover, .journalDetailByID: case .wechatAccessToken, .journalList, .journalMusic, .countryCode, .sendsms, .imageCheckCode, .login, .getUserInfo, .carousel, .otherUserInfo, .single, .journal, .messageList, .like, .cancelLike, .collectSongList, .journalCollectList, .followingList, .followerList, .blackList, .hotCommentList, .latestCommentList, .subCommentList, .filterMenu, .journalRecommend, .searchCategory, .searchSong, .searchJournal, .randomAudioTrack, .myThumbupList, .myCommentReplyList, .suggestions, .commentReport, .deleteComment, .thanks, .collectJournalSongList, .otherMessageList, .otherMessageDetail, .checkVersion, .journalDetail, .commentDetail, .lastJournalCover, .journalDetailByID, .autoLogin:
return URLEncoding.default return URLEncoding.default
case .autoLogin, .editUserInfo, .editAvatar, .logout, .commentLike, .sendComment, .feedback: case .editUserInfo, .editAvatar, .logout, .commentLike, .sendComment, .feedback:
return JSONEncoding.default return JSONEncoding.default
} }
} }

@ -104,8 +104,10 @@ extension RestApi {
return requestWithoutMapping(.logout(["": ""])).map { _ in } return requestWithoutMapping(.logout(["": ""])).map { _ in }
} }
func autoLogin() -> Single<String> { func autoLogin(deviceId: String, deviceBrand: String) -> Single<String> {
return requestObject(.autoLogin(["": ""]), with: "data", type: String.self) let dic = ["deviceId": deviceId, "deviceBrand": deviceBrand]
return requestObject(.autoLogin(dic), with: "data", type: String.self)
} }
func sendsms(countryCode: String, mobile: String, imageCheckCode: String?, deviceId: String) -> Single<Void> { func sendsms(countryCode: String, mobile: String, imageCheckCode: String?, deviceId: String) -> Single<Void> {

@ -35,6 +35,7 @@ target 'IndieMusic' do
pod 'EFQRCode' pod 'EFQRCode'
pod 'GrowingTextView', '0.7.2' pod 'GrowingTextView', '0.7.2'
pod 'Tiercel' pod 'Tiercel'
pod 'RSKImageCropper'
pod 'NSObject+Rx' pod 'NSObject+Rx'

Loading…
Cancel
Save