mirror of
https://github.com/Finb/Bark.git
synced 2025-12-08 21:36:01 +00:00
重构 MessageSettings
This commit is contained in:
parent
4cb6454087
commit
aed16c5a1a
@ -83,6 +83,10 @@
|
||||
06BBB88725650C6C0076F63E /* ArchiveSettingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5953224811505006B98F3 /* ArchiveSettingManager.swift */; };
|
||||
06BBB89125650CCF0076F63E /* ArchiveSettingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5953224811505006B98F3 /* ArchiveSettingManager.swift */; };
|
||||
06BBB896256518760076F63E /* NewServerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB895256518760076F63E /* NewServerViewModel.swift */; };
|
||||
06BBB8B72567AC140076F63E /* MessageSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB8B62567AC140076F63E /* MessageSettingsViewModel.swift */; };
|
||||
06BBB8BC2567B3AD0076F63E /* ArchiveSettingCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB8BB2567B3AD0076F63E /* ArchiveSettingCellViewModel.swift */; };
|
||||
06BBB8C12567B3EF0076F63E /* BaseTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */; };
|
||||
06BBB8C92567B6730076F63E /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06BBB8C82567B6730076F63E /* Operators.swift */; };
|
||||
06C5952D2480E3F8006B98F3 /* LabelCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5952C2480E3F8006B98F3 /* LabelCell.swift */; };
|
||||
06C5952F248107F5006B98F3 /* iCloudStatusCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */; };
|
||||
06C5953124811392006B98F3 /* ArchiveSettingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06C5953024811392006B98F3 /* ArchiveSettingCell.swift */; };
|
||||
@ -203,6 +207,10 @@
|
||||
06B1158E247BB1FB006D91FB /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
|
||||
06B11590247BBC15006D91FB /* NotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationServiceExtension.entitlements; sourceTree = "<group>"; };
|
||||
06BBB895256518760076F63E /* NewServerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewServerViewModel.swift; sourceTree = "<group>"; };
|
||||
06BBB8B62567AC140076F63E /* MessageSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSettingsViewModel.swift; sourceTree = "<group>"; };
|
||||
06BBB8BB2567B3AD0076F63E /* ArchiveSettingCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveSettingCellViewModel.swift; sourceTree = "<group>"; };
|
||||
06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTableViewCell.swift; sourceTree = "<group>"; };
|
||||
06BBB8C82567B6730076F63E /* Operators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
|
||||
06C5952C2480E3F8006B98F3 /* LabelCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelCell.swift; sourceTree = "<group>"; };
|
||||
06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iCloudStatusCell.swift; sourceTree = "<group>"; };
|
||||
06C5953024811392006B98F3 /* ArchiveSettingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveSettingCell.swift; sourceTree = "<group>"; };
|
||||
@ -262,6 +270,7 @@
|
||||
0603706C20E23EC000F4CA05 /* BarkSFSafariViewController.swift */,
|
||||
068F66B2247BD84C00DAD25A /* MessageListViewController.swift */,
|
||||
06885EB5247FB9880004A303 /* MessageSettingsViewController.swift */,
|
||||
06BBB8B62567AC140076F63E /* MessageSettingsViewModel.swift */,
|
||||
060481ED250F404500BC9799 /* SoundsViewController.swift */,
|
||||
065BE43F2563D649002A8CA4 /* SoundsViewModel.swift */,
|
||||
);
|
||||
@ -271,11 +280,13 @@
|
||||
0604F7DC20620D3400B32F09 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
06BBB8C02567B3EF0076F63E /* BaseTableViewCell.swift */,
|
||||
0603706820E1F89500F4CA05 /* PreviewCardCell.swift */,
|
||||
0667D191247D162C005DE2ED /* MessageTableViewCell.swift */,
|
||||
06C5952C2480E3F8006B98F3 /* LabelCell.swift */,
|
||||
06C5952E248107F5006B98F3 /* iCloudStatusCell.swift */,
|
||||
06C5953024811392006B98F3 /* ArchiveSettingCell.swift */,
|
||||
06BBB8BB2567B3AD0076F63E /* ArchiveSettingCellViewModel.swift */,
|
||||
06C595352481160F006B98F3 /* BKLabel.swift */,
|
||||
060481EF250F51CA00BC9799 /* SoundCell.swift */,
|
||||
065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */,
|
||||
@ -355,6 +366,7 @@
|
||||
0637FA7D20E0969800E80174 /* Client.swift */,
|
||||
0667D193247D1BA0005DE2ED /* Date+Extension.swift */,
|
||||
06C5953224811505006B98F3 /* ArchiveSettingManager.swift */,
|
||||
06BBB8C82567B6730076F63E /* Operators.swift */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
@ -693,6 +705,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
06BBB896256518760076F63E /* NewServerViewModel.swift in Sources */,
|
||||
06BBB8C92567B6730076F63E /* Operators.swift in Sources */,
|
||||
0603706920E1F89500F4CA05 /* PreviewCardCell.swift in Sources */,
|
||||
0637FA8C20E0D7A700E80174 /* BaseViewController.swift in Sources */,
|
||||
062B98C8251B27AE004562E7 /* UINavigationItem+Extension.swift in Sources */,
|
||||
@ -722,11 +735,14 @@
|
||||
06885EB6247FB9880004A303 /* MessageSettingsViewController.swift in Sources */,
|
||||
06C5952D2480E3F8006B98F3 /* LabelCell.swift in Sources */,
|
||||
0637FA7C20E0930E00E80174 /* BarkApi.swift in Sources */,
|
||||
06BBB8BC2567B3AD0076F63E /* ArchiveSettingCellViewModel.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 */,
|
||||
06BBB8B72567AC140076F63E /* MessageSettingsViewModel.swift in Sources */,
|
||||
06BBB8C12567B3EF0076F63E /* BaseTableViewCell.swift in Sources */,
|
||||
0661A543204FDA4100965E4E /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
||||
93
Common/Operators.swift
Normal file
93
Common/Operators.swift
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// Operators.swift
|
||||
// RxExample
|
||||
//
|
||||
// Created by Krunoslav Zaher on 12/6/15.
|
||||
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
|
||||
//
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
#elseif os(macOS)
|
||||
import AppKit
|
||||
#endif
|
||||
|
||||
// Two way binding operator between control property and relay, that's all it takes.
|
||||
infix operator <-> : DefaultPrecedence
|
||||
|
||||
#if os(iOS)
|
||||
func nonMarkedText(_ textInput: UITextInput) -> String? {
|
||||
let start = textInput.beginningOfDocument
|
||||
let end = textInput.endOfDocument
|
||||
|
||||
guard let rangeAll = textInput.textRange(from: start, to: end),
|
||||
let text = textInput.text(in: rangeAll) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let markedTextRange = textInput.markedTextRange else {
|
||||
return text
|
||||
}
|
||||
|
||||
guard let startRange = textInput.textRange(from: start, to: markedTextRange.start),
|
||||
let endRange = textInput.textRange(from: markedTextRange.end, to: end) else {
|
||||
return text
|
||||
}
|
||||
|
||||
return (textInput.text(in: startRange) ?? "") + (textInput.text(in: endRange) ?? "")
|
||||
}
|
||||
|
||||
func <-> <Base>(textInput: TextInput<Base>, relay: BehaviorRelay<String>) -> Disposable {
|
||||
let bindToUIDisposable = relay.bind(to: textInput.text)
|
||||
|
||||
let bindToRelay = textInput.text
|
||||
.subscribe(onNext: { [weak base = textInput.base] n in
|
||||
guard let base = base else {
|
||||
return
|
||||
}
|
||||
|
||||
let nonMarkedTextValue = nonMarkedText(base)
|
||||
|
||||
/**
|
||||
In some cases `textInput.textRangeFromPosition(start, toPosition: end)` will return nil even though the underlying
|
||||
value is not nil. This appears to be an Apple bug. If it's not, and we are doing something wrong, please let us know.
|
||||
The can be reproed easily if replace bottom code with
|
||||
|
||||
if nonMarkedTextValue != relay.value {
|
||||
relay.accept(nonMarkedTextValue ?? "")
|
||||
}
|
||||
and you hit "Done" button on keyboard.
|
||||
*/
|
||||
if let nonMarkedTextValue = nonMarkedTextValue, nonMarkedTextValue != relay.value {
|
||||
relay.accept(nonMarkedTextValue)
|
||||
}
|
||||
}, onCompleted: {
|
||||
bindToUIDisposable.dispose()
|
||||
})
|
||||
|
||||
return Disposables.create(bindToUIDisposable, bindToRelay)
|
||||
}
|
||||
#endif
|
||||
|
||||
func <-> <T>(property: ControlProperty<T>, relay: BehaviorRelay<T>) -> Disposable {
|
||||
if T.self == String.self {
|
||||
#if DEBUG && !os(macOS)
|
||||
fatalError("It is ok to delete this message, but this is here to warn that you are maybe trying to bind to some `rx.text` property directly to relay.\n" +
|
||||
"That will usually work ok, but for some languages that use IME, that simplistic method could cause unexpected issues because it will return intermediate results while text is being inputed.\n" +
|
||||
"REMEDY: Just use `textField <-> relay` instead of `textField.rx.text <-> relay`.\n" +
|
||||
"Find out more here: https://github.com/ReactiveX/RxSwift/issues/649\n"
|
||||
)
|
||||
#endif
|
||||
}
|
||||
|
||||
let bindToUIDisposable = relay.bind(to: property)
|
||||
let bindToRelay = property
|
||||
.subscribe(onNext: { n in
|
||||
relay.accept(n)
|
||||
}, onCompleted: {
|
||||
bindToUIDisposable.dispose()
|
||||
})
|
||||
|
||||
return Disposables.create(bindToUIDisposable, bindToRelay)
|
||||
}
|
||||
@ -44,7 +44,7 @@ class MessageListViewController: UIViewController {
|
||||
}
|
||||
|
||||
@objc func settingClick (){
|
||||
self.navigationController?.pushViewController(MessageSettingsViewController(), animated: true)
|
||||
self.navigationController?.pushViewController(MessageSettingsViewController(viewModel: MessageSettingsViewModel()), animated: true)
|
||||
}
|
||||
|
||||
func refresh() {
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
import UIKit
|
||||
import Material
|
||||
class MessageSettingsViewController: UIViewController {
|
||||
import RxDataSources
|
||||
class MessageSettingsViewController: BaseViewController {
|
||||
let tableView: UITableView = {
|
||||
let tableView = UITableView()
|
||||
tableView.separatorStyle = .none
|
||||
@ -19,54 +20,44 @@ class MessageSettingsViewController: UIViewController {
|
||||
|
||||
return tableView
|
||||
}()
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
override func makeUI() {
|
||||
self.title = NSLocalizedString("settings")
|
||||
|
||||
self.view.addSubview(tableView)
|
||||
tableView.dataSource = self
|
||||
tableView.delegate = self
|
||||
tableView.snp.makeConstraints { (make) in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension MessageSettingsViewController: UITableViewDelegate,UITableViewDataSource {
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 6
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
switch indexPath.row {
|
||||
case 0:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(LabelCell.self)") as! LabelCell
|
||||
cell.textLabel?.text = "iCloud"
|
||||
return cell
|
||||
case 1:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(iCloudStatusCell.self)") as! iCloudStatusCell
|
||||
return cell
|
||||
case 2:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(LabelCell.self)") as! LabelCell
|
||||
cell.textLabel?.text = NSLocalizedString("iCloudSync")
|
||||
return cell
|
||||
case 3:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(LabelCell.self)") as! LabelCell
|
||||
cell.textLabel?.text = NSLocalizedString("defaultArchiveSettings")
|
||||
return cell
|
||||
case 4:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(ArchiveSettingCell.self)") as! ArchiveSettingCell
|
||||
return cell
|
||||
case 5:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "\(LabelCell.self)") as! LabelCell
|
||||
cell.textLabel?.text = NSLocalizedString("archiveNote")
|
||||
return cell
|
||||
|
||||
default:
|
||||
return UITableViewCell()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
guard let viewModel = self.viewModel as? MessageSettingsViewModel else {
|
||||
return
|
||||
}
|
||||
let output = viewModel.transform(input: MessageSettingsViewModel.Input())
|
||||
|
||||
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, MessageSettingItem>> { (source, tableView, indexPath, item) -> UITableViewCell in
|
||||
switch item {
|
||||
case .label(let text):
|
||||
if let cell = tableView.dequeueReusableCell(withIdentifier: "\(LabelCell.self)") as? LabelCell {
|
||||
cell.textLabel?.text = text
|
||||
return cell
|
||||
}
|
||||
case .iCloudStatus:
|
||||
if let cell = tableView.dequeueReusableCell(withIdentifier: "\(iCloudStatusCell.self)") {
|
||||
return cell
|
||||
}
|
||||
case .archiveSetting(let viewModel):
|
||||
if let cell = tableView.dequeueReusableCell(withIdentifier: "\(ArchiveSettingCell.self)") as? ArchiveSettingCell {
|
||||
cell.bindViewModel(model: viewModel)
|
||||
return cell
|
||||
}
|
||||
}
|
||||
return UITableViewCell()
|
||||
}
|
||||
|
||||
output.settings
|
||||
.drive(tableView.rx.items(dataSource: dataSource))
|
||||
.disposed(by: rx.disposeBag)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
56
Controller/MessageSettingsViewModel.swift
Normal file
56
Controller/MessageSettingsViewModel.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// MessageSettingsViewModel.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/20.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class MessageSettingsViewModel: ViewModel, ViewModelType {
|
||||
struct Input {
|
||||
|
||||
}
|
||||
struct Output {
|
||||
var settings:Driver<[SectionModel<String, MessageSettingItem>]>
|
||||
}
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
let settings:[MessageSettingItem] = {
|
||||
var settings = [MessageSettingItem]()
|
||||
settings.append(.label(text: "iCloud"))
|
||||
settings.append(.iCloudStatus)
|
||||
settings.append(.label(text: NSLocalizedString("iCloudSync")))
|
||||
settings.append(.label(text: NSLocalizedString("defaultArchiveSettings")))
|
||||
settings.append(.archiveSetting(viewModel: ArchiveSettingCellViewModel(on: ArchiveSettingManager.shared.isArchive)))
|
||||
settings.append(.label(text: NSLocalizedString("archiveNote")))
|
||||
return settings
|
||||
}()
|
||||
|
||||
settings.compactMap { (item) -> ArchiveSettingCellViewModel? in
|
||||
if case let MessageSettingItem.archiveSetting(viewModel) = item {
|
||||
return viewModel
|
||||
}
|
||||
return nil
|
||||
}
|
||||
.first?
|
||||
.on
|
||||
.subscribe(onNext: { (on) in
|
||||
ArchiveSettingManager.shared.isArchive = on
|
||||
}).disposed(by: rx.disposeBag)
|
||||
|
||||
return Output(settings: Driver<[SectionModel<String, MessageSettingItem>]>
|
||||
.just([SectionModel(model: "model", items: settings)]))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum MessageSettingItem {
|
||||
case label(text:String)
|
||||
case iCloudStatus
|
||||
case archiveSetting(viewModel:ArchiveSettingCellViewModel)
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
class ArchiveSettingCell: UITableViewCell {
|
||||
class ArchiveSettingCell: BaseTableViewCell {
|
||||
let switchButton: UISwitch = {
|
||||
let btn = UISwitch()
|
||||
return btn
|
||||
@ -24,17 +24,18 @@ class ArchiveSettingCell: UITableViewCell {
|
||||
make.right.equalToSuperview().offset(-16)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
|
||||
switchButton.isOn = ArchiveSettingManager.shared.isArchive
|
||||
switchButton.addTarget(self, action: #selector(switchToggle(sender:)), for: .valueChanged)
|
||||
|
||||
}
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc func switchToggle(sender:UISwitch) {
|
||||
ArchiveSettingManager.shared.isArchive = sender.isOn
|
||||
override func bindViewModel(model: ViewModel) {
|
||||
super.bindViewModel(model: model)
|
||||
guard let viewModel = model as? ArchiveSettingCellViewModel else {
|
||||
return
|
||||
}
|
||||
(self.switchButton.rx.isOn <-> viewModel.on)
|
||||
.disposed(by: rx.reuseBag)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
17
View/ArchiveSettingCellViewModel.swift
Normal file
17
View/ArchiveSettingCellViewModel.swift
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// ArchiveSettingCellViewModel.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/20.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxCocoa
|
||||
class ArchiveSettingCellViewModel: ViewModel {
|
||||
var on: BehaviorRelay<Bool>
|
||||
init(on:Bool) {
|
||||
self.on = BehaviorRelay<Bool>(value: on)
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
16
View/BaseTableViewCell.swift
Normal file
16
View/BaseTableViewCell.swift
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
// BaseTableViewCell.swift
|
||||
// Bark
|
||||
//
|
||||
// Created by huangfeng on 2020/11/20.
|
||||
// Copyright © 2020 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class BaseTableViewCell: UITableViewCell {
|
||||
var viewModel:ViewModel?
|
||||
func bindViewModel(model:ViewModel){
|
||||
self.viewModel = model
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
import Material
|
||||
import AVKit
|
||||
|
||||
class SoundCell: UITableViewCell {
|
||||
class SoundCell: BaseTableViewCell {
|
||||
let copyButton = IconButton(image: UIImage(named: "baseline_file_copy_white_24pt"), tintColor: Color.grey.base)
|
||||
let nameLabel:UILabel = {
|
||||
let label = UILabel()
|
||||
@ -50,12 +50,11 @@ class SoundCell: UITableViewCell {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
var viewModel:ViewModel?
|
||||
func bindViewModel(model:ViewModel){
|
||||
override func bindViewModel(model:ViewModel){
|
||||
super.bindViewModel(model: model)
|
||||
guard let viewModel = model as? SoundCellViewModel else {
|
||||
return
|
||||
}
|
||||
self.viewModel = model
|
||||
|
||||
viewModel.name
|
||||
.bind(to: nameLabel.rx.text)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user