From 27f04da06480d3f7cb9c73acb6a5f77fb5af4adb Mon Sep 17 00:00:00 2001 From: Fin Date: Wed, 27 May 2020 17:08:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8E=86=E5=8F=B2=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bark.xcodeproj/project.pbxproj | 20 ++- Bark/AppDelegate.swift | 4 +- Bark/Info.plist | 5 + Bark/en.lproj/Localizable.strings | 2 + Bark/zh-Hans.lproj/Localizable.strings | 2 + Controller/HomeViewController.swift | 6 +- Controller/MessageListViewController.swift | 93 +++++++++++--- Model/Client.swift | 6 +- Model/Date+Extension.swift | 40 ++++++ Model/Message.swift | 4 + .../NotificationService.swift | 11 +- View/MessageTableViewCell.swift | 119 ++++++++++++++++++ 12 files changed, 282 insertions(+), 30 deletions(-) create mode 100644 Model/Date+Extension.swift create mode 100644 View/MessageTableViewCell.swift diff --git a/Bark.xcodeproj/project.pbxproj b/Bark.xcodeproj/project.pbxproj index 29eef33..032afea 100644 --- a/Bark.xcodeproj/project.pbxproj +++ b/Bark.xcodeproj/project.pbxproj @@ -32,6 +32,8 @@ 0661A545204FDA4100965E4E /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0661A544204FDA4100965E4E /* HomeViewController.swift */; }; 0661A54A204FDA4100965E4E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0661A549204FDA4100965E4E /* Assets.xcassets */; }; 0661A54D204FDA4100965E4E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0661A54B204FDA4100965E4E /* LaunchScreen.storyboard */; }; + 0667D192247D162C005DE2ED /* MessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */; }; + 0667D194247D1BA0005DE2ED /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0667D193247D1BA0005DE2ED /* Date+Extension.swift */; }; 06802E5320ECC40C00767047 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0661A549204FDA4100965E4E /* Assets.xcassets */; }; 068F66B3247BD84C00DAD25A /* MessageListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 068F66B2247BD84C00DAD25A /* MessageListViewController.swift */; }; 06B1158D247BA6D5006D91FB /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06B1158C247BA6D5006D91FB /* CloudKit.framework */; }; @@ -102,6 +104,8 @@ 0661A549204FDA4100965E4E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 0661A54C204FDA4100965E4E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 0661A54E204FDA4100965E4E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageTableViewCell.swift; sourceTree = ""; }; + 0667D193247D1BA0005DE2ED /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; sourceTree = ""; }; 0683486A2050F1310024B6DA /* Bark.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Bark.entitlements; sourceTree = ""; }; 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; }; @@ -168,6 +172,7 @@ isa = PBXGroup; children = ( 0603706820E1F89500F4CA05 /* PreviewCardCell.swift */, + 0667D191247D162C005DE2ED /* MessageTableViewCell.swift */, ); path = View; sourceTree = ""; @@ -185,6 +190,7 @@ 0637FA7B20E0930E00E80174 /* BarkApi.swift */, 0637FA7D20E0969800E80174 /* Client.swift */, 06B1158E247BB1FB006D91FB /* Message.swift */, + 0667D193247D1BA0005DE2ED /* Date+Extension.swift */, ); path = Model; sourceTree = ""; @@ -500,7 +506,9 @@ 0637FA8A20E0D58800E80174 /* NewServerViewController.swift in Sources */, 0637FA8220E09C4B00E80174 /* BarkNavigationController.swift in Sources */, 0637FA7A20E092B300E80174 /* Observable+Extension.swift in Sources */, + 0667D194247D1BA0005DE2ED /* Date+Extension.swift in Sources */, 0604F7DF20620D4900B32F09 /* ServerManager.swift in Sources */, + 0667D192247D162C005DE2ED /* MessageTableViewCell.swift in Sources */, 0603706720E1E31600F4CA05 /* Defines.swift in Sources */, 0637FA7C20E0930E00E80174 /* BarkApi.swift in Sources */, 0637FA8020E0981E00E80174 /* BarkSettings.swift in Sources */, @@ -570,7 +578,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5U8LBRXG3A; INFOPLIST_FILE = NotificationContentExtension/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationContentExtension; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -587,7 +595,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5U8LBRXG3A; INFOPLIST_FILE = NotificationContentExtension/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationContentExtension; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -720,7 +728,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5U8LBRXG3A; INFOPLIST_FILE = Bark/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -739,7 +747,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5U8LBRXG3A; INFOPLIST_FILE = Bark/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -757,7 +765,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5U8LBRXG3A; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -778,7 +786,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5U8LBRXG3A; INFOPLIST_FILE = NotificationServiceExtension/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.3; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationServiceExtension; diff --git a/Bark/AppDelegate.swift b/Bark/AppDelegate.swift index 5c45709..c82fb0a 100644 --- a/Bark/AppDelegate.swift +++ b/Bark/AppDelegate.swift @@ -18,7 +18,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD var window: UIWindow? var syncEngine: SyncEngine? - internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) self.window?.backgroundColor = Color.grey.lighten5 @@ -47,7 +47,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD bar.tintColor = Color.darkText.primary let buttonItem = UIBarButtonItem.appearance(whenContainedInInstancesOf: [BarkNavigationController.self]) - buttonItem.setTitleTextAttributes([NSAttributedString.Key.font: RobotoFont.regular(with: 0)], for: .normal) + buttonItem.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.systemFont(ofSize: 0)], for: .normal) buttonItem.setBackButtonTitlePositionAdjustment(UIOffset(horizontal: -1000, vertical: 0), for: .default) let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark") diff --git a/Bark/Info.plist b/Bark/Info.plist index 1bd087b..28b4470 100644 --- a/Bark/Info.plist +++ b/Bark/Info.plist @@ -27,6 +27,11 @@ NSAllowsArbitraryLoads + UIBackgroundModes + + fetch + remote-notification + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/Bark/en.lproj/Localizable.strings b/Bark/en.lproj/Localizable.strings index 6564d80..3dd13ee 100644 --- a/Bark/en.lproj/Localizable.strings +++ b/Bark/en.lproj/Localizable.strings @@ -46,3 +46,5 @@ copyParameter = "If the URL has a copy parameter then the value of the copy \npa automaticallyCopyTitle = "Automatically copy push content"; automaticallyCopy = "Automatically copy push content \nwhen a push is received"; + +historyMessage = "History Message"; diff --git a/Bark/zh-Hans.lproj/Localizable.strings b/Bark/zh-Hans.lproj/Localizable.strings index a1846b7..1e478a7 100644 --- a/Bark/zh-Hans.lproj/Localizable.strings +++ b/Bark/zh-Hans.lproj/Localizable.strings @@ -46,3 +46,5 @@ copyParameter = "下拉推送、锁屏界面左滑查看推送时,可以选择 automaticallyCopyTitle = "自动复制推送内容"; automaticallyCopy = "携带automaticallyCopy参数时,将自动复制推送内容。\n携带copy参数时,将只复制copy参数的值"; + +historyMessage = "历史消息"; diff --git a/Controller/HomeViewController.swift b/Controller/HomeViewController.swift index a39493b..45e9fe8 100644 --- a/Controller/HomeViewController.swift +++ b/Controller/HomeViewController.swift @@ -78,6 +78,7 @@ class HomeViewController: BaseViewController { let messageBtn = IconButton(image: Icon.history, tintColor: .black) messageBtn.frame = CGRect(x: 0, y: 0, width: 40, height: 40) + messageBtn.addTarget(self, action: #selector(history), for: .touchUpInside) navigationItem.leftBarButtonItem = UIBarButtonItem(customView: messageBtn) self.view.addSubview(self.tableView) @@ -108,7 +109,6 @@ class HomeViewController: BaseViewController { } override func viewWillAppear(_ animated: Bool) { if let url = URL(string: ServerManager.shared.currentAddress) { -// navigationItem.titleLabel.text = url.host navigationItem.title = url.host refreshState() } @@ -181,7 +181,9 @@ extension HomeViewController { }) } - + @objc func history(){ + self.navigationController?.pushViewController(MessageListViewController(), animated: true) + } @objc func refreshState() { switch Client.shared.state { case .ok: diff --git a/Controller/MessageListViewController.swift b/Controller/MessageListViewController.swift index 89da3b6..716fc71 100644 --- a/Controller/MessageListViewController.swift +++ b/Controller/MessageListViewController.swift @@ -7,24 +7,89 @@ // import UIKit +import Material +import RealmSwift -class MessageListViewController: UIViewController { - +class MessageListViewController: BaseViewController { + let tableView: UITableView = { + let tableView = UITableView() + tableView.separatorStyle = .none + tableView.register(MessageTableViewCell.self, forCellReuseIdentifier: "cell") + return tableView + }() + var results:Results? + deinit { + print("message list deinit") + } override func viewDidLoad() { super.viewDidLoad() - - // Do any additional setup after loading the view. + self.title = NSLocalizedString("historyMessage") + + let settingButton = IconButton(image: Icon.settings, tintColor: .black) + settingButton.frame = CGRect(x: 0, y: 0, width: 40, height: 40) + settingButton.addTarget(self, action: #selector(settingClick), for: .touchUpInside) + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: settingButton) + + self.view.addSubview(tableView) + tableView.dataSource = self + tableView.delegate = self + tableView.snp.makeConstraints { (make) in + make.edges.equalToSuperview() + } + + + self.refresh() } - - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + @objc func settingClick (){ + + } + + func refresh() { + if let realm = try? Realm() { + results = realm.objects(Message.self).filter("isDeleted != true").sorted(byKeyPath: "createDate", ascending: false) + self.tableView.reloadData() + } + else { + } + + } +} + +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]) + return configuration } - */ - } diff --git a/Model/Client.swift b/Model/Client.swift index e491cd6..27bb955 100644 --- a/Model/Client.swift +++ b/Model/Client.swift @@ -70,10 +70,8 @@ class Client: NSObject { let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert , .sound , .badge], completionHandler: {(_ granted: Bool, _ error: Error?) -> Void in if granted { - DispatchQueue.global(qos: .default).async { - DispatchQueue.main.sync { - UIApplication.shared.registerForRemoteNotifications() - } + dispatch_sync_safely_main_queue { + UIApplication.shared.registerForRemoteNotifications() } } else{ diff --git a/Model/Date+Extension.swift b/Model/Date+Extension.swift new file mode 100644 index 0000000..9025eae --- /dev/null +++ b/Model/Date+Extension.swift @@ -0,0 +1,40 @@ +// +// Date+Extension.swift +// Bark +// +// Created by huangfeng on 2020/5/26. +// Copyright © 2020 Fin. All rights reserved. +// + +import UIKit + +extension Date { + func formatString(format:String) -> String { + let formatter = DateFormatter() + formatter.dateFormat = format + return formatter.string(for: self) ?? "" + } + + func agoFormatString() -> String { + + let clendar = NSCalendar(calendarIdentifier: .gregorian) + let cps = clendar?.components([ .hour, .minute, .second, .day, .month, .year], from: self, to: Date(), options: .wrapComponents) + + let year = cps!.year! + let month = cps!.month! + let day = cps!.day! + let hour = cps!.hour! + let minute = cps!.minute! + + if year > 0 || month > 0 || day > 0{ + return formatString(format: "yyyy-MM-dd HH:mm") + } + if hour > 0 { + return "\(hour)小时" + (minute > 0 ? "\(minute)分钟" : "") + "前" + } + if minute > 1 { + return "\(minute)分钟前" + } + return "刚刚" + } +} diff --git a/Model/Message.swift b/Model/Message.swift index 9f9f7c6..fb04436 100644 --- a/Model/Message.swift +++ b/Model/Message.swift @@ -13,6 +13,7 @@ class Message: Object { @objc dynamic var id = NSUUID().uuidString @objc dynamic var title:String? @objc dynamic var body:String? + @objc dynamic var url:String? @objc dynamic var createDate:Date? // 设置为 true 后,将被IceCream自动清理 @@ -21,6 +22,9 @@ class Message: Object { override class func primaryKey() -> String? { return "id" } + override class func indexedProperties() -> [String] { + return ["createDate"] + } } extension Message: CKRecordConvertible {} diff --git a/NotificationServiceExtension/NotificationService.swift b/NotificationServiceExtension/NotificationService.swift index 86727b6..8cac217 100644 --- a/NotificationServiceExtension/NotificationService.swift +++ b/NotificationServiceExtension/NotificationService.swift @@ -60,11 +60,18 @@ class NotificationService: UNNotificationServiceExtension { let defaults = UserDefaults.init(suiteName: "group.bark") isArchive = defaults?.bool(forKey: "isArchive") ?? false } + let alert = (userInfo["aps"] as? [String:Any])?["alert"] as? [String:Any] + let title = alert?["title"] as? String + let body = alert?["body"] as? String + + let url = userInfo["url"] as? String + if (isArchive == true){ try? realm?.write{ let message = Message() - message.title = userInfo["title"] as? String - message.body = userInfo["body"] as? String + message.title = title + message.body = body + message.url = url message.createDate = Date() realm?.add(message) } diff --git a/View/MessageTableViewCell.swift b/View/MessageTableViewCell.swift new file mode 100644 index 0000000..8bd18c4 --- /dev/null +++ b/View/MessageTableViewCell.swift @@ -0,0 +1,119 @@ +// +// MessageTableViewCell.swift +// Bark +// +// Created by huangfeng on 2020/5/26. +// Copyright © 2020 Fin. All rights reserved. +// + +import UIKit +import Material +class MessageTableViewCell: UITableViewCell { + + let titleLabel: UILabel = { + let label = UILabel() + label.font = RobotoFont.regular(with: 16) + label.textColor = Color.darkText.primary + label.numberOfLines = 0 + return label + }() + let bodyLabel: UILabel = { + let label = UILabel() + label.font = RobotoFont.regular(with: 14) + label.textColor = Color.darkText.secondary + label.numberOfLines = 0 + return label + }() + + let urlLabel: UILabel = { + let label = UILabel() + label.font = RobotoFont.regular(with: 14) + label.textColor = Color.blue.darken1 + label.numberOfLines = 0 + return label + }() + + let dateLabel: UILabel = { + let label = UILabel() + label.font = RobotoFont.medium(with: 11) + label.textColor = Color.darkText.others + return label + }() + let separatorLine:UIImageView = { + let imageView = UIImageView() + imageView.backgroundColor = Color.grey.lighten5 + return imageView + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + self.selectionStyle = .none + + self.backgroundColor = Color.white + + addSubview(titleLabel) + addSubview(bodyLabel) + addSubview(urlLabel) + addSubview(dateLabel) + addSubview(separatorLine) + } + func layoutView(){ + titleLabel.snp.remakeConstraints { (make) in + make.left.equalTo(12) + make.top.equalTo(12) + make.right.equalTo(-12) + } + if (message?.title?.count ?? 0) > 0 { + bodyLabel.snp.remakeConstraints { (make) in + make.left.right.equalTo(titleLabel) + make.top.equalTo(titleLabel.snp.bottom).offset(6) + } + } + else{ + bodyLabel.snp.remakeConstraints { (make) in + make.left.equalTo(12) + make.top.equalTo(12) + make.right.equalTo(-12) + } + } + + urlLabel.snp.makeConstraints { (make) in + make.left.equalTo(bodyLabel) + make.top.equalTo(bodyLabel.snp.bottom).offset(6) + } + if (message?.url?.count ?? 0) > 0{ + dateLabel.snp.remakeConstraints { (make) in + make.left.equalTo(urlLabel) + make.top.equalTo(urlLabel.snp.bottom).offset(6) + } + } + else{ + dateLabel.snp.remakeConstraints { (make) in + make.left.equalTo(bodyLabel) + make.top.equalTo(bodyLabel.snp.bottom).offset(6) + } + } + + + separatorLine.snp.remakeConstraints { (make) in + make.left.right.bottom.equalToSuperview() + make.top.equalTo(dateLabel.snp.bottom).offset(12) + make.height.equalTo(8) + } + + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + var message:Message? { + didSet{ + self.titleLabel.text = message?.title + self.bodyLabel.text = message?.body + self.urlLabel.text = message?.url + self.dateLabel.text = (message?.createDate ?? Date()).agoFormatString() + layoutView() + + } + } + +}