diff --git a/Yep.xcodeproj/project.pbxproj b/Yep.xcodeproj/project.pbxproj index d7ed8fe4..cceb8aea 100644 --- a/Yep.xcodeproj/project.pbxproj +++ b/Yep.xcodeproj/project.pbxproj @@ -80,6 +80,8 @@ 50CDBE421ACA9B4200459CE0 /* ChatRightImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CDBE401ACA9B4200459CE0 /* ChatRightImageCell.swift */; }; 50CDBE431ACA9B4200459CE0 /* ChatRightImageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50CDBE411ACA9B4200459CE0 /* ChatRightImageCell.xib */; }; 50CDBE461ACA9F2200459CE0 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CDBE451ACA9F2200459CE0 /* ImageCache.swift */; }; + 50CDBE491ACBAD3200459CE0 /* ChatLeftImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */; }; + 50CDBE4A1ACBAD3200459CE0 /* ChatLeftImageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */; }; 50E114F41ABBF9CC00F13000 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F31ABBF9CC00F13000 /* Models.swift */; }; 50E114F71ABBFA7000F13000 /* RLMSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F61ABBFA7000F13000 /* RLMSupport.swift */; }; 50E114F91ABC137A00F13000 /* YepServiceSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F81ABC137A00F13000 /* YepServiceSync.swift */; }; @@ -181,6 +183,8 @@ 50CDBE401ACA9B4200459CE0 /* ChatRightImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatRightImageCell.swift; path = Views/Cells/ChatRightImage/ChatRightImageCell.swift; sourceTree = ""; }; 50CDBE411ACA9B4200459CE0 /* ChatRightImageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatRightImageCell.xib; path = Views/Cells/ChatRightImage/ChatRightImageCell.xib; sourceTree = ""; }; 50CDBE451ACA9F2200459CE0 /* ImageCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageCache.swift; path = Caches/ImageCache.swift; sourceTree = ""; }; + 50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatLeftImageCell.swift; path = Views/Cells/ChatLeftImage/ChatLeftImageCell.swift; sourceTree = ""; }; + 50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatLeftImageCell.xib; path = Views/Cells/ChatLeftImage/ChatLeftImageCell.xib; sourceTree = ""; }; 50E114F31ABBF9CC00F13000 /* Models.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Models.swift; path = Realm/Models.swift; sourceTree = ""; }; 50E114F61ABBFA7000F13000 /* RLMSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RLMSupport.swift; path = Realm/RLMSupport.swift; sourceTree = ""; }; 50E114F81ABC137A00F13000 /* YepServiceSync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepServiceSync.swift; path = Services/YepServiceSync.swift; sourceTree = ""; }; @@ -404,6 +408,7 @@ 503315991AC101830008A209 /* ChatLeftText */, 5033159E1AC101CB0008A209 /* ChatRightText */, 50CDBE441ACA9B4600459CE0 /* ChatRightImage */, + 50CDBE4B1ACBAD3700459CE0 /* ChatLeftImageCell */, ); name = Cells; sourceTree = ""; @@ -604,6 +609,15 @@ name = ChatRightImage; sourceTree = ""; }; + 50CDBE4B1ACBAD3700459CE0 /* ChatLeftImageCell */ = { + isa = PBXGroup; + children = ( + 50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */, + 50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */, + ); + name = ChatLeftImageCell; + sourceTree = ""; + }; 50E114F51ABBF9D100F13000 /* Realm */ = { isa = PBXGroup; children = ( @@ -748,6 +762,7 @@ 502AE5591AB932D5005BD199 /* ProfileSectionHeaderReusableView.xib in Resources */, 502AE5411AB88862005BD199 /* SkillRankCell.xib in Resources */, 502AE5541AB93215005BD199 /* ProfileFooterCell.xib in Resources */, + 50CDBE4A1ACBAD3200459CE0 /* ChatLeftImageCell.xib in Resources */, 0A8F54B61AB67D11004AD60E /* Main.storyboard in Resources */, 5033159D1AC101C80008A209 /* ChatRightTextCell.xib in Resources */, 50CDBE431ACA9B4200459CE0 /* ChatRightImageCell.xib in Resources */, @@ -874,6 +889,7 @@ 502AE51E1AB712D2005BD199 /* RegisterPickNameViewController.swift in Sources */, 50E114F91ABC137A00F13000 /* YepServiceSync.swift in Sources */, 5023DE2A1AB685BA00B3EE96 /* ContactsViewController.swift in Sources */, + 50CDBE491ACBAD3200459CE0 /* ChatLeftImageCell.swift in Sources */, 5033159C1AC101C80008A209 /* ChatRightTextCell.swift in Sources */, 5023DE561AB6CA1000B3EE96 /* AvatarCache.swift in Sources */, 5023DE371AB6979600B3EE96 /* ConversationCell.swift in Sources */, diff --git a/Yep/Caches/ImageCache.swift b/Yep/Caches/ImageCache.swift index 6ff80a04..20581b0c 100644 --- a/Yep/Caches/ImageCache.swift +++ b/Yep/Caches/ImageCache.swift @@ -15,15 +15,8 @@ class ImageCache { var cache = NSCache() func rightMessageImageOfMessage(message: Message, completion: (UIImage) -> ()) { - let fileName = message.localAttachmentName - if fileName.isEmpty { - completion(UIImage()) - - return - } - - let imageKey = "image-\(fileName)" + let imageKey = "image-\(message.messageID)-\(message.localAttachmentName)--\(message.attachmentURLString)" // 先看看缓存 if let image = cache.objectForKey(imageKey) as? UIImage { @@ -31,54 +24,60 @@ class ImageCache { } else { + let fileName = message.localAttachmentName + let attachmentURLString = message.attachmentURLString + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { - if - let imageFileURL = NSFileManager.yepMessageImageURLWithName(fileName), - let image = UIImage(contentsOfFile: imageFileURL.path!) { - let rightMessageImage = image.bubbleImageWithTailDirection(.Right, size: CGSize(width: 200, height: 100)) + if !fileName.isEmpty { + if + let imageFileURL = NSFileManager.yepMessageImageURLWithName(fileName), + let image = UIImage(contentsOfFile: imageFileURL.path!) { - self.cache.setObject(rightMessageImage, forKey: imageKey) + let rightMessageImage = image.bubbleImageWithTailDirection(.Right, size: CGSize(width: 200, height: 100)) - completion(rightMessageImage) - - } else { - // TODO: 下载 + self.cache.setObject(rightMessageImage, forKey: imageKey) + + completion(rightMessageImage) - let attachmentURLString = message.attachmentURLString - - if attachmentURLString.isEmpty { - completion(UIImage()) - - return - } - - let url = NSURL(string: attachmentURLString)! - - if let data = NSData(contentsOfURL: url) { - let image = UIImage(data: data)! - - let messageImageName = NSUUID().UUIDString - - let messageImageURL = NSFileManager.saveMessageImageData(data, withName: messageImageName) - - dispatch_async(dispatch_get_main_queue()) { - let realm = message.realm - realm.beginWriteTransaction() - message.localAttachmentName = messageImageName - realm.commitWriteTransaction() - } - - let rightMessageImage = image.bubbleImageWithTailDirection(.Right, size: CGSize(width: 200, height: 100)) - - self.cache.setObject(rightMessageImage, forKey: imageKey) - - completion(rightMessageImage) + return } } + // TODO: 下载 + + if attachmentURLString.isEmpty { + completion(UIImage()) + + return + } + + let url = NSURL(string: attachmentURLString)! + + if let data = NSData(contentsOfURL: url) { + let image = UIImage(data: data)! + + let messageImageName = NSUUID().UUIDString + + let messageImageURL = NSFileManager.saveMessageImageData(data, withName: messageImageName) + + dispatch_async(dispatch_get_main_queue()) { + let realm = message.realm + realm.beginWriteTransaction() + message.localAttachmentName = messageImageName + realm.commitWriteTransaction() + } + + let rightMessageImage = image.bubbleImageWithTailDirection(.Right, size: CGSize(width: 200, height: 100)) + + self.cache.setObject(rightMessageImage, forKey: imageKey) + + completion(rightMessageImage) + } } + + } } } \ No newline at end of file diff --git a/Yep/Realm/Models.swift b/Yep/Realm/Models.swift index c9d20b81..50435025 100644 --- a/Yep/Realm/Models.swift +++ b/Yep/Realm/Models.swift @@ -95,11 +95,32 @@ enum MessageDownloadState: Int { case Downloaded = 2 // 已下载 } -enum MessageMediaType: Int { - case Text = 0 - case Image = 1 - case Video = 2 - case Audio = 3 +enum MessageMediaType: Int, Printable { + case Text = 0 + case Image = 1 + case Video = 2 + case Audio = 3 + case Sticker = 4 + case Location = 5 + + var description: String { + get { + switch self { + case Text: + return "text" + case Image: + return "image" + case Video: + return "video" + case Audio: + return "audio" + case Sticker: + return "sticker" + case Location: + return "location" + } + } + } } enum MessageSendState: Int { diff --git a/Yep/Services/YepService.swift b/Yep/Services/YepService.swift index 194f9a53..1ce7e06e 100644 --- a/Yep/Services/YepService.swift +++ b/Yep/Services/YepService.swift @@ -615,7 +615,7 @@ func sendMessageWithMediaType(mediaType: MessageMediaType, #text: String?, #atta var messageInfo: JSONDictionary = [ "recipient_id": recipientID, "recipient_type": recipientType, - "media_type": mediaType.rawValue, + "media_type": mediaType.description, ] if let text = text { diff --git a/Yep/Services/YepServiceSync.swift b/Yep/Services/YepServiceSync.swift index 247745ee..0977904d 100644 --- a/Yep/Services/YepServiceSync.swift +++ b/Yep/Services/YepServiceSync.swift @@ -488,9 +488,21 @@ func syncMessageWithMessageInfo(messageInfo: JSONDictionary, inRealm realm: RLMR if let attachments = messageInfo["attachments"] as? [JSONDictionary] { for attachmentInfo in attachments { - // TODO: 若未来没有 Qiniu,需要改动 - // S3: fallback file,尽量用它 - if let fallbackFileInfo = attachmentInfo["fallback_file"] as? JSONDictionary { + + // S3: normal file + if let normalFileInfo = attachmentInfo["file"] as? JSONDictionary { + if let fileURLString = normalFileInfo["url"] as? String { + if let kind = attachmentInfo["kind"] as? String { + if kind == "thumbnail" { + message.thumbnailURLString = fileURLString + } else { + message.attachmentURLString = fileURLString + } + } + } + } + /* + else if let fallbackFileInfo = attachmentInfo["fallback_file"] as? JSONDictionary { if let fileURLString = fallbackFileInfo["url"] as? String { if let kind = attachmentInfo["kind"] as? String { if kind == "thumbnail" { @@ -500,30 +512,27 @@ func syncMessageWithMessageInfo(messageInfo: JSONDictionary, inRealm realm: RLMR } } } - - } else { - // Qiniu: normal file, Qiniu - if let normalFileInfo = attachmentInfo["file"] as? JSONDictionary { - if let fileURLString = normalFileInfo["url"] as? String { - if let kind = attachmentInfo["kind"] as? String { - if kind == "thumbnail" { - message.thumbnailURLString = fileURLString - } else { - message.attachmentURLString = fileURLString - } - } - } - } } + */ } if let mediaType = messageInfo["media_type"] as? String { - if mediaType == "image" { + + switch mediaType { + case MessageMediaType.Text.description: + message.mediaType = MessageMediaType.Text.rawValue + case MessageMediaType.Image.description: message.mediaType = MessageMediaType.Image.rawValue - } else if mediaType == "video" { + case MessageMediaType.Video.description: message.mediaType = MessageMediaType.Video.rawValue - } else if mediaType == "audio" { + case MessageMediaType.Audio.description: message.mediaType = MessageMediaType.Audio.rawValue + case MessageMediaType.Sticker.description: + message.mediaType = MessageMediaType.Sticker.rawValue + case MessageMediaType.Location.description: + message.mediaType = MessageMediaType.Location.rawValue + default: + break } // TODO: 若有更多的 Media Type } diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index 614b39a7..0734f2f0 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -59,6 +59,7 @@ class ConversationViewController: UIViewController { let chatLeftTextCellIdentifier = "ChatLeftTextCell" let chatRightTextCellIdentifier = "ChatRightTextCell" + let chatLeftImageCellIdentifier = "ChatLeftImageCell" let chatRightImageCellIdentifier = "ChatRightImageCell" @@ -100,6 +101,7 @@ class ConversationViewController: UIViewController { conversationCollectionView.registerNib(UINib(nibName: chatLeftTextCellIdentifier, bundle: nil), forCellWithReuseIdentifier: chatLeftTextCellIdentifier) conversationCollectionView.registerNib(UINib(nibName: chatRightTextCellIdentifier, bundle: nil), forCellWithReuseIdentifier: chatRightTextCellIdentifier) + conversationCollectionView.registerNib(UINib(nibName: chatLeftImageCellIdentifier, bundle: nil), forCellWithReuseIdentifier: chatLeftImageCellIdentifier) conversationCollectionView.registerNib(UINib(nibName: chatRightImageCellIdentifier, bundle: nil), forCellWithReuseIdentifier: chatRightImageCellIdentifier) conversationCollectionView.bounces = true @@ -440,17 +442,37 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi if let sender = message.fromFriend { if sender.friendState != UserFriendState.Me.rawValue { - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftTextCellIdentifier, forIndexPath: indexPath) as! ChatLeftTextCell + switch message.mediaType { + case MessageMediaType.Image.rawValue: + let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftImageCellIdentifier, forIndexPath: indexPath) as! ChatLeftImageCell - cell.textContentLabel.text = message.textContent - - AvatarCache.sharedInstance.roundAvatarOfUser(sender, withRadius: 40 * 0.5) { roundImage in - dispatch_async(dispatch_get_main_queue()) { - cell.avatarImageView.image = roundImage + AvatarCache.sharedInstance.roundAvatarOfUser(sender, withRadius: 40 * 0.5) { roundImage in + dispatch_async(dispatch_get_main_queue()) { + cell.avatarImageView.image = roundImage + } } - } - return cell + ImageCache.sharedInstance.rightMessageImageOfMessage(message) { image in + dispatch_async(dispatch_get_main_queue()) { + cell.messageImageView.image = image + } + } + + return cell + + default: + let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftTextCellIdentifier, forIndexPath: indexPath) as! ChatLeftTextCell + + cell.textContentLabel.text = message.textContent + + AvatarCache.sharedInstance.roundAvatarOfUser(sender, withRadius: 40 * 0.5) { roundImage in + dispatch_async(dispatch_get_main_queue()) { + cell.avatarImageView.image = roundImage + } + } + + return cell + } } else { diff --git a/Yep/Views/Cells/ChatLeftImage/ChatLeftImageCell.swift b/Yep/Views/Cells/ChatLeftImage/ChatLeftImageCell.swift new file mode 100644 index 00000000..f063b50d --- /dev/null +++ b/Yep/Views/Cells/ChatLeftImage/ChatLeftImageCell.swift @@ -0,0 +1,22 @@ +// +// ChatLeftImageCell.swift +// Yep +// +// Created by NIX on 15/4/1. +// Copyright (c) 2015年 Catch Inc. All rights reserved. +// + +import UIKit + +class ChatLeftImageCell: UICollectionViewCell { + + @IBOutlet weak var avatarImageView: UIImageView! + + @IBOutlet weak var messageImageView: UIImageView! + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + +} diff --git a/Yep/Views/Cells/ChatLeftImage/ChatLeftImageCell.xib b/Yep/Views/Cells/ChatLeftImage/ChatLeftImageCell.xib new file mode 100644 index 00000000..85ae3701 --- /dev/null +++ b/Yep/Views/Cells/ChatLeftImage/ChatLeftImageCell.xib @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +