blob: a004cfec0ee0c2bee552414608f884812c8311bd [file] [log] [blame]
//
// MessageViewController.swift
// ActivityFeed
//
// Created by Robert Walsh on 1/21/16.
//
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. The ASF licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. For additional information regarding
* copyright in this work, please see the NOTICE file in the top level
* directory of this distribution.
*
*/
import Foundation
import UsergridSDK
import SlackTextViewController
import WatchConnectivity
class MessageViewController : SLKTextViewController {
static let MESSAGE_CELL_IDENTIFIER = "MessengerCell"
private var messageEntities: [ActivityEntity] = []
init() {
super.init(tableViewStyle:.plain)
commonInit()
}
required init(coder decoder: NSCoder) {
super.init(coder: decoder)
commonInit()
}
override static func tableViewStyle(for decoder: NSCoder) -> UITableViewStyle {
return .plain
}
override func viewWillAppear(_ animated: Bool) {
self.reloadMessages()
if let username = Usergrid.currentUser?.name {
self.navigationItem.title = "\(username)'s Feed"
}
super.viewWillAppear(animated)
}
func commonInit() {
self.bounces = true
self.shakeToClearEnabled = true
self.isKeyboardPanningEnabled = true
self.shouldScrollToBottomAfterKeyboardShows = true
self.isInverted = true
self.registerClass(forTextView:MessageTextView.classForCoder())
self.activateWCSession()
}
func reloadMessages() {
UsergridManager.getFeedMessages { (response) -> Void in
self.messageEntities = response.entities as? [ActivityEntity] ?? []
self.tableView!.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.rightButton.setTitle("Send", for: [])
self.textInputbar.autoHideRightButton = true
self.textInputbar.maxCharCount = 256
self.textInputbar.editorTitle.textColor = UIColor.darkGray
self.tableView!.separatorStyle = .none
self.tableView!.register(MessageTableViewCell.self, forCellReuseIdentifier:MessageViewController.MESSAGE_CELL_IDENTIFIER)
}
override func didPressRightButton(_ sender: Any!) {
self.textView.refreshFirstResponder()
UsergridManager.postFeedMessage(self.textView.text) { (response) -> Void in
if let messageEntity = response.entity as? ActivityEntity {
let indexPath = NSIndexPath.init(row: 0, section: 0)
let rowAnimation: UITableViewRowAnimation = self.isInverted ? .bottom : .top
let scrollPosition: UITableViewScrollPosition = self.isInverted ? .bottom : .top
self.tableView!.beginUpdates()
self.messageEntities.insert(messageEntity, at: 0)
self.tableView!.insertRows(at: [indexPath as IndexPath], with: rowAnimation)
self.tableView!.endUpdates()
self.tableView!.scrollToRow(at: indexPath as IndexPath, at: scrollPosition, animated: true)
self.tableView!.reloadRows(at: [indexPath as IndexPath], with: .automatic)
self.sendEntitiesToWatch(self.messageEntities)
}
}
super.didPressRightButton(sender)
}
override func keyForTextCaching() -> String? {
return Bundle.main.bundleIdentifier
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.messageEntities.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return self.messageCellForRowAtIndexPath(indexPath)
}
@IBAction func unwindToChat(_ segue: UIStoryboardSegue) {
}
func populateCell(_ cell:MessageTableViewCell,feedEntity:ActivityEntity) {
cell.titleLabel.text = feedEntity.displayName
cell.bodyLabel.text = feedEntity.content
cell.thumbnailView.image = nil
if let imageURLString = feedEntity.imageURL, let imageURL = URL(string: imageURLString) {
URLSession.shared.dataTask(with: imageURL) { (data, response, error) in
if let imageData = data, let image = UIImage(data: imageData) {
DispatchQueue.main.async(execute: { () -> Void in
cell.thumbnailView.image = image
})
}
}.resume()
}
}
func messageCellForRowAtIndexPath(_ indexPath:IndexPath) -> MessageTableViewCell {
let cell = self.tableView!.dequeueReusableCell(withIdentifier: MessageViewController.MESSAGE_CELL_IDENTIFIER) as! MessageTableViewCell
self.populateCell(cell, feedEntity: self.messageEntities[indexPath.row])
cell.indexPath = indexPath
cell.transform = self.tableView!.transform
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let feedEntity = messageEntities[(indexPath as NSIndexPath).row]
guard let messageText = feedEntity.content, !messageText.isEmpty
else {
return 0
}
let messageUsername : NSString = (feedEntity.displayName ?? "") as NSString
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byWordWrapping
paragraphStyle.alignment = .left
let pointSize = MessageTableViewCell.defaultFontSize
let attributes = [NSFontAttributeName:UIFont.boldSystemFont(ofSize: pointSize),NSParagraphStyleAttributeName:paragraphStyle]
let width: CGFloat = self.tableView!.frame.width - MessageTableViewCell.kMessageTableViewCellAvatarHeight - 25
let titleBounds = messageUsername.boundingRect(with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
let bodyBounds = messageText.boundingRect(with: CGSize(width: width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
var height = titleBounds.height + bodyBounds.height + 40
if height < MessageTableViewCell.kMessageTableViewCellMinimumHeight {
height = MessageTableViewCell.kMessageTableViewCellMinimumHeight
}
return height
}
}
extension MessageViewController : WCSessionDelegate {
func activateWCSession() {
if (WCSession.isSupported()) {
let session = WCSession.default()
session.delegate = self
session.activate()
}
}
@available(iOS 9.3, *)
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
func sessionDidBecomeInactive(_ session: WCSession) {
}
func sessionDidDeactivate(_ session: WCSession) {
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Swift.Void) {
if let action = message["action"] as? String, action == "getMessages" {
UsergridManager.getFeedMessages { (response) -> Void in
if let entities = response.entities {
self.sendEntitiesToWatch(entities)
}
}
}
}
func sendEntitiesToWatch(_ messages:[UsergridEntity]) {
if WCSession.default().isReachable {
NSKeyedArchiver.setClassName("ActivityEntity", for: ActivityEntity.self)
let data = NSKeyedArchiver.archivedData(withRootObject: messages)
WCSession.default().sendMessageData(data, replyHandler: nil, errorHandler: { (error) -> Void in
self.showAlert("WCSession Unreachable.", message: "\(error)")
})
}
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
if let action = message["action"] as? String, action == "getMessages" {
UsergridManager.getFeedMessages { (response) -> Void in
if let entities = response.entities {
self.sendEntitiesToWatch(entities)
}
}
}
}
}