123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- //
- // MessageSettingsViewModel.swift
- // Bark
- //
- // Created by huangfeng on 2020/11/20.
- // Copyright © 2020 Fin. All rights reserved.
- //
- import Foundation
- import Material
- import RealmSwift
- import RxCocoa
- import RxDataSources
- import RxSwift
- import SwiftyJSON
- class MessageSettingsViewModel: ViewModel, ViewModelType {
- struct Input {
- var itemSelected: Driver<MessageSettingItem>
- var deviceToken: Driver<String?>
- var backupAction: Driver<Void>
- var restoreAction: Driver<Data>
- var viewDidAppear: Observable<Void>
- var archiveSettingRelay: BehaviorRelay<Bool>
- }
- struct Output {
- var settings: Driver<[SectionModel<String, MessageSettingItem>]>
- var openUrl: Driver<URL>
- var copyDeviceToken: Driver<String>
- var exportData: Driver<Data>
- }
- func transform(input: Input) -> Output {
- let restoreSuccess = input
- .restoreAction
- .compactMap { data -> Void? in
- guard let json = try? JSON(data: data), let arr = json.array else {
- return nil
- }
- guard let realm = try? Realm() else {
- return nil
- }
- try? realm.write {
- for message in arr {
- guard let id = message["id"].string else {
- continue
- }
- guard let createDate = message["createDate"].int64 else {
- continue
- }
- let title = message["title"].string
- let body = message["body"].string
- let url = message["url"].string
- let group = message["group"].string
- let messageObject = Message()
- messageObject.id = id
- messageObject.title = title
- messageObject.body = body
- messageObject.url = url
- messageObject.group = group
- messageObject.createDate = Date(timeIntervalSince1970: TimeInterval(createDate))
- realm.add(messageObject, update: .modified)
- }
- }
- return ()
- }.asObservable().share()
- 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("historyMessage")))
- settings.append(.backup(viewModel: MutableTextCellViewModel(
- title: "\(NSLocalizedString("export"))/\(NSLocalizedString("import"))",
- text: Observable.merge([restoreSuccess, input.viewDidAppear])
- .map { _ in
- if let realm = try? Realm() {
- return realm.objects(Message.self)
- .filter("isDeleted != true")
- .count
- }
- return 0
- }
- .map { count in
- "\(count) \(NSLocalizedString("items"))"
- }
- .asDriver(onErrorDriveWith: .empty()))
- ))
- settings.append(.label(text: NSLocalizedString("exportOrImport")))
- settings.append(.archiveSetting(viewModel: ArchiveSettingCellViewModel(on: input.archiveSettingRelay)))
- settings.append(.label(text: NSLocalizedString("archiveNote")))
- settings.append(.label(text: NSLocalizedString("info")))
- settings.append(.deviceToken(
- viewModel: MutableTextCellViewModel(
- title: "Device Token",
- text: input
- .deviceToken
- .map {
- deviceToken in
- if let deviceToken = deviceToken {
- return "\(deviceToken.prefix(2))****\(deviceToken.suffix(4))"
- }
- return NSLocalizedString("unknown")
- })
- ))
- settings.append(.label(text: NSLocalizedString("deviceTokenInfo")))
- if let infoDict = Bundle.main.infoDictionary,
- let runId = infoDict["GitHub Run Id"] as? String
- {
- settings.append(.detail(
- title: "Github Run Id",
- text: "\(runId)",
- textColor: BKColor.grey.darken2,
- url: URL(string: "https://github.com/Finb/Bark/actions/runs/\(runId)")))
- settings.append(.label(text: NSLocalizedString("buildDesc")))
- }
- settings.append(.label(text: NSLocalizedString("other")))
- settings.append(.detail(
- title: NSLocalizedString("faq"),
- text: nil,
- textColor: nil,
- url: URL(string: NSLocalizedString("faqUrl"))))
- settings.append(.spacer(height: 0.5, color: BKColor.grey.lighten4))
- settings.append(.detail(
- title: NSLocalizedString("documentation"),
- text: nil,
- textColor: nil,
- url: URL(string: NSLocalizedString("docUrl"))))
- return settings
- }()
- let openUrl = input.itemSelected.compactMap { item -> URL? in
- if case let MessageSettingItem.detail(_, _, _, url) = item {
- return url
- }
- return nil
- }
- let deviceTokenValue: BehaviorRelay<String?> = BehaviorRelay(value: nil)
- input.deviceToken.drive(deviceTokenValue)
- .disposed(by: rx.disposeBag)
- let copyDeviceToken = input.itemSelected.compactMap { item -> String? in
- if case MessageSettingItem.deviceToken = item {
- return deviceTokenValue.value
- }
- return nil
- }
- // 导出数据
- let exportSuccess = input.backupAction
- .asObservable()
- .subscribe(on: ConcurrentDispatchQueueScheduler(qos: .userInitiated))
- .compactMap { _ in
- if let realm = try? Realm() {
- let messages = realm.objects(Message.self)
- .filter("isDeleted != true")
- .sorted(byKeyPath: "createDate", ascending: false)
- var arr = [[String: AnyObject]]()
- for message in messages {
- arr.append(message.toDictionary())
- }
- return try? JSON(arr).rawData(options: JSONSerialization.WritingOptions.prettyPrinted)
- }
- return nil
- }
- return Output(
- settings: Driver<[SectionModel<String, MessageSettingItem>]>
- .just([SectionModel(model: "model", items: settings)]),
- openUrl: openUrl,
- copyDeviceToken: copyDeviceToken,
- exportData: exportSuccess.asDriver(onErrorDriveWith: .empty()))
- }
- }
- enum MessageSettingItem {
- // 普通标题标签
- case label(text: String)
- // iCloud 状态
- case iCloudStatus
- // 默认保存
- case archiveSetting(viewModel: ArchiveSettingCellViewModel)
- // 带 详细按钮的 文本cell
- case detail(title: String?, text: String?, textColor: UIColor?, url: URL?)
- // 备份还原按钮
- case backup(viewModel: MutableTextCellViewModel)
- // deviceToken
- case deviceToken(viewModel: MutableTextCellViewModel)
- // 分隔线
- case spacer(height: CGFloat, color: UIColor?)
- }
|