添加历史消息列表

This commit is contained in:
Fin 2020-05-27 17:08:59 +08:00
parent b202e1e240
commit 27f04da064
12 changed files with 282 additions and 30 deletions

View File

@ -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 = "<group>"; };
0661A54C204FDA4100965E4E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; 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>"; };
0667D193247D1BA0005DE2ED /* Date+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+Extension.swift"; 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; };
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 = "<group>";
@ -185,6 +190,7 @@
0637FA7B20E0930E00E80174 /* BarkApi.swift */,
0637FA7D20E0969800E80174 /* Client.swift */,
06B1158E247BB1FB006D91FB /* Message.swift */,
0667D193247D1BA0005DE2ED /* Date+Extension.swift */,
);
path = Model;
sourceTree = "<group>";
@ -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;

View File

@ -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")

View File

@ -27,6 +27,11 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>

View File

@ -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";

View File

@ -46,3 +46,5 @@ copyParameter = "下拉推送、锁屏界面左滑查看推送时,可以选择
automaticallyCopyTitle = "自动复制推送内容";
automaticallyCopy = "携带automaticallyCopy参数时将自动复制推送内容。\n携带copy参数时将只复制copy参数的值";
historyMessage = "历史消息";

View File

@ -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:

View File

@ -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<Message>?
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
}
*/
}

View File

@ -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{

View File

@ -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 "刚刚"
}
}

View File

@ -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 {}

View File

@ -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)
}

View File

@ -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()
}
}
}