添加 MessageListViewModel

重构 MessageListViewController
This commit is contained in:
Fin 2020-11-22 16:12:59 +08:00
parent 84a8813f5f
commit 2140923db4
6 changed files with 266 additions and 92 deletions

View File

@ -52,6 +52,7 @@
0632CE2320EC9098003FDF46 /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0632CE2220EC9098003FDF46 /* NotificationViewController.swift */; }; 0632CE2320EC9098003FDF46 /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0632CE2220EC9098003FDF46 /* NotificationViewController.swift */; };
0632CE2620EC9098003FDF46 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0632CE2420EC9098003FDF46 /* MainInterface.storyboard */; }; 0632CE2620EC9098003FDF46 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0632CE2420EC9098003FDF46 /* MainInterface.storyboard */; };
0632CE2A20EC9098003FDF46 /* NotificationContentExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0632CE1E20EC9098003FDF46 /* NotificationContentExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 0632CE2A20EC9098003FDF46 /* NotificationContentExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 0632CE1E20EC9098003FDF46 /* NotificationContentExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
0633E80A256A091B00ED0680 /* MJRefresh+Rx.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0633E809256A091B00ED0680 /* MJRefresh+Rx.swift */; };
0637FA7820E0926D00E80174 /* BarkTargetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA7720E0926D00E80174 /* BarkTargetType.swift */; }; 0637FA7820E0926D00E80174 /* BarkTargetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA7720E0926D00E80174 /* BarkTargetType.swift */; };
0637FA7A20E092B300E80174 /* Observable+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA7920E092B300E80174 /* Observable+Extension.swift */; }; 0637FA7A20E092B300E80174 /* Observable+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA7920E092B300E80174 /* Observable+Extension.swift */; };
0637FA7C20E0930E00E80174 /* BarkApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA7B20E0930E00E80174 /* BarkApi.swift */; }; 0637FA7C20E0930E00E80174 /* BarkApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0637FA7B20E0930E00E80174 /* BarkApi.swift */; };
@ -74,6 +75,8 @@
0661A54D204FDA4100965E4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0661A54B204FDA4100965E4E /* LaunchScreen.storyboard */; }; 0661A54D204FDA4100965E4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0661A54B204FDA4100965E4E /* LaunchScreen.storyboard */; };
0667D192247D162C005DE2ED /* MessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */; }; 0667D192247D162C005DE2ED /* MessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */; };
0667D194247D1BA0005DE2ED /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D193247D1BA0005DE2ED /* Date+Extension.swift */; }; 0667D194247D1BA0005DE2ED /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D193247D1BA0005DE2ED /* Date+Extension.swift */; };
0672CB06256903F700570C9D /* MessageListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0672CB05256903F700570C9D /* MessageListViewModel.swift */; };
067B2EB525693E38008B6BE1 /* MessageTableViewCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 067B2EB425693E38008B6BE1 /* MessageTableViewCellViewModel.swift */; };
06802E5320ECC40C00767047 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0661A549204FDA4100965E4E /* Assets.xcassets */; }; 06802E5320ECC40C00767047 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0661A549204FDA4100965E4E /* Assets.xcassets */; };
06885EB6247FB9880004A303 /* MessageSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06885EB5247FB9880004A303 /* MessageSettingsViewController.swift */; }; 06885EB6247FB9880004A303 /* MessageSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06885EB5247FB9880004A303 /* MessageSettingsViewController.swift */; };
068F66B3247BD84C00DAD25A /* MessageListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 068F66B2247BD84C00DAD25A /* MessageListViewController.swift */; }; 068F66B3247BD84C00DAD25A /* MessageListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 068F66B2247BD84C00DAD25A /* MessageListViewController.swift */; };
@ -175,6 +178,7 @@
0632CE2220EC9098003FDF46 /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = "<group>"; }; 0632CE2220EC9098003FDF46 /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = "<group>"; };
0632CE2520EC9098003FDF46 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; }; 0632CE2520EC9098003FDF46 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
0632CE2720EC9098003FDF46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 0632CE2720EC9098003FDF46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0633E809256A091B00ED0680 /* MJRefresh+Rx.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MJRefresh+Rx.swift"; sourceTree = "<group>"; };
0637FA7720E0926D00E80174 /* BarkTargetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarkTargetType.swift; sourceTree = "<group>"; }; 0637FA7720E0926D00E80174 /* BarkTargetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarkTargetType.swift; sourceTree = "<group>"; };
0637FA7920E092B300E80174 /* Observable+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Observable+Extension.swift"; sourceTree = "<group>"; }; 0637FA7920E092B300E80174 /* Observable+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Observable+Extension.swift"; sourceTree = "<group>"; };
0637FA7B20E0930E00E80174 /* BarkApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarkApi.swift; sourceTree = "<group>"; }; 0637FA7B20E0930E00E80174 /* BarkApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarkApi.swift; sourceTree = "<group>"; };
@ -199,6 +203,8 @@
0661A54E204FDA4100965E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 0661A54E204FDA4100965E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0667D191247D162C005DE2ED /* MessageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewCell.swift; sourceTree = "<group>"; }; 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewCell.swift; sourceTree = "<group>"; };
0667D193247D1BA0005DE2ED /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; }; 0667D193247D1BA0005DE2ED /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = "<group>"; };
0672CB05256903F700570C9D /* MessageListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageListViewModel.swift; sourceTree = "<group>"; };
067B2EB425693E38008B6BE1 /* MessageTableViewCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewCellViewModel.swift; sourceTree = "<group>"; };
0683486A2050F1310024B6DA /* Bark.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Bark.entitlements; sourceTree = "<group>"; }; 0683486A2050F1310024B6DA /* Bark.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Bark.entitlements; sourceTree = "<group>"; };
0683487020510FB20024B6DA /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; 0683487020510FB20024B6DA /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; };
0683487220510FB20024B6DA /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; }; 0683487220510FB20024B6DA /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; };
@ -265,12 +271,13 @@
children = ( children = (
0637FA8B20E0D7A700E80174 /* BaseViewController.swift */, 0637FA8B20E0D7A700E80174 /* BaseViewController.swift */,
0637FA8120E09C4B00E80174 /* BarkNavigationController.swift */, 0637FA8120E09C4B00E80174 /* BarkNavigationController.swift */,
0603706C20E23EC000F4CA05 /* BarkSFSafariViewController.swift */,
0661A544204FDA4100965E4E /* HomeViewController.swift */, 0661A544204FDA4100965E4E /* HomeViewController.swift */,
065BE4542565055F002A8CA4 /* HomeViewModel.swift */, 065BE4542565055F002A8CA4 /* HomeViewModel.swift */,
0637FA8920E0D58800E80174 /* NewServerViewController.swift */, 0637FA8920E0D58800E80174 /* NewServerViewController.swift */,
06BBB895256518760076F63E /* NewServerViewModel.swift */, 06BBB895256518760076F63E /* NewServerViewModel.swift */,
0603706C20E23EC000F4CA05 /* BarkSFSafariViewController.swift */,
068F66B2247BD84C00DAD25A /* MessageListViewController.swift */, 068F66B2247BD84C00DAD25A /* MessageListViewController.swift */,
0672CB05256903F700570C9D /* MessageListViewModel.swift */,
06885EB5247FB9880004A303 /* MessageSettingsViewController.swift */, 06885EB5247FB9880004A303 /* MessageSettingsViewController.swift */,
06BBB8B62567AC140076F63E /* MessageSettingsViewModel.swift */, 06BBB8B62567AC140076F63E /* MessageSettingsViewModel.swift */,
060481ED250F404500BC9799 /* SoundsViewController.swift */, 060481ED250F404500BC9799 /* SoundsViewController.swift */,
@ -285,6 +292,7 @@
06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */, 06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */,
0603706820E1F89500F4CA05 /* PreviewCardCell.swift */, 0603706820E1F89500F4CA05 /* PreviewCardCell.swift */,
0667D191247D162C005DE2ED /* MessageTableViewCell.swift */, 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */,
067B2EB425693E38008B6BE1 /* MessageTableViewCellViewModel.swift */,
06C5952C2480E3F8006B98F3 /* LabelCell.swift */, 06C5952C2480E3F8006B98F3 /* LabelCell.swift */,
06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */, 06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */,
06C5953024811392006B98F3 /* ArchiveSettingCell.swift */, 06C5953024811392006B98F3 /* ArchiveSettingCell.swift */,
@ -370,6 +378,7 @@
0667D193247D1BA0005DE2ED /* Date+Extension.swift */, 0667D193247D1BA0005DE2ED /* Date+Extension.swift */,
06C5953224811505006B98F3 /* ArchiveSettingManager.swift */, 06C5953224811505006B98F3 /* ArchiveSettingManager.swift */,
06BBB8C82567B6730076F63E /* Operators.swift */, 06BBB8C82567B6730076F63E /* Operators.swift */,
0633E809256A091B00ED0680 /* MJRefresh+Rx.swift */,
); );
path = Common; path = Common;
sourceTree = "<group>"; sourceTree = "<group>";
@ -678,12 +687,14 @@
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Bark/Pods-Bark-resources.sh", "${PODS_ROOT}/Target Support Files/Pods-Bark/Pods-Bark-resources.sh",
"${PODS_ROOT}/MJRefresh/MJRefresh/MJRefresh.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/Material/com.cosmicmind.material.icons.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/Material/com.cosmicmind.material.icons.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/Material/com.cosmicmind.material.fonts.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/Material/com.cosmicmind.material.fonts.bundle",
"${PODS_ROOT}/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle", "${PODS_ROOT}/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle",
); );
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MJRefresh.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/com.cosmicmind.material.icons.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/com.cosmicmind.material.icons.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/com.cosmicmind.material.fonts.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/com.cosmicmind.material.fonts.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SVProgressHUD.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SVProgressHUD.bundle",
@ -711,6 +722,8 @@
06BBB896256518760076F63E /* NewServerViewModel.swift in Sources */, 06BBB896256518760076F63E /* NewServerViewModel.swift in Sources */,
06BBB8C92567B6730076F63E /* Operators.swift in Sources */, 06BBB8C92567B6730076F63E /* Operators.swift in Sources */,
0603706920E1F89500F4CA05 /* PreviewCardCell.swift in Sources */, 0603706920E1F89500F4CA05 /* PreviewCardCell.swift in Sources */,
0672CB06256903F700570C9D /* MessageListViewModel.swift in Sources */,
0633E80A256A091B00ED0680 /* MJRefresh+Rx.swift in Sources */,
0637FA8C20E0D7A700E80174 /* BaseViewController.swift in Sources */, 0637FA8C20E0D7A700E80174 /* BaseViewController.swift in Sources */,
062B98C8251B27AE004562E7 /* UINavigationItem+Extension.swift in Sources */, 062B98C8251B27AE004562E7 /* UINavigationItem+Extension.swift in Sources */,
060481EE250F404500BC9799 /* SoundsViewController.swift in Sources */, 060481EE250F404500BC9799 /* SoundsViewController.swift in Sources */,
@ -727,6 +740,7 @@
065BE44B2563D8E1002A8CA4 /* Reusable.swift in Sources */, 065BE44B2563D8E1002A8CA4 /* Reusable.swift in Sources */,
0637FA8620E0AB6600E80174 /* UIColor+Extension.swift in Sources */, 0637FA8620E0AB6600E80174 /* UIColor+Extension.swift in Sources */,
0637FA8A20E0D58800E80174 /* NewServerViewController.swift in Sources */, 0637FA8A20E0D58800E80174 /* NewServerViewController.swift in Sources */,
067B2EB525693E38008B6BE1 /* MessageTableViewCellViewModel.swift in Sources */,
0637FA8220E09C4B00E80174 /* BarkNavigationController.swift in Sources */, 0637FA8220E09C4B00E80174 /* BarkNavigationController.swift in Sources */,
0637FA7A20E092B300E80174 /* Observable+Extension.swift in Sources */, 0637FA7A20E092B300E80174 /* Observable+Extension.swift in Sources */,
060481F0250F51CA00BC9799 /* SoundCell.swift in Sources */, 060481F0250F51CA00BC9799 /* SoundCell.swift in Sources */,

View File

@ -183,7 +183,7 @@ extension HomeViewController {
}) })
} }
@objc func history(){ @objc func history(){
self.navigationController?.pushViewController(MessageListViewController(), animated: true) self.navigationController?.pushViewController(MessageListViewController(viewModel: MessageListViewModel()), animated: true)
} }
@objc func refreshState() { @objc func refreshState() {
switch Client.shared.state { switch Client.shared.state {

View File

@ -9,120 +9,131 @@
import UIKit import UIKit
import Material import Material
import RealmSwift import RealmSwift
import RxCocoa
import RxDataSources
import MJRefresh
class MessageListViewController: UIViewController { class MessageListViewController: BaseViewController {
let tableView: UITableView = { let tableView: UITableView = {
let tableView = UITableView() let tableView = UITableView()
tableView.separatorStyle = .none tableView.separatorStyle = .none
tableView.backgroundColor = Color.grey.lighten5 tableView.backgroundColor = Color.grey.lighten5
tableView.register(MessageTableViewCell.self, forCellReuseIdentifier: "cell") tableView.register(MessageTableViewCell.self, forCellReuseIdentifier: "\(MessageTableViewCell.self)")
return tableView return tableView
}() }()
var results:Results<Message>?
deinit {
print("message list deinit")
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = NSLocalizedString("historyMessage")
let settingButton: BKButton = {
let settingButton = BKButton() let settingButton = BKButton()
settingButton.setImage(Icon.settings, for: .normal) settingButton.setImage(Icon.settings, for: .normal)
settingButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40) settingButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
settingButton.addTarget(self, action: #selector(settingClick), for: .touchUpInside) return settingButton
}()
deinit {
print("message list deinit")
}
override func makeUI() {
self.title = NSLocalizedString("historyMessage")
navigationItem.setRightBarButtonItem(item: UIBarButtonItem(customView: settingButton)) navigationItem.setRightBarButtonItem(item: UIBarButtonItem(customView: settingButton))
self.view.addSubview(tableView) self.view.addSubview(tableView)
tableView.dataSource = self
tableView.delegate = self
tableView.snp.makeConstraints { (make) in tableView.snp.makeConstraints { (make) in
make.edges.equalToSuperview() make.edges.equalToSuperview()
} }
tableView.rx.setDelegate(self).disposed(by: rx.disposeBag)
tableView.mj_footer = MJRefreshAutoFooter()
self.refresh()
} }
@objc func settingClick (){ override func bindViewModel() {
self.navigationController?.pushViewController(MessageSettingsViewController(viewModel: MessageSettingsViewModel()), animated: true) guard let viewModel = self.viewModel as? MessageListViewModel else {
return
} }
func refresh() { let output = viewModel.transform(input: MessageListViewModel.Input(
if let realm = try? Realm() { settingClick: self.settingButton.rx.tap.asDriver(),
results = realm.objects(Message.self).filter("isDeleted != true").sorted(byKeyPath: "createDate", ascending: false) loadMore: tableView.mj_footer!.rx.refresh.asDriver(),
self.tableView.reloadData() itemDelete: tableView.rx.itemDeleted.asDriver(),
itemSelected: tableView.rx.modelSelected(MessageTableViewCellViewModel.self).asDriver()
))
//
output.settingClick
.drive(onNext: {[weak self] viewModel in
self?.navigationController?
.pushViewController(MessageSettingsViewController(viewModel: viewModel),
animated: true)
})
.disposed(by: rx.disposeBag)
//tableView
output.refreshAction
.drive(tableView.rx.refreshAction)
.disposed(by: rx.disposeBag)
//tableView
let dataSource = RxTableViewSectionedAnimatedDataSource<MessageSection>(
animationConfiguration: AnimationConfiguration(
insertAnimation: .none,
reloadAnimation: .none,
deleteAnimation: .left),
configureCell:{ (source, tableView, indexPath, item) -> UITableViewCell in
guard let cell = tableView.dequeueReusableCell(withIdentifier: "\(MessageTableViewCell.self)") as? MessageTableViewCell else {
return UITableViewCell ()
}
cell.bindViewModel(model: item)
return cell
}, canEditRowAtIndexPath: { _, _ in
return true
})
output.messages
.drive(tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)
//messagealert
output.alertMessage.drive(onNext: {[weak self] message in
self?.alertMessage(message: message)
}).disposed(by: rx.disposeBag)
//messageURL
output.urlTap.drive(onNext: { url in
if ["http","https"].contains(url.scheme?.lowercased() ?? ""){
Client.shared.currentNavigationController?.present(BarkSFSafariViewController(url: url), animated: true, completion: nil)
} }
else{ else{
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} }
}).disposed(by: rx.disposeBag)
}
}
extension MessageListViewController: UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let results = results{
return results.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MessageTableViewCell
cell.message = results![indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .destructive, title: "删除") {[weak self] (action, sourceView, actionPerformed) in
if let realm = try? Realm() {
try? realm.write {
let message = self?.results?[indexPath.row]
message?.isDeleted = true
}
}
_ = self?.results?.dropFirst(indexPath.row)
self?.tableView.performBatchUpdates({
self?.tableView.deleteRows(at: [indexPath], with: .none)
}, completion: nil)
actionPerformed(true)
} }
let configuration = UISwipeActionsConfiguration(actions: [action]) func alertMessage(message:String) {
return configuration
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let copyAction = UIAlertAction(title: NSLocalizedString("Copy2"), style: .default, handler: {[weak self] let copyAction = UIAlertAction(title: NSLocalizedString("Copy2"), style: .default, handler: {[weak self]
(alert: UIAlertAction) -> Void in (alert: UIAlertAction) -> Void in
if let message = self?.results?[indexPath.row] { UIPasteboard.general.string = message
var str:String = ""
if let title = message.title {
str += "\(title)\n"
}
if let body = message.body {
str += "\(body)\n"
}
if let url = message.url {
str += "\(url)"
}
str = String(str.prefix(str.count - 1))
UIPasteboard.general.string = str
self?.showSnackbar(text: NSLocalizedString("Copy")) self?.showSnackbar(text: NSLocalizedString("Copy"))
}
}) })
let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel"), style: .cancel, handler: { let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel"), style: .cancel, handler: { _ in })
(alert: UIAlertAction) -> Void in
})
alertController.addAction(copyAction) alertController.addAction(copyAction)
alertController.addAction(cancelAction) alertController.addAction(cancelAction)
Client.shared.currentNavigationController?.present(alertController, animated: true, completion: nil) Client.shared.currentNavigationController?.present(alertController, animated: true, completion: nil)
} }
}
extension MessageListViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .destructive, title: "删除") {[weak self] (action, sourceView, actionPerformed) in
self?.tableView.dataSource?.tableView?(self!.tableView, commit: .delete, forRowAt: indexPath)
actionPerformed(true)
}
let configuration = UISwipeActionsConfiguration(actions: [action])
return configuration
}
} }

View File

@ -0,0 +1,145 @@
//
// MessageListViewModel.swift
// Bark
//
// Created by huangfeng on 2020/11/21.
// Copyright © 2020 Fin. All rights reserved.
//
import Foundation
import RxSwift
import RxDataSources
import RxCocoa
import RealmSwift
class MessageListViewModel: ViewModel,ViewModelType {
struct Input {
var settingClick: Driver<Void>
var loadMore: Driver<Void>
var itemDelete: Driver<IndexPath>
var itemSelected: Driver<MessageTableViewCellViewModel>
}
struct Output {
var messages:Driver<[MessageSection]>
var settingClick: Driver<MessageSettingsViewModel>
var refreshAction:Driver<MJRefreshAction>
var alertMessage:Driver<String>
var urlTap:Driver<URL>
}
let results:Results<Message>? = {
if let realm = try? Realm() {
return realm.objects(Message.self)
.filter("isDeleted != true")
.sorted(byKeyPath: "createDate", ascending: false)
}
return nil
}()
var page = 0
let pageCount = 20
func getNextPage() -> [Message] {
if let result = results {
let startIndex = page * pageCount
let endIndex = min(startIndex + pageCount, result.count)
guard endIndex > startIndex else {
return []
}
var messages:[Message] = []
for i in startIndex ..< endIndex {
messages.append(result[i])
}
page += 1
return messages
}
return []
}
func transform(input: Input) -> Output {
let settingClick = input.settingClick
.map{
MessageSettingsViewModel()
}
.asDriver()
let alertMessage = input.itemSelected.map { (model) -> String in
let message = model.message
var copyContent:String = ""
if let title = message.title {
copyContent += "\(title)\n"
}
if let body = message.body {
copyContent += "\(body)\n"
}
if let url = message.url {
copyContent += "\(url)\n"
}
copyContent = String(copyContent.prefix(copyContent.count - 1))
return copyContent
}
//
let messagesRelay = BehaviorRelay<[MessageSection]>(value: [])
let refreshAction = BehaviorRelay<MJRefreshAction>(value: .none)
Observable<Void>.just(())
.concat(input.loadMore)
.subscribe(onNext: {[weak self] in
guard let strongSelf = self else { return }
let messages = strongSelf.getNextPage()
let cellViewModels = messages.map({ (message) -> MessageTableViewCellViewModel in
return MessageTableViewCellViewModel(message: message)
})
refreshAction.accept(.endLoadmore)
if var section = messagesRelay.value.first {
section.messages.append(contentsOf: cellViewModels)
messagesRelay.accept([section])
}
else{
messagesRelay.accept([MessageSection(header: "model", messages: cellViewModels)])
}
}).disposed(by: rx.disposeBag)
//message
input.itemDelete.drive(onNext: {[weak self] indexPath in
if var section = messagesRelay.value.first {
if let realm = try? Realm() {
try? realm.write {
let message = self?.results?[indexPath.row]
message?.isDeleted = true
}
}
section.messages.remove(at: indexPath.row)
messagesRelay.accept([section])
}
}).disposed(by: rx.disposeBag)
// cell url
let urlTap = messagesRelay.flatMapLatest { (section) -> Observable<String> in
if let section = section.first {
let taps = section.messages.compactMap { (model) -> Observable<String> in
return model.urlTap.asObservable()
}
return Observable.merge(taps)
}
return .empty()
}
.compactMap { URL(string: $0) } //url
return Output(
messages: messagesRelay.asDriver(onErrorJustReturn: []),
settingClick: settingClick,
refreshAction: refreshAction.asDriver(),
alertMessage: alertMessage,
urlTap: urlTap.asDriver(onErrorDriveWith: .empty())
)
}
}

