mirror of
https://github.com/wahyd4/Yep.git
synced 2026-08-26 21:26:00 +10:00
add ChatLeftImageCell; MediaType; better logic for rightMessageImageOfMessage
This commit is contained in:
@@ -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 = "<group>"; };
|
||||
50CDBE411ACA9B4200459CE0 /* ChatRightImageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatRightImageCell.xib; path = Views/Cells/ChatRightImage/ChatRightImageCell.xib; sourceTree = "<group>"; };
|
||||
50CDBE451ACA9F2200459CE0 /* ImageCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageCache.swift; path = Caches/ImageCache.swift; sourceTree = "<group>"; };
|
||||
50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatLeftImageCell.swift; path = Views/Cells/ChatLeftImage/ChatLeftImageCell.swift; sourceTree = "<group>"; };
|
||||
50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatLeftImageCell.xib; path = Views/Cells/ChatLeftImage/ChatLeftImageCell.xib; sourceTree = "<group>"; };
|
||||
50E114F31ABBF9CC00F13000 /* Models.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Models.swift; path = Realm/Models.swift; sourceTree = "<group>"; };
|
||||
50E114F61ABBFA7000F13000 /* RLMSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RLMSupport.swift; path = Realm/RLMSupport.swift; sourceTree = "<group>"; };
|
||||
50E114F81ABC137A00F13000 /* YepServiceSync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepServiceSync.swift; path = Services/YepServiceSync.swift; sourceTree = "<group>"; };
|
||||
@@ -404,6 +408,7 @@
|
||||
503315991AC101830008A209 /* ChatLeftText */,
|
||||
5033159E1AC101CB0008A209 /* ChatRightText */,
|
||||
50CDBE441ACA9B4600459CE0 /* ChatRightImage */,
|
||||
50CDBE4B1ACBAD3700459CE0 /* ChatLeftImageCell */,
|
||||
);
|
||||
name = Cells;
|
||||
sourceTree = "<group>";
|
||||
@@ -604,6 +609,15 @@
|
||||
name = ChatRightImage;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
50CDBE4B1ACBAD3700459CE0 /* ChatLeftImageCell */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */,
|
||||
50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */,
|
||||
);
|
||||
name = ChatLeftImageCell;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
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 */,
|
||||
|
||||
+45
-46
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-5
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7528.3" systemVersion="14C1514" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7518.3"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX" customClass="ChatLeftImageCell" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="298" height="144"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="298" height="144"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="m2x-3M-xx2" userLabel="Avatar Image View">
|
||||
<rect key="frame" x="15" y="20" width="40" height="40"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="m2x-3M-xx2" secondAttribute="height" multiplier="1:1" id="CIb-Am-uCH"/>
|
||||
<constraint firstAttribute="width" constant="40" id="JD9-KR-rN4"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="2Dg-WB-LbN" userLabel="Message Image View">
|
||||
<rect key="frame" x="65" y="10" width="173" height="124"/>
|
||||
<color key="backgroundColor" red="0.0" green="1" blue="0.50196081400000003" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="2Dg-WB-LbN" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="10" id="2kd-sa-eEC"/>
|
||||
<constraint firstItem="2Dg-WB-LbN" firstAttribute="leading" secondItem="m2x-3M-xx2" secondAttribute="trailing" constant="10" id="XGu-Kt-JG7"/>
|
||||
<constraint firstItem="2Dg-WB-LbN" firstAttribute="top" secondItem="m2x-3M-xx2" secondAttribute="top" constant="-10" id="Z28-JS-Ei8"/>
|
||||
<constraint firstAttribute="bottom" secondItem="2Dg-WB-LbN" secondAttribute="bottom" constant="10" id="aYs-Kl-RF4"/>
|
||||
<constraint firstItem="m2x-3M-xx2" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" constant="15" id="jaW-UR-cHe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="2Dg-WB-LbN" secondAttribute="trailing" constant="60" id="pJy-mX-Usl"/>
|
||||
</constraints>
|
||||
<size key="customSize" width="298" height="144"/>
|
||||
<connections>
|
||||
<outlet property="avatarImageView" destination="m2x-3M-xx2" id="YKv-gh-cr8"/>
|
||||
<outlet property="messageImageView" destination="2Dg-WB-LbN" id="JaH-m0-woi"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="288" y="408"/>
|
||||
</collectionViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
Reference in New Issue
Block a user