diff --git a/Bark/AppDelegate.swift b/Bark/AppDelegate.swift index 2d5b956..e2cb063 100644 --- a/Bark/AppDelegate.swift +++ b/Bark/AppDelegate.swift @@ -17,8 +17,37 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD var window: UIWindow? var syncEngine: SyncEngine? + func setupRealm() { + let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark") + let fileUrl = groupUrl?.appendingPathComponent("bark.realm") + let config = Realm.Configuration( + fileURL: fileUrl, + schemaVersion: 12, + migrationBlock: { migration, oldSchemaVersion in + // We haven’t migrated anything yet, so oldSchemaVersion == 0 + if (oldSchemaVersion < 1) { + // Nothing to do! + // Realm will automatically detect new properties and removed properties + // And will update the schema on disk automatically + } + }) + // Tell Realm to use this new configuration object for the default Realm + Realm.Configuration.defaultConfiguration = config + //iCloud 同步 + syncEngine = SyncEngine(objects: [ + SyncObject(type: Message.self) + ], databaseScope: .private) + + #if DEBUG + let realm = try? Realm() + print("message count: \(realm?.objects(Message.self).count ?? 0)") + #endif + } + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + //必须在应用一开始就配置,否则应用可能提前在配置之前试用了 Realm() ,则会创建两个独立数据库。 + setupRealm() self.window = UIWindow(frame: UIScreen.main.bounds) if #available(iOS 13.0, *) { @@ -65,33 +94,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD bar.backIndicatorImage = UIImage(named: "back") bar.backIndicatorTransitionMaskImage = UIImage(named: "back") bar.tintColor = Color.darkText.primary - - - let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark") - let fileUrl = groupUrl?.appendingPathComponent("bark.realm") - let config = Realm.Configuration( - fileURL: fileUrl, - schemaVersion: 12, - migrationBlock: { migration, oldSchemaVersion in - // We haven’t migrated anything yet, so oldSchemaVersion == 0 - if (oldSchemaVersion < 1) { - // Nothing to do! - // Realm will automatically detect new properties and removed properties - // And will update the schema on disk automatically - } - }) - // Tell Realm to use this new configuration object for the default Realm - Realm.Configuration.defaultConfiguration = config - //iCloud 同步 - syncEngine = SyncEngine(objects: [ - SyncObject(type: Message.self) - ], databaseScope: .private) - - - let realm = try? Realm() - print("message count: \(realm?.objects(Message.self).count ?? 0)") - return true } diff --git a/Bark/en.lproj/Localizable.strings b/Bark/en.lproj/Localizable.strings index 6d58f8e..3a04b68 100644 --- a/Bark/en.lproj/Localizable.strings +++ b/Bark/en.lproj/Localizable.strings @@ -70,3 +70,8 @@ setSounds = "You can set different sounds for push notifications"; viewAllSounds = "View all sounds"; service = "Service"; + +lastHour = "The last hour"; +today = "Today"; +todayAndYesterday = "Today and yesterday"; +allTime = "All time"; diff --git a/Bark/zh-Hans.lproj/Localizable.strings b/Bark/zh-Hans.lproj/Localizable.strings index 475d6c9..d484955 100644 --- a/Bark/zh-Hans.lproj/Localizable.strings +++ b/Bark/zh-Hans.lproj/Localizable.strings @@ -70,3 +70,9 @@ setSounds = "可以为推送设置不同的铃声"; viewAllSounds = "查看所有铃声"; service = "服务器"; + + +lastHour = "过去一小时"; +today = "今天"; +todayAndYesterday = "昨天和今天"; +allTime = "所有时间"; diff --git a/Common/Date+Extension.swift b/Common/Date+Extension.swift index 26f026a..018a517 100644 --- a/Common/Date+Extension.swift +++ b/Common/Date+Extension.swift @@ -41,3 +41,24 @@ extension Date { return "刚刚" } } + +extension Date { + static var yesterday: Date { return Date().dayBefore } + static var tomorrow: Date { return Date().dayAfter } + static var lastHour: Date { return Calendar.current.date(byAdding: .hour, value: -1, to: Date())! } + var dayBefore: Date { + return Calendar.current.date(byAdding: .day, value: -1, to: noon)! + } + var dayAfter: Date { + return Calendar.current.date(byAdding: .day, value: 1, to: noon)! + } + var noon: Date { + return Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: self)! + } + var month: Int { + return Calendar.current.component(.month, from: self) + } + var isLastDayOfMonth: Bool { + return dayAfter.month != month + } +} diff --git a/Controller/MessageListViewController.swift b/Controller/MessageListViewController.swift index d445a35..c1dda5d 100644 --- a/Controller/MessageListViewController.swift +++ b/Controller/MessageListViewController.swift @@ -13,7 +13,21 @@ import RxCocoa import RxDataSources import MJRefresh +enum MessageDeleteType { + case lastHour + case today + case todayAndYesterday + case allTime +} + class MessageListViewController: BaseViewController { + let deleteButton: BKButton = { + let btn = BKButton() + btn.setImage(UIImage(named: "baseline_delete_outline_black_24pt"), for: .normal) + btn.frame = CGRect(x: 0, y: 0, width: 40, height: 40) + return btn + }() + let tableView: UITableView = { let tableView = UITableView() tableView.separatorStyle = .none @@ -29,6 +43,8 @@ class MessageListViewController: BaseViewController { override func makeUI() { self.title = NSLocalizedString("historyMessage") + navigationItem.setRightBarButtonItem(item: UIBarButtonItem(customView: deleteButton)) + self.view.addSubview(tableView) tableView.snp.makeConstraints { (make) in make.edges.equalToSuperview() @@ -42,11 +58,37 @@ class MessageListViewController: BaseViewController { return } - let output = viewModel.transform(input: MessageListViewModel.Input( - loadMore: tableView.mj_footer!.rx.refresh.asDriver(), - itemDelete: tableView.rx.itemDeleted.asDriver(), - itemSelected: tableView.rx.modelSelected(MessageTableViewCellViewModel.self).asDriver() - )) + let batchDelete = deleteButton.rx + .tap + .flatMapLatest { Void -> PublishRelay in + let relay = PublishRelay() + + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + alertController.addAction(UIAlertAction(title: NSLocalizedString("lastHour"), style: .default, handler: { _ in + relay.accept(.lastHour) + })) + alertController.addAction(UIAlertAction(title: NSLocalizedString("today"), style: .default, handler: { _ in + relay.accept(.today) + })) + alertController.addAction(UIAlertAction(title: NSLocalizedString("todayAndYesterday"), style: .default, handler: { _ in + relay.accept(.todayAndYesterday) + })) + alertController.addAction(UIAlertAction(title: NSLocalizedString("allTime"), style: .default, handler: { _ in + relay.accept(.allTime) + })) + alertController.addAction(UIAlertAction(title: NSLocalizedString("cancel"), style: .cancel, handler: nil)) + self.navigationController?.present(alertController, animated: true, completion: nil) + + return relay + } + + let output = viewModel.transform( + input: MessageListViewModel.Input( + loadMore: tableView.mj_footer!.rx.refresh.asDriver(), + itemDelete: tableView.rx.itemDeleted.asDriver(), + itemSelected: tableView.rx.modelSelected(MessageTableViewCellViewModel.self).asDriver(), + delete:batchDelete.asDriver(onErrorDriveWith: .empty()) + )) //tableView 刷新状态 output.refreshAction diff --git a/Controller/MessageListViewModel.swift b/Controller/MessageListViewModel.swift index 6bf676c..cfdedd7 100644 --- a/Controller/MessageListViewModel.swift +++ b/Controller/MessageListViewModel.swift @@ -17,6 +17,7 @@ class MessageListViewModel: ViewModel,ViewModelType { var loadMore: Driver var itemDelete: Driver var itemSelected: Driver + var delete: Driver } struct Output { @@ -124,7 +125,40 @@ class MessageListViewModel: ViewModel,ViewModelType { } .compactMap { URL(string: $0) } //只处理正确的url + //批量删除 + input.delete.drive(onNext: {[weak self] type in + guard let strongSelf = self else { return } + + var date = Date() + switch type { + case .allTime: + date = Date(timeIntervalSince1970: 0) + case .todayAndYesterday: + date = Date.yesterday + case .today: + date = Date().noon + case .lastHour: + date = Date.lastHour + } + + if let realm = try? Realm() { + let messages = realm.objects(Message.self).filter("createDate >= %@", date) + try? realm.write{ + for msg in messages{ + msg.isDeleted = true + } + } + } + + strongSelf.page = 0 + let messages = strongSelf.getNextPage() + let cellViewModels = messages.map({ (message) -> MessageTableViewCellViewModel in + return MessageTableViewCellViewModel(message: message) + }) + messagesRelay.accept([MessageSection(header: "model", messages: cellViewModels)]) + + }).disposed(by: rx.disposeBag) return Output( messages: messagesRelay.asDriver(onErrorJustReturn: []),