Last active
September 11, 2018 05:43
-
-
Save dilipiOSDeveloper/893d653154f07b18c7c90e987346c1b3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ChatViewController.swift | |
// pukkading | |
// | |
// Created by Vikas Pundora on 23/07/18. | |
// Copyright © 2018 Twist. All rights reserved. | |
// | |
import UIKit | |
import SystemConfiguration | |
import Foundation | |
import JSQMessagesViewController | |
import SDWebImage | |
import MobileCoreServices | |
import Alamofire | |
class ChatViewController: JSQMessagesViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate { | |
var timer = Timer() // Timer | |
var listId:String? | |
var receivedId:String? | |
var listName:String? | |
var messages = [MyMessage]() | |
var avatars = [String: JSQMessagesAvatarImage]() | |
var outgoingBubbleImageView: JSQMessagesBubbleImage! | |
var incomingBubbleImageView: JSQMessagesBubbleImage! | |
var strImage = [UIImage]() | |
let picker = UIImagePickerController() | |
var parentNavigationController: UINavigationController? | |
var stringID = String() | |
var userValueStore:String! | |
var shopKeeperValueStore:String? | |
//var staticTextArray = [String]() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
if (!self.isInternetAvailable()){ | |
self.alertMessageShow(title: "No Internet Connection", message: "Make sure your device is connected to the internet.") | |
} | |
else{ | |
GIFHUD.shared.setGif(named: "pika.gif") | |
GIFHUD.shared.show() | |
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3), execute: { | |
GIFHUD.shared.dismiss(completion: { | |
}) | |
}) | |
//self.userValueStore = "" | |
self.senderId = "1" | |
self.senderDisplayName = "Sender" | |
picker.delegate = self | |
self.edgesForExtendedLayout = [] | |
self.collectionView?.collectionViewLayout.sectionInset = UIEdgeInsets(top: 60, left: 0, bottom: 0, right: 0) | |
self.inputToolbar?.contentView?.textView.placeHolder = "Type a message..." | |
self.inputToolbar?.contentView?.textView.returnKeyType = UIReturnKeyType.done | |
self.inputToolbar?.contentView?.textView.autocorrectionType = .no | |
collectionView?.collectionViewLayout.incomingAvatarViewSize = .zero | |
collectionView?.collectionViewLayout.outgoingAvatarViewSize = .zero | |
addHeaderView() | |
setupBubbles() | |
chatMessageShow() | |
automaticallyScrollsToMostRecentMessage = true | |
timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(updateChat), userInfo: nil, repeats: true) | |
} | |
} | |
override func viewDidDisappear(_ animated: Bool) { | |
//timer.invalidate() | |
} | |
func updateChat(){ | |
userMessageAfterParticularMessages() | |
} | |
func addHeaderView() { | |
let selectableView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: 60)) | |
selectableView.backgroundColor = UIColor(red: 0.149, green: 0.1529, blue: 0.2, alpha: 1.0) | |
let btn: UIButton = UIButton(frame: CGRect(x: 8, y: 13, width: 50, height: 50)) | |
btn.setTitle("Back", for: .normal) | |
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14) | |
btn.addTarget(self, action: #selector(backButtonAction), for: .touchUpInside) | |
selectableView.addSubview(btn) | |
let lblListTitle = UILabel(frame: CGRect(x:btn.frame.size.width + 10 ,y:24,width: selectableView.frame.size.width - 100, height: 18)) | |
lblListTitle.textColor = UIColor.white | |
lblListTitle.textAlignment = .center | |
lblListTitle.font = UIFont.boldSystemFont(ofSize: 16) | |
lblListTitle.text = listName | |
selectableView.addSubview(lblListTitle) | |
view.addSubview(selectableView) | |
} | |
func backButtonAction(){ | |
timer.invalidate() | |
_ = navigationController?.popViewController(animated: true) | |
} | |
private func setupBubbles() { | |
let factory = JSQMessagesBubbleImageFactory() | |
outgoingBubbleImageView = factory?.outgoingMessagesBubbleImage(with: UIColor.jsq_messageBubbleBlue()) | |
incomingBubbleImageView = factory?.incomingMessagesBubbleImage(with: UIColor.jsq_messageBubbleGreen()) | |
} | |
override func collectionView(_ collectionView: JSQMessagesCollectionView, attributedTextForCellTopLabelAt indexPath: IndexPath) -> NSAttributedString? { | |
let message = messages[indexPath.item] | |
if indexPath.item == 0 { | |
return NSAttributedString(string:message.date.dateString(), attributes: | |
[NSForegroundColorAttributeName: UIColor.lightGray, | |
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 13.0)]) | |
}else { | |
let previousMessage = messages[indexPath.item - 1] | |
if Calendar.current.isDate(previousMessage.date, inSameDayAs: message.date) { | |
return nil | |
}else { | |
return NSAttributedString(string:message.date.dateString(), attributes: | |
[NSForegroundColorAttributeName: UIColor.lightGray, | |
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 13.0)]) | |
} | |
} | |
} | |
override func collectionView(_ collectionView: JSQMessagesCollectionView, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout, heightForCellTopLabelAt indexPath: IndexPath) -> CGFloat { | |
let message = messages[indexPath.item] | |
if indexPath.item == 0 { | |
return kJSQMessagesCollectionViewCellLabelHeightDefault | |
}else { | |
let previousMessage = messages[indexPath.item - 1] | |
if Calendar.current.isDate(previousMessage.date, inSameDayAs: message.date) { | |
return 0.0 | |
}else { | |
return kJSQMessagesCollectionViewCellLabelHeightDefault | |
} | |
} | |
} | |
// Showing outgoing bubble based on sender id | |
override func collectionView(_ collectionView: JSQMessagesCollectionView, messageBubbleImageDataForItemAt indexPath: IndexPath) -> JSQMessageBubbleImageDataSource { | |
let message = messages[indexPath.item] | |
if message.senderId == "1" { | |
return outgoingBubbleImageView | |
} else { | |
return incomingBubbleImageView | |
} | |
} | |
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { | |
print("Array Count : \(messages.count)") | |
return messages.count | |
} | |
override func collectionView(_ collectionView: JSQMessagesCollectionView!, messageDataForItemAt indexPath: IndexPath!) -> JSQMessageData!{ | |
return messages[indexPath.item] | |
} | |
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { | |
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell | |
let message = self.messages[indexPath.item] | |
let dateFormat = DateFormatter() | |
dateFormat.dateFormat = "h:mm a" | |
let strDate: String = dateFormat.string(from: (message.date)!) | |
cell.cellBottomLabel.text = strDate | |
let topdate = DateFormatter() | |
topdate.dateStyle = .medium | |
topdate.doesRelativeDateFormatting = true | |
let dateString = topdate.string(from: message.date) | |
cell.cellTopLabel.text = dateString | |
return cell | |
} | |
override func didPressSend(_ button: UIButton!, withMessageText text: String!, senderId: String!, senderDisplayName: String!, date: Date!){ | |
sendMessageToOtherUser(with: text)// | |
//self.staticTextArray.append(text) | |
self.messages.append(MyMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: date, text: text, messageID:"")) | |
// this shows on chat screen same time after sending | |
self.finishSendingMessage(animated: true) | |
self.view.endEditing(true) | |
} | |
override func didPressAccessoryButton(_ sender: UIButton!) { | |
print("didPressAccessoryButton") | |
let alert = UIAlertController(title: "Media Message", message: "Please Select A Media", preferredStyle: .actionSheet) | |
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: {(alert : UIAlertAction) in | |
self.view.endEditing(true) | |
}) | |
let photos = UIAlertAction(title: "Photos", style: .default, handler: {(alert : UIAlertAction) in | |
self.chooseMedia(type: kUTTypeImage) | |
}) | |
alert.addAction(cancel) | |
alert.addAction(photos) | |
present(alert, animated: true, completion: nil) | |
} | |
override func collectionView(_ collectionView: JSQMessagesCollectionView, didTapMessageBubbleAt indexPath: IndexPath) { | |
let message: JSQMessage? = messages[indexPath.item] | |
if message?.isMediaMessage != nil { | |
let mediaItem: JSQMessageMediaData? = message?.media | |
if (mediaItem is JSQPhotoMediaItem) { | |
print("Tapped photo message bubble!") | |
let photoItem = mediaItem as? JSQPhotoMediaItem | |
let newImageView = UIImageView(image: photoItem?.image) | |
newImageView.frame = UIScreen.main.bounds | |
newImageView.backgroundColor = UIColor.black.withAlphaComponent(0.8) | |
newImageView.contentMode = .scaleToFill | |
newImageView.isUserInteractionEnabled = true | |
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage)) | |
newImageView.addGestureRecognizer(tap) | |
self.view.addSubview(newImageView) | |
self.tabBarController?.tabBar.isHidden = true | |
} | |
} | |
} | |
func dismissFullscreenImage(_ sender: UITapGestureRecognizer) { | |
self.tabBarController?.tabBar.isHidden = false | |
sender.view?.removeFromSuperview() | |
} | |
override func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) { | |
let msgID = messages[indexPath.item] | |
print("Message ID : \(msgID.messageID)") | |
if(msgID.senderId == "1"){ | |
if (action == #selector(UIResponderStandardEditActions.delete(_:))) { | |
self.messages.remove(at: indexPath.item) | |
self.deleteOwnerMessage(with: "\(msgID.messageID)") | |
print("Message After Delete : \(messages)") | |
} | |
} | |
} | |
// Image Picker Functions | |
private func chooseMedia(type: CFString){ | |
picker.mediaTypes = [type as String] | |
present(picker, animated: true, completion: nil) | |
} | |
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { | |
DispatchQueue.main.async { () -> Void in | |
if let pic = info[UIImagePickerControllerOriginalImage] as? UIImage{ | |
self.strImage.append(pic) | |
//let img = JSQPhotoMediaItem(image: pic) | |
//let date = Date() | |
self.sendImageToOtherUser() | |
//self.messages.append(MyMessage(senderId: "1", senderDisplayName: self.senderDisplayName, date: date, media: img!, messageID: self.stringID)) | |
self.finishSendingMessage(animated: true) | |
} | |
self.dismiss(animated: true, completion: nil) | |
} | |
} | |
// end Picker | |
override func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { | |
if text == "\n" { | |
self.view.endEditing(true) | |
} | |
return true | |
} | |
// diliptest 1234 business user , user id - 1929 , deal id - 29861 author id - 1910 | |
// User Message Page after perticular message for a Perticular Listing | |
func userMessageAfterParticularMessages(){ | |
let prs = [ | |
"user_id":Current_User.ID, | |
"receiver_id":receivedId, | |
"deal_id":listId, | |
"msg_id":userValueStore, | |
"user_listing_after_msg": "1" as String | |
] | |
Service.StartWithoutLoading(prs as [String : AnyObject]?, onCompletion: { result in | |
print("RESPONSE JSON :\(result)") | |
if let status_value = result["status"] as? String{ | |
if(status_value == "success"){ | |
guard let message_array = result["message"] as? [[String:AnyObject]] else{return} | |
for messageData in message_array{ | |
let msg_ID = messageData["id"] as? String | |
let self_Message = messageData["is_self"] as? String | |
let is_attachment = messageData["is_attachment"] as? String | |
let msg_text = messageData["message"] as? String | |
let added_time = messageData["added_time"] | |
guard let timeinterval : TimeInterval = (added_time)?.doubleValue else{return} | |
let dateFromServer = NSDate(timeIntervalSince1970:timeinterval) | |
let dateFormater : DateFormatter = DateFormatter() | |
dateFormater.dateFormat = "dd-MMM-yyyy hh:mm a" | |
let shopkeeper = UserDefaults.standard.object(forKey: "shopkeeper_name") as? String // shopkeeper | |
let user = UserDefaults.standard.object(forKey: "user_image") as? String // other user | |
DispatchQueue.main.async { | |
let photo = JSQPhotoMediaItem() | |
if(self_Message == "1"){ | |
if is_attachment == "0"{ | |
self.messages.removeLast() | |
let message = MyMessage(senderId: self_Message!, senderDisplayName: shopkeeper!, date: dateFromServer as Date, text: msg_text!, messageID: msg_ID!) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
else{ | |
if let url = NSURL(string:msg_text! ){ | |
guard let data = NSData(contentsOf: url as URL) else{ return } | |
let image = UIImage(data: data as Data) | |
photo.image = image | |
photo.appliesMediaViewMaskAsOutgoing = true | |
let message = MyMessage(senderId: self_Message!, senderDisplayName: shopkeeper!, date: dateFromServer as Date!, media: photo, messageID: msg_ID!) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
} | |
} | |
else{ | |
if is_attachment == "0"{ | |
//self.messages.removeLast() | |
let message = MyMessage(senderId: "0", senderDisplayName: user!, date: dateFromServer as Date, text: msg_text!, messageID: msg_ID!) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
else{ | |
if let url = NSURL(string:msg_text! ){ | |
guard let data = NSData(contentsOf: url as URL) else{ return } | |
let image = UIImage(data: data as Data) | |
photo.image = image | |
photo.appliesMediaViewMaskAsOutgoing = true | |
let message = MyMessage(senderId: "0", senderDisplayName: user!, date: dateFromServer as Date!, media: photo, messageID: msg_ID!) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
} | |
} | |
} | |
} | |
let id = message_array.last?["id"] | |
print("last message id \(id)") | |
self.userValueStore = id as! String! | |
} | |
else{ | |
print(status_value as Any) | |
} | |
} | |
}) | |
} | |
// delete own message based on message id | |
func deleteOwnerMessage(with messageID:String){ | |
let prs = [ | |
"msg_id":messageID, | |
"send_msg_delete_self": "1" as String | |
] | |
print("Message ID Passed for Delete API : \(messageID)") | |
Service.StartWithoutLoading(prs as [String : AnyObject]?, onCompletion: { result in | |
print("JSON Response :\(result)") | |
DispatchQueue.global(qos: .background).async { | |
let json = result as? [String:AnyObject] | |
DispatchQueue.main.async { | |
if let sq = json?["status"] as? String{ | |
if (sq == "success"){ | |
print("Shopkeeper message deleted successfully.") | |
self.collectionView.reloadData() | |
} | |
else{ | |
self.showAlertWithTitle("Error", message: "Cannot delete the received message.") | |
print("Error in deleting deal") | |
} | |
} | |
} | |
} | |
}) | |
} | |
// delete message web service | |
// {"status":"success","message_id":1269,"result":"Message sent successfully"} | |
// Send Message to other user | |
func sendMessageToOtherUser(with messageSend:String){ | |
let prs = [ | |
"author_id":Current_User.ID, | |
"receiver_id":receivedId, | |
"deal_id":listId, | |
"message":messageSend, | |
"send_msg_to_other": "1" as String | |
] | |
Alamofire.upload( | |
multipartFormData: { MultipartFormData in | |
for (key, value) in prs { | |
MultipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key) | |
} | |
}, to: URL.App_URL) { (result) in | |
switch result { | |
case .success(let upload, _, _): | |
upload.responseJSON { response in | |
print(response.result.value as Any) | |
if let jsonDict = response.result.value as? [String:AnyObject], | |
let status = jsonDict["status"] as? String { | |
DispatchQueue.main.async { | |
if (status == "success"){ | |
let idMessage = jsonDict["message_id"] as? Int | |
//self.userValueStore = "\(idMessage!)" | |
} | |
else{ | |
self.showAlertWithTitle("Failed", message: "Error while sending message.") | |
} | |
} | |
} | |
} | |
case .failure(let encodingError): | |
print(encodingError) | |
DispatchQueue.main.async { | |
let alertView = UIAlertView(title: "Error", message: "Server is not responding properly.", delegate: nil, cancelButtonTitle: "Try Again") | |
alertView.alertViewStyle = .default | |
alertView.show() | |
} | |
break | |
} | |
} | |
} | |
func sendImageToOtherUser(){ | |
let prs = [ | |
"author_id":Current_User.ID, | |
"receiver_id":receivedId, | |
"deal_id":listId, | |
"send_msg_to_other": "1" as String | |
] | |
Alamofire.upload( | |
multipartFormData: { MultipartFormData in | |
for (key, value) in prs { | |
MultipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key) | |
} | |
for element in 0..<self.strImage.count { | |
let singleImage : Data? = self.strImage[element].lowestQualityJPEGNSData as Data? | |
MultipartFormData.append(singleImage!, withName: "image", fileName: "swift_file.jpg", mimeType: "image/jpeg") | |
} | |
}, to: URL.App_URL) { (result) in | |
switch result { | |
case .success(let upload, _, _): | |
upload.responseJSON { response in | |
print(response.result.value as Any) | |
if let jsonDict = response.result.value as? [String:AnyObject], | |
let status = jsonDict["status"] as? String { | |
DispatchQueue.global(qos: .background).async { | |
DispatchQueue.main.async { | |
if (status == "success"){ | |
_ = jsonDict["message_id"] as? Int | |
//self.stringID = "\(idMessage!)" | |
} | |
else{ | |
self.showAlertWithTitle("Failed", message: "Error while sending message.") | |
} | |
} | |
} | |
} | |
} | |
case .failure(let encodingError): | |
print(encodingError) | |
DispatchQueue.global(qos: .background).async { | |
let alertView = UIAlertView(title: "Error", message: "Server is not responding properly.", delegate: nil, cancelButtonTitle: "Try Again") | |
alertView.alertViewStyle = .default | |
alertView.show() | |
} | |
break | |
} | |
} | |
} | |
// Chat Message[ User Message Page for Perticular Listing (next step of above api) ] | |
func chatMessageShow(){ | |
let prs = [ | |
"user_id":Current_User.ID, | |
"receiver_id":receivedId, | |
"deal_id":listId, | |
"user_listing_msg": "1" as String | |
] | |
Service.StartWithoutLoading(prs as [String : AnyObject]?, onCompletion: { result in | |
guard let resultDict = result["result"] as? [String:AnyObject] else{return} | |
let user_image = resultDict["user_image"] as? String | |
UserDefaults.standard.set(user_image, forKey: "user_image") | |
let shopkeeper_name = resultDict["shopkeeper_name"] as? String | |
UserDefaults.standard.set(shopkeeper_name, forKey: "shopkeeper_name") | |
guard let messageArray = resultDict["message"] as? [[String:AnyObject]] else{return} | |
print("Message Array : \(messageArray)") | |
DispatchQueue.main.async { () -> Void in | |
for message in messageArray{ | |
guard let msg = message["message"] as? String else{ return } | |
let is_self = message["is_self"] as? String | |
let messageID = message["id"] as? String | |
let added_time = message["added_time"] | |
guard let timeinterval : TimeInterval = (added_time)?.doubleValue else{return} | |
let dateFromServer = NSDate(timeIntervalSince1970:timeinterval) | |
let dateFormater : DateFormatter = DateFormatter() | |
dateFormater.dateFormat = "dd-MMM-yyyy hh:mm a" // 22-Sep-2017 02:53 PM | |
let is_attachment = message["is_attachment"] as? String | |
let photo = JSQPhotoMediaItem() | |
if is_self == "1"{ | |
if is_attachment == "0"{ | |
let message = MyMessage(senderId: is_self!, senderDisplayName: shopkeeper_name!, date: dateFromServer as Date, text: msg, messageID: messageID!) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
else if is_attachment == "1"{ | |
if let url = NSURL(string:msg ){ | |
guard let data = NSData(contentsOf: url as URL) else{ return } | |
let image = UIImage(data: data as Data) | |
photo.image = image | |
photo.appliesMediaViewMaskAsOutgoing = true | |
let message = MyMessage(senderId: is_self!, senderDisplayName: shopkeeper_name!, date: dateFromServer as Date!, media: photo, messageID: messageID!) | |
self.messages.append(message) | |
print(message.messageID) | |
self.finishReceivingMessage(animated: true) | |
} | |
} | |
} | |
else{ | |
if is_attachment == "0"{ | |
let message = MyMessage(senderId: "0", senderDisplayName: user_image!, date: dateFromServer as Date!, text: msg, messageID: messageID!) | |
print(message.messageID) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
else if is_attachment == "1"{ | |
if let url = NSURL(string:msg ){ | |
guard let data = NSData(contentsOf: url as URL) else{ return } | |
let image = UIImage(data: data as Data) | |
photo.image = image | |
photo.appliesMediaViewMaskAsOutgoing = false | |
let message = MyMessage(senderId: "0", senderDisplayName: user_image!, date: dateFromServer as Date!, media: photo, messageID: messageID!) | |
print(message.messageID) | |
self.messages.append(message) | |
self.finishReceivingMessage(animated: true) | |
} | |
} | |
} | |
} | |
self.collectionView.reloadData() | |
self.collectionView.layoutIfNeeded() | |
} | |
}) | |
} | |
// Chat Message End | |
} | |
public extension Date { | |
public func dateString (format: String = "dd MMM, yyyy") -> String { | |
let formatter = DateFormatter() | |
formatter.dateFormat = format | |
return formatter.string(from: self) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment