mirror of
https://github.com/Finb/Bark.git
synced 2025-12-08 21:36:01 +00:00
替换为MVVM
This commit is contained in:
parent
2b1b087047
commit
b1e2f527e9
@ -63,6 +63,10 @@
|
||||
0637FA8C20E0D7A700E80174 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA8B20E0D7A700E80174 /* BaseViewController.swift */; };
|
||||
063C499520E36BF9001BCA35 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 063C499720E36BF9001BCA35 /* Localizable.strings */; };
|
||||
065A4D4220EE1A31002EB2DB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 063C499720E36BF9001BCA35 /* Localizable.strings */; };
|
||||
065BE4402563D649002A8CA4 /* SoundsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE43F2563D649002A8CA4 /* SoundsViewModel.swift */; };
|
||||
065BE4462563D7E5002A8CA4 /* ViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE4452563D7E5002A8CA4 /* ViewModelType.swift */; };
|
||||
065BE44B2563D8E1002A8CA4 /* Reusable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE44A2563D8E1002A8CA4 /* Reusable.swift */; };
|
||||
065BE4502563D939002A8CA4 /* SoundCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */; };
|
||||
0661A543204FDA4100965E4E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0661A542204FDA4100965E4E /* AppDelegate.swift */; };
|
||||
0661A545204FDA4100965E4E /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0661A544204FDA4100965E4E /* HomeViewController.swift */; };
|
||||
0661A54A204FDA4100965E4E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0661A549204FDA4100965E4E /* Assets.xcassets */; };
|
||||
@ -175,6 +179,10 @@
|
||||
0637FA8B20E0D7A700E80174 /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; };
|
||||
063C499620E36BF9001BCA35 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
063C499820E36C15001BCA35 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
065BE43F2563D649002A8CA4 /* SoundsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundsViewModel.swift; sourceTree = "<group>"; };
|
||||
065BE4452563D7E5002A8CA4 /* ViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelType.swift; sourceTree = "<group>"; };
|
||||
065BE44A2563D8E1002A8CA4 /* Reusable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reusable.swift; sourceTree = "<group>"; };
|
||||
065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundCellViewModel.swift; sourceTree = "<group>"; };
|
||||
0661A53F204FDA4100965E4E /* Bark.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Bark.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0661A542204FDA4100965E4E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
0661A544204FDA4100965E4E /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = "<group>"; };
|
||||
@ -249,6 +257,7 @@
|
||||
068F66B2247BD84C00DAD25A /* MessageListViewController.swift */,
|
||||
06885EB5247FB9880004A303 /* MessageSettingsViewController.swift */,
|
||||
060481ED250F404500BC9799 /* SoundsViewController.swift */,
|
||||
065BE43F2563D649002A8CA4 /* SoundsViewModel.swift */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
@ -263,6 +272,7 @@
|
||||
06C5953024811392006B98F3 /* ArchiveSettingCell.swift */,
|
||||
06C595352481160F006B98F3 /* BKLabel.swift */,
|
||||
060481EF250F51CA00BC9799 /* SoundCell.swift */,
|
||||
065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */,
|
||||
062B98C2251B2762004562E7 /* BKButton.swift */,
|
||||
062B98C7251B27AE004562E7 /* UINavigationItem+Extension.swift */,
|
||||
);
|
||||
@ -336,10 +346,20 @@
|
||||
path = NotificationContentExtension;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
065BE4442563D7AA002A8CA4 /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
065BE4452563D7E5002A8CA4 /* ViewModelType.swift */,
|
||||
065BE44A2563D8E1002A8CA4 /* Reusable.swift */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
0661A536204FDA4100965E4E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
063204EF250B6DC2001561EC /* Sounds */,
|
||||
065BE4442563D7AA002A8CA4 /* Common */,
|
||||
0604F7DD20620D3800B32F09 /* Model */,
|
||||
0604F7DC20620D3400B32F09 /* View */,
|
||||
0604F7DB20620D2700B32F09 /* Controller */,
|
||||
@ -664,12 +684,14 @@
|
||||
060481EE250F404500BC9799 /* SoundsViewController.swift in Sources */,
|
||||
0603706D20E23EC000F4CA05 /* BarkSFSafariViewController.swift in Sources */,
|
||||
06C5953124811392006B98F3 /* ArchiveSettingCell.swift in Sources */,
|
||||
065BE4502563D939002A8CA4 /* SoundCellViewModel.swift in Sources */,
|
||||
06B1158F247BB1FB006D91FB /* Message.swift in Sources */,
|
||||
06C595362481160F006B98F3 /* BKLabel.swift in Sources */,
|
||||
0637FA7820E0926D00E80174 /* BarkTargetType.swift in Sources */,
|
||||
0637FA7E20E0969800E80174 /* Client.swift in Sources */,
|
||||
0661A545204FDA4100965E4E /* HomeViewController.swift in Sources */,
|
||||
06C5952F248107F5006B98F3 /* iCloudStatusCell.swift in Sources */,
|
||||
065BE44B2563D8E1002A8CA4 /* Reusable.swift in Sources */,
|
||||
0637FA8620E0AB6600E80174 /* UIColor+Extension.swift in Sources */,
|
||||
0637FA8A20E0D58800E80174 /* NewServerViewController.swift in Sources */,
|
||||
0637FA8220E09C4B00E80174 /* BarkNavigationController.swift in Sources */,
|
||||
@ -685,6 +707,8 @@
|
||||
06C5952D2480E3F8006B98F3 /* LabelCell.swift in Sources */,
|
||||
0637FA7C20E0930E00E80174 /* BarkApi.swift in Sources */,
|
||||
0637FA8020E0981E00E80174 /* BarkSettings.swift in Sources */,
|
||||
065BE4402563D649002A8CA4 /* SoundsViewModel.swift in Sources */,
|
||||
065BE4462563D7E5002A8CA4 /* ViewModelType.swift in Sources */,
|
||||
0603706B20E20A7C00F4CA05 /* String+Extension.swift in Sources */,
|
||||
068F66B3247BD84C00DAD25A /* MessageListViewController.swift in Sources */,
|
||||
0661A543204FDA4100965E4E /* AppDelegate.swift in Sources */,
|
||||
|
||||
49
Common/Reusable.swift
Normal file
49
Common/Reusable.swift
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// Reusable.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/17.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
|
||||
private var prepareForReuseBag: Int8 = 0
|
||||
|
||||
@objc public protocol Reusable : class {
|
||||
func prepareForReuse()
|
||||
}
|
||||
|
||||
extension UITableViewCell: Reusable {}
|
||||
extension UITableViewHeaderFooterView: Reusable {}
|
||||
extension UICollectionReusableView: Reusable {}
|
||||
|
||||
extension Reactive where Base: Reusable {
|
||||
var prepareForReuse: Observable<Void> {
|
||||
return Observable.of(sentMessage(#selector(Base.prepareForReuse)).map { _ in }, deallocated).merge()
|
||||
}
|
||||
|
||||
var reuseBag: DisposeBag {
|
||||
MainScheduler.ensureExecutingOnScheduler()
|
||||
|
||||
if let bag = objc_getAssociatedObject(base, &prepareForReuseBag) as? DisposeBag {
|
||||
return bag
|
||||
}
|
||||
|
||||
let bag = DisposeBag()
|
||||
objc_setAssociatedObject(base, &prepareForReuseBag, bag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
|
||||
|
||||
_ = sentMessage(#selector(Base.prepareForReuse))
|
||||
.subscribe(onNext: { [weak base] _ in
|
||||
guard let strongBase = base else {
|
||||
return
|
||||
}
|
||||
let newBag = DisposeBag()
|
||||
objc_setAssociatedObject(strongBase, &prepareForReuseBag, newBag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
|
||||
})
|
||||
|
||||
return bag
|
||||
}
|
||||
}
|
||||
19
Common/ViewModelType.swift
Normal file
19
Common/ViewModelType.swift
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// ViewModelType.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/17.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
|
||||
protocol ViewModelType {
|
||||
associatedtype Input
|
||||
associatedtype Output
|
||||
|
||||
func transform(input: Input) -> Output
|
||||
}
|
||||
|
||||
class ViewModel:NSObject{ }
|
||||
@ -9,15 +9,35 @@
|
||||
import UIKit
|
||||
import Material
|
||||
class BaseViewController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let viewModel:ViewModel
|
||||
init(viewModel:ViewModel) {
|
||||
self.viewModel = viewModel
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
self.view.backgroundColor = Color.grey.lighten5
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle{
|
||||
get {
|
||||
return .lightContent
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
makeUI()
|
||||
bindViewModel()
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
|
||||
}
|
||||
func bindViewModel(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
import UserNotifications
|
||||
import Material
|
||||
class HomeViewController: BaseViewController {
|
||||
class HomeViewController: UIViewController {
|
||||
|
||||
let newButton: BKButton = {
|
||||
let btn = BKButton()
|
||||
@ -42,7 +42,7 @@ class HomeViewController: BaseViewController {
|
||||
notice: NSLocalizedString("setSounds"),
|
||||
queryParameter: "sound=minuet",
|
||||
moreInfo:NSLocalizedString("viewAllSounds"),
|
||||
moreViewController: SoundsViewController()
|
||||
moreViewController: SoundsViewController(viewModel: SoundsViewModel())
|
||||
),
|
||||
PreviewModel(
|
||||
body: NSLocalizedString("archiveNotificationMessageTitle"),
|
||||
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
import Material
|
||||
import RealmSwift
|
||||
|
||||
class MessageListViewController: BaseViewController {
|
||||
class MessageListViewController: UIViewController {
|
||||
let tableView: UITableView = {
|
||||
let tableView = UITableView()
|
||||
tableView.separatorStyle = .none
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
import Material
|
||||
class MessageSettingsViewController: BaseViewController {
|
||||
class MessageSettingsViewController: UIViewController {
|
||||
let tableView: UITableView = {
|
||||
let tableView = UITableView()
|
||||
tableView.separatorStyle = .none
|
||||
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
import Material
|
||||
import SnapKit
|
||||
import SafariServices
|
||||
class NewServerViewController: BaseViewController {
|
||||
class NewServerViewController: UIViewController {
|
||||
|
||||
let addressTextField : TextField = {
|
||||
let textField = TextField()
|
||||
|
||||
@ -10,55 +10,70 @@ import UIKit
|
||||
import Material
|
||||
import AVKit
|
||||
|
||||
class SoundsViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
import NSObject_Rx
|
||||
|
||||
class SoundsViewController: BaseViewController {
|
||||
let tableView: UITableView = {
|
||||
let tableView = UITableView()
|
||||
tableView.backgroundColor = Color.grey.lighten5
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "\(SoundCell.self)")
|
||||
tableView.register(SoundCell.self, forCellReuseIdentifier: "\(SoundCell.self)")
|
||||
return tableView
|
||||
}()
|
||||
let audios:[AVURLAsset] = {
|
||||
var urls = Bundle.main.urls(forResourcesWithExtension: "caf", subdirectory: nil) ?? []
|
||||
urls.sort { (u1, u2) -> Bool in
|
||||
u1.lastPathComponent.localizedStandardCompare(u2.lastPathComponent) == ComparisonResult.orderedAscending
|
||||
}
|
||||
let audios = urls.map { (url) -> AVURLAsset in
|
||||
let asset = AVURLAsset(url: url)
|
||||
return asset
|
||||
}
|
||||
return audios
|
||||
}()
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
override func makeUI() {
|
||||
self.title = NSLocalizedString("notificationSound")
|
||||
self.tableView.dataSource = self
|
||||
self.tableView.delegate = self
|
||||
|
||||
self.view.addSubview(self.tableView)
|
||||
self.tableView.snp.makeConstraints { (make) in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
let header = UILabel()
|
||||
header.fontSize = 12
|
||||
header.text = " \(NSLocalizedString("previewSound"))"
|
||||
header.textColor = Color.darkText.secondary
|
||||
header.frame = CGRect(x: 0, y: 0, width: 0, height: 40)
|
||||
self.tableView.tableHeaderView = header
|
||||
|
||||
self.tableView.tableHeaderView = {
|
||||
let header = UILabel()
|
||||
header.fontSize = 12
|
||||
header.text = " \(NSLocalizedString("previewSound"))"
|
||||
header.textColor = Color.darkText.secondary
|
||||
header.frame = CGRect(x: 0, y: 0, width: 0, height: 40)
|
||||
return header
|
||||
}()
|
||||
}
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return audios.count
|
||||
}
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(SoundCell.self)") as? SoundCell ?? SoundCell()
|
||||
cell.nameLabel.text = audios[indexPath.row].url.deletingPathExtension().lastPathComponent
|
||||
cell.durationLabel.text = "\(String(format: "%.2g", CMTimeGetSeconds(audios[indexPath.row].duration))) second(s)";
|
||||
return cell
|
||||
}
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
var soundID:SystemSoundID = 0
|
||||
AudioServicesCreateSystemSoundID(audios[indexPath.row].url as CFURL, &soundID)
|
||||
AudioServicesPlaySystemSoundWithCompletion(soundID) {
|
||||
AudioServicesDisposeSystemSoundID(soundID)
|
||||
override func bindViewModel() {
|
||||
guard let viewModel = viewModel as? SoundsViewModel else {
|
||||
return
|
||||
}
|
||||
|
||||
let output = viewModel.transform(
|
||||
input: SoundsViewModel.Input(soundSelected: self.tableView.rx
|
||||
.modelSelected(SoundCellViewModel.self)
|
||||
.asDriver()))
|
||||
|
||||
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String,SoundCellViewModel>> { (source, tableView, indexPath, item) -> UITableViewCell in
|
||||
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(SoundCell.self)") as? SoundCell else {
|
||||
return UITableViewCell()
|
||||
}
|
||||
cell.bindViewModel(model: item)
|
||||
return cell
|
||||
}
|
||||
|
||||
output.audios
|
||||
.map{ [SectionModel(model: "model", items: $0)] }
|
||||
.bind(to: tableView.rx.items(dataSource: dataSource))
|
||||
.disposed(by: rx.disposeBag)
|
||||
|
||||
output.copyNameAction.drive(onNext: { name in
|
||||
UIPasteboard.general.string = name.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
Client.shared.currentNavigationController?.showSnackbar(text: NSLocalizedString("Copy"))
|
||||
}).disposed(by: rx.disposeBag)
|
||||
|
||||
output.playAction.drive(onNext: { url in
|
||||
var soundID:SystemSoundID = 0
|
||||
AudioServicesCreateSystemSoundID(url, &soundID)
|
||||
AudioServicesPlaySystemSoundWithCompletion(soundID) {
|
||||
AudioServicesDisposeSystemSoundID(soundID)
|
||||
}
|
||||
}).disposed(by: rx.disposeBag)
|
||||
}
|
||||
}
|
||||
|
||||
49
Controller/SoundsViewModel.swift
Normal file
49
Controller/SoundsViewModel.swift
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// SoundsViewModel.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/17.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import AVKit
|
||||
|
||||
class SoundsViewModel:ViewModel,ViewModelType {
|
||||
|
||||
struct Input {
|
||||
var soundSelected:Driver<SoundCellViewModel>
|
||||
}
|
||||
struct Output {
|
||||
var audios:Observable<[SoundCellViewModel]>
|
||||
var copyNameAction: Driver<String>
|
||||
var playAction: Driver<CFURL>
|
||||
}
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
let models = { () -> [AVURLAsset] in
|
||||
var urls = Bundle.main.urls(forResourcesWithExtension: "caf", subdirectory: nil) ?? []
|
||||
urls.sort { (u1, u2) -> Bool in
|
||||
u1.lastPathComponent.localizedStandardCompare(u2.lastPathComponent) == ComparisonResult.orderedAscending
|
||||
}
|
||||
let audios = urls.map { (url) -> AVURLAsset in
|
||||
let asset = AVURLAsset(url: url)
|
||||
return asset
|
||||
}
|
||||
return audios
|
||||
}().map { SoundCellViewModel(model: $0 ) }
|
||||
|
||||
let copyAction = Driver.merge(
|
||||
models.map { $0.copyNameAction.asDriver(onErrorDriveWith: .empty()) }
|
||||
).asDriver()
|
||||
|
||||
return Output(
|
||||
audios: Observable.just(models),
|
||||
copyNameAction: copyAction,
|
||||
playAction: input.soundSelected.map{ $0.model.url as CFURL }
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
7
Podfile
7
Podfile
@ -15,6 +15,13 @@ def pods
|
||||
pod 'DeviceKit'
|
||||
pod 'DefaultsKit', :git => 'https://github.com/nmdias/DefaultsKit'
|
||||
pod 'IceCream'
|
||||
|
||||
pod 'RxSwift'
|
||||
pod 'RxCocoa'
|
||||
pod 'RxGesture'
|
||||
pod 'RxDataSources'
|
||||
pod 'NSObject+Rx'
|
||||
|
||||
end
|
||||
|
||||
target 'Bark' do
|
||||
|
||||
37
Podfile.lock
37
Podfile.lock
@ -2,6 +2,7 @@ PODS:
|
||||
- Alamofire (5.2.0)
|
||||
- DefaultsKit (0.2.0)
|
||||
- DeviceKit (3.2.0)
|
||||
- Differentiator (4.0.1)
|
||||
- FDFullscreenPopGesture (1.1)
|
||||
- IceCream (1.13.1):
|
||||
- RealmSwift
|
||||
@ -18,12 +19,26 @@ PODS:
|
||||
- Moya/RxSwift (14.0.0):
|
||||
- Moya/Core
|
||||
- RxSwift (~> 5.0)
|
||||
- "NSObject+Rx (5.1.0)":
|
||||
- RxSwift (~> 5.1)
|
||||
- ObjectMapper (4.2.0)
|
||||
- Realm (5.0.0):
|
||||
- Realm/Headers (= 5.0.0)
|
||||
- Realm/Headers (5.0.0)
|
||||
- RealmSwift (5.0.0):
|
||||
- Realm (= 5.0.0)
|
||||
- RxCocoa (5.1.1):
|
||||
- RxRelay (~> 5)
|
||||
- RxSwift (~> 5)
|
||||
- RxDataSources (4.0.1):
|
||||
- Differentiator (~> 4.0)
|
||||
- RxCocoa (~> 5.0)
|
||||
- RxSwift (~> 5.0)
|
||||
- RxGesture (3.0.2):
|
||||
- RxCocoa (~> 5.1)
|
||||
- RxSwift (~> 5.1)
|
||||
- RxRelay (5.1.1):
|
||||
- RxSwift (~> 5)
|
||||
- RxSwift (5.1.1)
|
||||
- SnapKit (5.0.1)
|
||||
- SVProgressHUD (2.2.5)
|
||||
@ -37,12 +52,24 @@ DEPENDENCIES:
|
||||
- KVOController
|
||||
- Material
|
||||
- Moya/RxSwift
|
||||
- "NSObject+Rx"
|
||||
- ObjectMapper
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
- RxGesture
|
||||
- RxSwift
|
||||
- SnapKit
|
||||
- SVProgressHUD
|
||||
- SwiftyJSON
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
- Differentiator
|
||||
- "NSObject+Rx"
|
||||
- RxCocoa
|
||||
- RxDataSources
|
||||
- RxGesture
|
||||
- RxRelay
|
||||
trunk:
|
||||
- Alamofire
|
||||
- DeviceKit
|
||||
@ -73,20 +100,26 @@ SPEC CHECKSUMS:
|
||||
Alamofire: c1ca147559e730bfb2182c8c7aafbdd90a867987
|
||||
DefaultsKit: 6c767941b2c3fe34c4d70e300e6c3b80c94964dd
|
||||
DeviceKit: d081659419cce07c0b5239dbc9fb39ed7413c7fe
|
||||
Differentiator: 886080237d9f87f322641dedbc5be257061b0602
|
||||
FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
|
||||
IceCream: 0447d87b55df85651dd60b15712cef64dbe1cb54
|
||||
KVOController: d72ace34afea42468329623b3379ab3cd1d286b6
|
||||
Material: a2a3f400a3b549d53ef89e56c58c4535b29db387
|
||||
Motion: cf1e060e489f6661126374d5c60dbd2ed991605c
|
||||
Moya: 5b45dacb75adb009f97fde91c204c1e565d31916
|
||||
"NSObject+Rx": fa6bbcc1ab1faa06b01466bc09b1e0692bbc5946
|
||||
ObjectMapper: 1eb41f610210777375fa806bf161dc39fb832b81
|
||||
Realm: 76066d333de26f97e9caedaa85ee3ff4a62ca265
|
||||
RealmSwift: c1bdff09b422569dc6881410d9ccf712bcdb79b0
|
||||
RxCocoa: 32065309a38d29b5b0db858819b5bf9ef038b601
|
||||
RxDataSources: efee07fa4de48477eca0a4611e6d11e2da9c1114
|
||||
RxGesture: d6bd7447ca3a596c7a9702a6a2b6a2bb5d8bae54
|
||||
RxRelay: d77f7d771495f43c556cbc43eebd1bb54d01e8e9
|
||||
RxSwift: 81470a2074fa8780320ea5fe4102807cb7118178
|
||||
SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb
|
||||
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
|
||||
SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7
|
||||
|
||||
PODFILE CHECKSUM: 90c7dcd577fc40757291126890d6791408bb905a
|
||||
PODFILE CHECKSUM: f0191b272c872b4d43da19a114ad4be556fb7eba
|
||||
|
||||
COCOAPODS: 1.8.4
|
||||
COCOAPODS: 1.10.0
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
import Material
|
||||
import AVKit
|
||||
|
||||
class SoundCell: UITableViewCell {
|
||||
let copyButton = IconButton(image: UIImage(named: "baseline_file_copy_white_24pt"), tintColor: Color.grey.base)
|
||||
@ -29,6 +30,8 @@ class SoundCell: UITableViewCell {
|
||||
|
||||
self.contentView.addSubview(nameLabel)
|
||||
self.contentView.addSubview(durationLabel)
|
||||
self.contentView.addSubview(copyButton)
|
||||
|
||||
nameLabel.snp.makeConstraints { (make) in
|
||||
make.left.top.equalToSuperview().offset(15)
|
||||
}
|
||||
@ -37,21 +40,34 @@ class SoundCell: UITableViewCell {
|
||||
make.top.equalTo(nameLabel.snp.bottom).offset(5)
|
||||
make.bottom.equalToSuperview().offset(-15)
|
||||
}
|
||||
self.contentView.addSubview(copyButton)
|
||||
copyButton.snp.makeConstraints { (make) in
|
||||
make.right.equalToSuperview().offset(-15)
|
||||
make.centerY.equalToSuperview()
|
||||
make.width.height.equalTo(40)
|
||||
}
|
||||
copyButton.addTarget(self, action: #selector(copyName), for: .touchUpInside)
|
||||
}
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
@objc func copyName(){
|
||||
if let urlStr = self.nameLabel.text{
|
||||
UIPasteboard.general.string = urlStr.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
Client.shared.currentNavigationController?.showSnackbar(text: NSLocalizedString("Copy"))
|
||||
|
||||
var viewModel:ViewModel?
|
||||
func bindViewModel(model:ViewModel){
|
||||
guard let viewModel = model as? SoundCellViewModel else {
|
||||
return
|
||||
}
|
||||
self.viewModel = model
|
||||
|
||||
viewModel.name
|
||||
.bind(to: nameLabel.rx.text)
|
||||
.disposed(by: rx.reuseBag)
|
||||
viewModel.duration
|
||||
.map { String(format: "%.2f", CMTimeGetSeconds($0) ) }
|
||||
.bind(to: durationLabel.rx.text)
|
||||
.disposed(by: rx.reuseBag)
|
||||
|
||||
copyButton.rx.tap
|
||||
.map{ viewModel.name.value }
|
||||
.bind(to: viewModel.copyNameAction)
|
||||
.disposed(by: rx.reuseBag)
|
||||
}
|
||||
}
|
||||
|
||||
27
View/SoundCellViewModel.swift
Normal file
27
View/SoundCellViewModel.swift
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// SoundCellViewModel.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/17.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import AVKit
|
||||
|
||||
class SoundCellViewModel:ViewModel {
|
||||
let name = BehaviorRelay<String>(value: "")
|
||||
let duration = BehaviorRelay<CMTime>(value: .zero)
|
||||
|
||||
let copyNameAction = PublishRelay<String>()
|
||||
let playAction = PublishRelay<CFURL>()
|
||||
|
||||
let model: AVURLAsset
|
||||
init(model: AVURLAsset) {
|
||||
self.model = model
|
||||
name.accept(model.url.deletingPathExtension().lastPathComponent)
|
||||
duration.accept(model.duration)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user