Well, after a lot of documentation I managed to make it work.
I leave the whole code, although it needs to be polished a bit, I hope that this type of response does not make me negative. XD.
class ChatComents: JSQMessagesViewController {
var user: FIRUser?
var messages = [JSQMessage]()
var messagesStack = [JSQMessage]()
var avatars = Dictionary<String, AnyObject>()
var avatarsTapImage = Dictionary<String, UIImage>()
var avatarsUrl = Dictionary<String, String>()
var outgoingBubbleImageView: JSQMessagesBubbleImage!
var incomingBubbleImageView: JSQMessagesBubbleImage!
var senderImageUrl: String!
var batchMessages = true
var messagesBlockCant: UInt = 25
var numeroDeComentarios: Int?
var ref: FIRDatabaseReference!
var imageRemoteURL: String?
//var currentUsername: String?
var messageRef: FIRDatabaseReference!
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
var currentUserAvatar = UIImageView()
// *** STEP 1: STORE FIREBASE REFERENCES
var messagesRef: FIRDatabaseReference!
private func setupBubbles() {
let factory = JSQMessagesBubbleImageFactory()
outgoingBubbleImageView = factory.outgoingMessagesBubbleImageWithColor(
UIColor.jsq_messageBubbleBlueColor())
incomingBubbleImageView = factory.incomingMessagesBubbleImageWithColor(
UIColor.jsq_messageBubbleGreenColor()) //jsq_messageBubbleLightGrayColor
}
func convertDateFormater(date: String) -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z" // 2016-06-20 20:32:40 +0000
dateFormatter.timeZone = NSTimeZone(name: "UTC")
guard let date = dateFormatter.dateFromString(date) else {
assert(false, "no date from string")
return ""
}
dateFormatter.dateFormat = "d MMM yyyy HH:mm"
dateFormatter.timeZone = NSTimeZone(name: "UTC")
let timeStamp = dateFormatter.stringFromDate(date)
print("fecha reformateada vale: ", timeStamp)
return timeStamp
}
func setupFirebase() {
// *** STEP 2: SETUP FIREBASE
// *** STEP 4: RECEIVE MESSAGES FROM FIREBASE (limited to latest 25
messageRef.queryLimitedToLast(messagesBlockCant).observeEventType(FIRDataEventType.ChildAdded, withBlock: { (snapshot) in
let text = snapshot.value!["text"] as! String
let senderId = snapshot.value!["senderId"] as! String
let imageUrl = snapshot.value!["imageURL"] as! String
let senderDisplayName = snapshot.value!["senderDisplayName"] as! String
let fecha = snapshot.value!["fecha"] as! String
print("fecha sin formato es: ", fecha) // ....
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" //"yyyy-MM-dd HH:mm:ss Z" // 2016-06-20 20:32:40 +0000
let date = dateFormatter.dateFromString(fecha)
let dateFormatter24Hrs = NSDateFormatter()
dateFormatter24Hrs.dateFormat = "yyyy-MM-dd hh:mm:ss Z" // 2016-06-20 2311:16:48 p.m. +0000
//let fechita = dateFormatter.dateFromString(fecha)
print("La fecha final es: ", date, "del texto: ", text)
let message = JSQMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: date, text: text)
self.avatarsUrl.updateValue(imageUrl, forKey: senderId)
print("avatarsUrl vale: ", self.avatarsUrl)
self.messages.append(message)
self.finishReceivingMessage()
})
}
func sendMessage(text: String!, senderId: String!) {
// *** STEP 3: ADD A MESSAGE TO FIREBASE
let components = calendar.components([.Day , .Month , .Year], fromDate: date)
let year = components.year
let month = components.month
let day = components.day
let fechaComentario = String(String(day) + "/" + String(month) + "/" + String(year))
print("Fecha del comentario: ", fechaComentario)
messageRef.childByAutoId().setValue([
"text": text, //
"votes": 0,
"senderDisplayName": senderDisplayName,
"senderId": senderId, //
"nombreEntidad": Variable.currentObject,
"imageURL": senderImageUrl, //
"fecha": fechaComentario //
])
}
func setupAvatarImage(name: String, imageUrl: String?, incoming: Bool, initials: String) {
print("el name vale: ", name)
print("el initial vale: ", initials)
if let stringUrl = imageUrl {
if let url = NSURL(string: stringUrl) {
if let data = NSData(contentsOfURL: url) {
let image = UIImage(data: data)
let diameter = incoming ? UInt(collectionView!.collectionViewLayout.incomingAvatarViewSize.width) : UInt(collectionView!.collectionViewLayout.outgoingAvatarViewSize.width)
print("diametro es: ", diameter)
let avatarImage = JSQMessagesAvatarImageFactory.avatarImageWithImage(image, diameter: diameter)
avatars[name] = avatarImage
avatarsTapImage[name] = image
return
}
}
}
setupAvatarColor(name, incoming: incoming, initials: initials)
}
func setupAvatarColor(name: String, incoming: Bool, initials: String) {
let diameter = incoming ? UInt(collectionView!.collectionViewLayout.incomingAvatarViewSize.width) : UInt(collectionView!.collectionViewLayout.outgoingAvatarViewSize.width)
let rgbValue = name.hash
let r = CGFloat(Float((rgbValue & 0xFF0000) >> 16)/255.0)
let g = CGFloat(Float((rgbValue & 0xFF00) >> 8)/255.0)
let b = CGFloat(Float(rgbValue & 0xFF)/255.0)
let color = UIColor(red: r, green: g, blue: b, alpha: 0.5)
let nameLength = initials.characters.count
let initialsName : String? = initials.substringToIndex(senderId.startIndex.advancedBy(min(3, nameLength)))
print("INICIALES: ", initialsName)
let userImage = JSQMessagesAvatarImageFactory.avatarImageWithUserInitials(initialsName, backgroundColor: color, textColor: UIColor.blackColor(), font: UIFont.systemFontOfSize(CGFloat(13)), diameter: diameter)
avatars[name] = userImage
avatarsTapImage[name] = userImage.avatarHighlightedImage
}
func loadMore() {
print("Load earlier messages!")
//setupFirebase()
self.collectionView.collectionViewLayout.springinessEnabled = false
messagesBlockCant += 25
var contador = 1
// *** STEP 4: RECEIVE MESSAGES FROM FIREBASE (limited to latest 25
messageRef.queryLimitedToLast(messagesBlockCant).observeEventType(FIRDataEventType.ChildAdded, withBlock: { (snapshot) in
self.collectionView.infiniteScrollingView.startAnimating()
let diferencia = self.numeroDeComentarios! - self.messages.count
if (diferencia != 0) // (self.numeroDeComentarios! >= self.messages.count) //|| (diferencia != 0)
{
//self.collectionView.showsInfiniteScrolling = false
let oldBottomOffset = self.collectionView.contentSize.height - self.collectionView.contentOffset.y
//print("Este mensaje no deberia aparecer si diferencia es 0: ", diferencia)
let text = snapshot.value!["text"] as! String
let senderId = snapshot.value!["senderId"] as! String
let imageUrl = snapshot.value!["imageURL"] as! String
let senderDisplayName = snapshot.value!["senderDisplayName"] as! String
let fecha = snapshot.value!["fecha"] as! String
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" //"yyyy-MM-dd HH:mm:ss Z" // 2016-06-20 20:32:40 +0000
let date = dateFormatter.dateFromString(fecha)
let message = JSQMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: date, text: text)
self.avatarsUrl.updateValue(imageUrl, forKey: senderId)
if diferencia > 24
{
if contador <= 25 {
self.messagesStack.insert(message, atIndex: 0)
print("La fecha final es: ", date, "del texto: ", text)
//print("contador: ", contador)
}
}
else
{
if contador <= diferencia+1
{
self.messagesStack.insert(message, atIndex: 0)
print("self.messagesStack contiene: ", text)
print("text agregado cuando ya no es multiplo de 25: ", diferencia)
print("contador diferente a 25: ", contador)
}
}
contador += 1
if contador == 26{
if diferencia > 24
{
for limiteMax in 0...24{
//print("limiteMax vale: ", limiteMax)
//print("messagesStack.count vale: ", self.messagesStack.count)
let traspasoValores = self.messagesStack[limiteMax]
self.messages.insert(traspasoValores, atIndex: 0)
self.finishReceivingMessage()
}
} else{
if diferencia != 0 {
for limiteMax in 1...diferencia {
let traspasoValores = self.messagesStack[limiteMax]
self.messages.insert(traspasoValores, atIndex: 0)
self.finishReceivingMessage()
}
}
}
}
self.finishReceivingMessageAnimated(false)
self.collectionView.layoutIfNeeded()
self.collectionView.contentOffset = CGPointMake(0, self.collectionView.contentSize.height - oldBottomOffset)
self.collectionView.infiniteScrollingView.stopAnimating()
self.collectionView.collectionViewLayout.springinessEnabled = false
}
else{
print("No hay mas comentarios que mostrar")
self.collectionView.infiniteScrollingView.stopAnimating()
self.collectionView.collectionViewLayout.springinessEnabled = false
self.collectionView.showsInfiniteScrolling = false
}
self.collectionView.infiniteScrollingView.stopAnimating()
})
}
override func viewDidLoad() {
super.viewDidLoad()
//inputToolbar!.contentView!.leftBarButtonItem = nil
self.inputToolbar.removeFromSuperview()
//automaticallyScrollsToMostRecentMessage = true
self.showLoadEarlierMessagesHeader = true
self.collectionView.loadEarlierMessagesHeaderTextColor = UIColor.blackColor()
// Infinite scrolling
//navigationController?.navigationBar.topItem?.title = "Atras"
setupBubbles()
senderId = (senderId != nil) ? senderId : "Anonymous"
let profileImageUrl = imageRemoteURL
if let urlString = profileImageUrl {
setupAvatarImage(senderId, imageUrl: urlString as String, incoming: false, initials: senderDisplayName)
senderImageUrl = urlString as String
} else {
setupAvatarColor(senderId, incoming: false, initials: senderDisplayName)
senderImageUrl = ""
}
setupFirebase()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
//self.collectionView.triggerPullToRefresh()
Variable.refComment.observeEventType(FIRDataEventType.Value, withBlock: { snapshot in
let numeroDeComents = snapshot.childrenCount
self.numeroDeComentarios = Int(numeroDeComents)
print("y el numero de comentarios en viewDidAppear es: ", self.numeroDeComentarios!)
}, withCancelBlock: { error in
print(error.description)
})
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
}
override func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!,
senderDisplayName: String!, date: NSDate!) {
let components = calendar.components([.Day , .Month , .Year], fromDate: date)
let year = components.year
let month = components.month
let day = components.day
let fechaComentario = String(String(day) + "/" + String(month) + "/" + String(year))
print("Fecha del comentario: ", fechaComentario)
let fechaComment = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let convertedDate = dateFormatter.stringFromDate(fechaComment)
print("convertedDate vale: ", convertedDate)
let messageItem = [
"text": text, //
"votes": 0,
"senderDisplayName": senderDisplayName,
"senderId": senderId, //
"nombreEntidad": Variable.currentObject,
"imageURL": imageRemoteURL!, //
"fecha": String(convertedDate) //
]
messageRef.childByAutoId().setValue(messageItem)
// 4
JSQSystemSoundPlayer.jsq_playMessageSentSound()
// 5
finishSendingMessage()
}
func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!, date: NSDate!) {
JSQSystemSoundPlayer.jsq_playMessageSentSound()
}
override func didPressAccessoryButton(sender: UIButton!) {
print("Camera pressed!")
}
override func collectionView(collectionView: JSQMessagesCollectionView!, didTapMessageBubbleAtIndexPath indexPath: NSIndexPath!) {
print("Tapped message bubble!")
}
func dismissFullscreenImage(sender: UITapGestureRecognizer) {
sender.view?.removeFromSuperview()
}
override func collectionView(collectionView: JSQMessagesCollectionView!, didTapAvatarImageView avatarImageView: UIImageView!, atIndexPath indexPath: NSIndexPath!) {
print("Tapped avatar!")
let message = messages[indexPath.row]
Variable.popupUsername = message.senderDisplayName
Variable.popupImageProfile = avatarsTapImage[message.senderId]!
Variable.popupImageProfileUrl = avatarsUrl[message.senderId]
Variable.popupSenderId = message.senderId
//Variable.popupLoveUserCant =
//Variable.popupCommentUserCant =
PopupController
.create(self)
.show(ProfileResumeVC.instance())
}
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .None
}
override func collectionView(collectionView: JSQMessagesCollectionView!, messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
override func collectionView(collectionView: JSQMessagesCollectionView!, messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item] // 1
if message.senderId == senderId {
return outgoingBubbleImageView
} else { // 3
return incomingBubbleImageView
}
}
override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellTopLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! {
let message = self.messages[indexPath.item]
return JSQMessagesTimestampFormatter.sharedFormatter().attributedTimestampForDate(message.date)
}
override func collectionView(collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForCellTopLabelAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
return kJSQMessagesCollectionViewCellLabelHeightDefault
}
override func collectionView(collectionView: JSQMessagesCollectionView!, header headerView: JSQMessagesLoadEarlierHeaderView!, didTapLoadEarlierMessagesButton sender: UIButton!) {
print("Load earlier messages!")
//setupFirebase()
showLoadEarlierMessagesHeader = true
self.collectionView.collectionViewLayout.springinessEnabled = false
messagesBlockCant += 25
var contador = 1
// *** CONTANDO EL NUMERO DE COMENTARIOS
// *** STEP 4: RECEIVE MESSAGES FROM FIREBASE (limited to latest 25
messageRef.queryLimitedToLast(messagesBlockCant).observeEventType(FIRDataEventType.ChildAdded, withBlock: { (snapshot) in
let diferencia = self.numeroDeComentarios! - self.messages.count
if (diferencia != 0) // (self.numeroDeComentarios! >= self.messages.count) //|| (diferencia != 0)
{
let oldBottomOffset = self.collectionView.contentSize.height - self.collectionView.contentOffset.y
let text = snapshot.value!["text"] as! String
let senderId = snapshot.value!["senderId"] as! String
let imageUrl = snapshot.value!["imageURL"] as! String
let senderDisplayName = snapshot.value!["senderDisplayName"] as! String
let fecha = snapshot.value!["fecha"] as! String
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" //"yyyy-MM-dd HH:mm:ss Z" // 2016-06-20 20:32:40 +0000
let date = dateFormatter.dateFromString(fecha)
let message = JSQMessage(senderId: senderId, senderDisplayName: senderDisplayName, date: date, text: text)
self.avatarsUrl.updateValue(imageUrl, forKey: senderId)
if diferencia > 24
{
if contador <= 25 {
self.messagesStack.insert(message, atIndex: 0)
print("La fecha final es: ", date, "del texto: ", text)
}
}
else
{
if contador <= diferencia+1
{
self.messagesStack.insert(message, atIndex: 0)
print("self.messagesStack contiene: ", text)
print("text agregado cuando ya no es multiplo de 25: ", diferencia)
print("contador diferente a 25: ", contador)
}
}
contador += 1
if contador == 26{
if diferencia > 24
{
for limiteMax in 0...24{
//print("limiteMax vale: ", limiteMax)
//print("messagesStack.count vale: ", self.messagesStack.count)
let traspasoValores = self.messagesStack[limiteMax]
self.messages.insert(traspasoValores, atIndex: 0)
self.finishReceivingMessage()
}
} else{
print("No es exacto, debemos hacer algo aqui: ", diferencia)
if diferencia != 0 {
for limiteMax in 1...diferencia {
print("limiteMax vale en xxx: ", limiteMax)
print("messagesStack.count vale en xxx: ", self.messagesStack.count)
let traspasoValores = self.messagesStack[limiteMax]
self.messages.insert(traspasoValores, atIndex: 0)
self.finishReceivingMessage()
}
}
}
}
self.finishReceivingMessageAnimated(false)
self.collectionView.layoutIfNeeded()
self.collectionView.contentOffset = CGPointMake(0, self.collectionView.contentSize.height - oldBottomOffset)
self.collectionView.collectionViewLayout.springinessEnabled = false
}
else{
print("No hay mas comentarios que mostrar")
self.collectionView.collectionViewLayout.springinessEnabled = false
self.showLoadEarlierMessagesHeader = false
}
})
}
override func collectionView(collectionView: JSQMessagesCollectionView!, avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
let message = messages[indexPath.item]
var imageAvatar : JSQMessageAvatarImageDataSource?
for senderReferenceImage in avatars.keys where senderReferenceImage == message.senderId
{
imageAvatar = avatars[senderReferenceImage] as? JSQMessageAvatarImageDataSource
// print("Hola desde el primer Ford XD")
return imageAvatar
}
for senderReferenceUrl in avatarsUrl.keys where senderReferenceUrl == message.senderId
{
print("message.senderId! vale: ", message.senderId!)
print("avatarsUrl[senderReferenceUrl] vale: ", avatarsUrl[senderReferenceUrl]!)
setupAvatarImage(message.senderId!, imageUrl: avatarsUrl[senderReferenceUrl], incoming: true, initials: message.senderDisplayName)
imageAvatar = avatars[senderReferenceUrl] as? JSQMessageAvatarImageDataSource
return imageAvatar
}
return JSQMessagesAvatarImage.avatarWithImage(self.currentUserAvatar.image)
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return messages.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.blackColor()
} else {
cell.textView!.textColor = UIColor.blackColor()
}
let attributes : [NSObject:AnyObject] = [NSForegroundColorAttributeName:cell.textView!.textColor!, NSUnderlineStyleAttributeName: 1]
cell.textView!.linkTextAttributes = attributes as AnyObject as! [String : AnyObject]
return cell
}
// View usernames above bubbles
override func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> NSAttributedString! {
let message = messages[indexPath.item];
// Sent by me, skip
if message.senderId! == senderId {
return nil
}
// Same as previous sender, skip
if indexPath.item > 0 {
let previousMessage = messages[indexPath.item - 1];
if previousMessage.senderId == message.senderId {
return NSAttributedString(string:message.senderDisplayName!)
}
}
return NSAttributedString(string:message.senderDisplayName!)
}
override func collectionView(collectionView: JSQMessagesCollectionView!, layout collectionViewLayout: JSQMessagesCollectionViewFlowLayout!, heightForMessageBubbleTopLabelAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
let message = messages[indexPath.item]
// Sent by me, skip
if message.senderId == senderId {
return CGFloat(0.0);
}
// Same as previous sender, skip
if indexPath.item > 0 {
let previousMessage = messages[indexPath.item - 1];
if previousMessage.senderId == message.senderId {
return CGFloat(0.0);
}
}
return kJSQMessagesCollectionViewCellLabelHeightDefault
}
}