View File

@ -22,6 +22,7 @@ def pods
pod 'RxDataSources' pod 'RxDataSources'
pod 'NSObject+Rx' pod 'NSObject+Rx'
pod 'MJRefresh'
end end
target 'Bark' do target 'Bark' do

View File

@ -11,6 +11,7 @@ PODS:
- Material/Core (= 3.1.8) - Material/Core (= 3.1.8)
- Material/Core (3.1.8): - Material/Core (3.1.8):
- Motion (~> 3.1.1) - Motion (~> 3.1.1)
- MJRefresh (3.5.0)
- Motion (3.1.3): - Motion (3.1.3):
- Motion/Core (= 3.1.3) - Motion/Core (= 3.1.3)
- Motion/Core (3.1.3) - Motion/Core (3.1.3)
@ -51,6 +52,7 @@ DEPENDENCIES:
- IceCream - IceCream
- KVOController - KVOController
- Material - Material
- MJRefresh
- Moya/RxSwift - Moya/RxSwift
- "NSObject+Rx" - "NSObject+Rx"
- ObjectMapper - ObjectMapper
@ -64,24 +66,24 @@ DEPENDENCIES:
SPEC REPOS: SPEC REPOS:
https://github.com/CocoaPods/Specs.git: https://github.com/CocoaPods/Specs.git:
- Differentiator
- "NSObject+Rx"
- RxCocoa
- RxDataSources
- RxGesture
- RxRelay
trunk:
- Alamofire - Alamofire
- DeviceKit - DeviceKit
- Differentiator
- FDFullscreenPopGesture - FDFullscreenPopGesture
- IceCream - IceCream
- KVOController - KVOController
- Material - Material
- MJRefresh
- Motion - Motion
- Moya - Moya
- "NSObject+Rx"
- ObjectMapper - ObjectMapper
- Realm - Realm
- RealmSwift - RealmSwift
- RxCocoa
- RxDataSources
- RxGesture
- RxRelay
- RxSwift - RxSwift
- SnapKit - SnapKit
- SVProgressHUD - SVProgressHUD
@ -105,6 +107,7 @@ SPEC CHECKSUMS:
IceCream: 0447d87b55df85651dd60b15712cef64dbe1cb54 IceCream: 0447d87b55df85651dd60b15712cef64dbe1cb54
KVOController: d72ace34afea42468329623b3379ab3cd1d286b6 KVOController: d72ace34afea42468329623b3379ab3cd1d286b6
Material: a2a3f400a3b549d53ef89e56c58c4535b29db387 Material: a2a3f400a3b549d53ef89e56c58c4535b29db387
MJRefresh: 6afc955813966afb08305477dd7a0d9ad5e79a16
Motion: cf1e060e489f6661126374d5c60dbd2ed991605c Motion: cf1e060e489f6661126374d5c60dbd2ed991605c
Moya: 5b45dacb75adb009f97fde91c204c1e565d31916 Moya: 5b45dacb75adb009f97fde91c204c1e565d31916
"NSObject+Rx": fa6bbcc1ab1faa06b01466bc09b1e0692bbc5946 "NSObject+Rx": fa6bbcc1ab1faa06b01466bc09b1e0692bbc5946
@ -120,6 +123,6 @@ SPEC CHECKSUMS:
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6 SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7 SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7
PODFILE CHECKSUM: f0191b272c872b4d43da19a114ad4be556fb7eba PODFILE CHECKSUM: d8fe9b628db96415f1c950df034b6353a4921da5
COCOAPODS: 1.10.0 COCOAPODS: 1.10.0