Compare commits
54 Commits
signal-mas
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26fb5cbcf4 | ||
|
|
c8262eee36 | ||
|
|
184f53b07b | ||
|
|
ed9858bd6d | ||
|
|
9dffc05aa7 | ||
|
|
cb5c4facbc | ||
|
|
84d1b659f3 | ||
|
|
b73b5d9983 | ||
|
|
6a30411791 | ||
|
|
8703ce020c | ||
|
|
fcbbfdc43f | ||
|
|
bc976a04d9 | ||
|
|
43f6e75bbf | ||
|
|
59ea2b6920 | ||
|
|
dee758a3ff | ||
|
|
82482a1fc5 | ||
|
|
7c2cec63f9 | ||
|
|
91fbb4dce7 | ||
|
|
0d8fabe142 | ||
|
|
4049f54789 | ||
|
|
54ae40b07a | ||
|
|
bcf0ac6e1f | ||
|
|
e70cec697f | ||
|
|
b22b7a4caf | ||
|
|
b8b3fb9122 | ||
|
|
5fc12f5cba | ||
|
|
4cad607ae2 | ||
|
|
597670e446 | ||
|
|
881ddddeb4 | ||
|
|
32395453ff | ||
|
|
5c6dce5a04 | ||
|
|
3d248e4af0 | ||
|
|
6bbef1949b | ||
|
|
1031a89858 | ||
|
|
21d877492e | ||
|
|
5670accd2c | ||
|
|
d138d4f3a3 | ||
|
|
cddbbf2c75 | ||
|
|
104ba0e023 | ||
|
|
a27fa1091e | ||
|
|
7446b63cbb | ||
|
|
73482f6ace | ||
|
|
2dad6e3036 | ||
|
|
99971a8d38 | ||
|
|
da7203dee2 | ||
|
|
88e16ac830 | ||
|
|
41dddfea3a | ||
|
|
ebea4ef0b8 | ||
|
|
f115194efa | ||
|
|
06e7c2bec9 | ||
|
|
6dded2cce9 | ||
|
|
f03bac13a0 | ||
|
|
33b81ca6b0 | ||
|
|
752edc4f0f |
@ -58,9 +58,7 @@
|
||||
88A25FCA19D8E01A00924534 /* JSQMessagesCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F8B19D8E01A00924534 /* JSQMessagesCollectionView.m */; };
|
||||
88A25FCB19D8E01A00924534 /* JSQMessagesCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F8D19D8E01A00924534 /* JSQMessagesCollectionViewCell.m */; };
|
||||
88A25FCC19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F8F19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m */; };
|
||||
88A25FCD19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88A25F9019D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib */; };
|
||||
88A25FCE19D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9219D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m */; };
|
||||
88A25FCF19D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88A25F9319D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib */; };
|
||||
88A25FD019D8E01A00924534 /* JSQMessagesComposerTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9519D8E01A00924534 /* JSQMessagesComposerTextView.m */; };
|
||||
88A25FD119D8E01A00924534 /* JSQMessagesInputToolbar.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9719D8E01A00924534 /* JSQMessagesInputToolbar.m */; };
|
||||
88A25FD219D8E01A00924534 /* JSQMessagesLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 88A25F9919D8E01A00924534 /* JSQMessagesLabel.m */; };
|
||||
@ -105,6 +103,23 @@
|
||||
88C4583019F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C4582F19F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m */; };
|
||||
88E4D7131A0DBD6B000CC061 /* JSQMessages.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8841B88719F4988800EA16B6 /* JSQMessages.strings */; };
|
||||
94A4FA20C2FBD0D62614D5A8 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 97E6750B77E8A7042BA0754B /* libPods.a */; };
|
||||
FC15B7A91A1E880900F59801 /* JSQCallCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC15B7A81A1E880900F59801 /* JSQCallCollectionViewCell.xib */; };
|
||||
FC15B7B01A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC15B7AE1A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib */; };
|
||||
FC15B7B11A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC15B7AF1A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib */; };
|
||||
FC4FA03A1A1E1BD100DA100A /* JSQCall.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA0391A1E1BD100DA100A /* JSQCall.m */; };
|
||||
FC4FA03D1A1E81AF00DA100A /* JSQCallCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FC4FA03C1A1E81AF00DA100A /* JSQCallCollectionViewCell.m */; };
|
||||
FCA52AEF1A2B6ECE00CCADFA /* call_missed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AEE1A2B6ECE00CCADFA /* call_missed@2x.png */; };
|
||||
FCA52AF51A2B6FAE00CCADFA /* call_canceled@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF11A2B6FAE00CCADFA /* call_canceled@2x.png */; };
|
||||
FCA52AF61A2B6FAE00CCADFA /* call_failed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF21A2B6FAE00CCADFA /* call_failed@2x.png */; };
|
||||
FCA52AF71A2B6FAE00CCADFA /* call_incoming@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF31A2B6FAE00CCADFA /* call_incoming@2x.png */; };
|
||||
FCA52AF81A2B6FAE00CCADFA /* call_outgoing@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52AF41A2B6FAE00CCADFA /* call_outgoing@2x.png */; };
|
||||
FCA52B021A2B9F0E00CCADFA /* warning_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52B001A2B9F0E00CCADFA /* warning_white@2x.png */; };
|
||||
FCA52B031A2B9F0E00CCADFA /* error_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FCA52B011A2B9F0E00CCADFA /* error_white@2x.png */; };
|
||||
FCFA5E131A29FC1000C8E32E /* JSQDisplayedMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E121A29FC1000C8E32E /* JSQDisplayedMessage.m */; };
|
||||
FCFA5E161A29FE3B00C8E32E /* JSQInfoMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E151A29FE3B00C8E32E /* JSQInfoMessage.m */; };
|
||||
FCFA5E191A2A044500C8E32E /* JSQErrorMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E181A2A044500C8E32E /* JSQErrorMessage.m */; };
|
||||
FCFA5E1D1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FCFA5E1B1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m */; };
|
||||
FCFA5E1E1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FCFA5E1C1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -219,10 +234,8 @@
|
||||
88A25F8D19D8E01A00924534 /* JSQMessagesCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCollectionViewCell.m; sourceTree = "<group>"; };
|
||||
88A25F8E19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesCollectionViewCellIncoming.h; sourceTree = "<group>"; };
|
||||
88A25F8F19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCollectionViewCellIncoming.m; sourceTree = "<group>"; };
|
||||
88A25F9019D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellIncoming.xib; sourceTree = "<group>"; };
|
||||
88A25F9119D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesCollectionViewCellOutgoing.h; sourceTree = "<group>"; };
|
||||
88A25F9219D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesCollectionViewCellOutgoing.m; sourceTree = "<group>"; };
|
||||
88A25F9319D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellOutgoing.xib; sourceTree = "<group>"; };
|
||||
88A25F9419D8E01A00924534 /* JSQMessagesComposerTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesComposerTextView.h; sourceTree = "<group>"; };
|
||||
88A25F9519D8E01A00924534 /* JSQMessagesComposerTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesComposerTextView.m; sourceTree = "<group>"; };
|
||||
88A25F9619D8E01A00924534 /* JSQMessagesInputToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesInputToolbar.h; sourceTree = "<group>"; };
|
||||
@ -277,7 +290,30 @@
|
||||
88C4582E19F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesMediaViewBubbleImageMasker.h; sourceTree = "<group>"; };
|
||||
88C4582F19F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaViewBubbleImageMasker.m; sourceTree = "<group>"; };
|
||||
97E6750B77E8A7042BA0754B /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FC15B7A81A1E880900F59801 /* JSQCallCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQCallCollectionViewCell.xib; sourceTree = "<group>"; };
|
||||
FC15B7AE1A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellIncoming.xib; sourceTree = "<group>"; };
|
||||
FC15B7AF1A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQMessagesCollectionViewCellOutgoing.xib; sourceTree = "<group>"; };
|
||||
FC4FA0381A1E1BD100DA100A /* JSQCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQCall.h; sourceTree = "<group>"; };
|
||||
FC4FA0391A1E1BD100DA100A /* JSQCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQCall.m; sourceTree = "<group>"; };
|
||||
FC4FA03B1A1E81AF00DA100A /* JSQCallCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQCallCollectionViewCell.h; sourceTree = "<group>"; };
|
||||
FC4FA03C1A1E81AF00DA100A /* JSQCallCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQCallCollectionViewCell.m; sourceTree = "<group>"; };
|
||||
FC5C727E4CCDA2B95A7BA30C /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
FCA52AEE1A2B6ECE00CCADFA /* call_missed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "call_missed@2x.png"; path = "../../JSQMessagesDemo/call_missed@2x.png"; sourceTree = "<group>"; };
|
||||
FCA52AF11A2B6FAE00CCADFA /* call_canceled@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_canceled@2x.png"; sourceTree = "<group>"; };
|
||||
FCA52AF21A2B6FAE00CCADFA /* call_failed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_failed@2x.png"; sourceTree = "<group>"; };
|
||||
FCA52AF31A2B6FAE00CCADFA /* call_incoming@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_incoming@2x.png"; sourceTree = "<group>"; };
|
||||
FCA52AF41A2B6FAE00CCADFA /* call_outgoing@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "call_outgoing@2x.png"; sourceTree = "<group>"; };
|
||||
FCA52B001A2B9F0E00CCADFA /* warning_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "warning_white@2x.png"; sourceTree = "<group>"; };
|
||||
FCA52B011A2B9F0E00CCADFA /* error_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "error_white@2x.png"; sourceTree = "<group>"; };
|
||||
FCFA5E111A29FC1000C8E32E /* JSQDisplayedMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQDisplayedMessage.h; sourceTree = "<group>"; };
|
||||
FCFA5E121A29FC1000C8E32E /* JSQDisplayedMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQDisplayedMessage.m; sourceTree = "<group>"; };
|
||||
FCFA5E141A29FE3B00C8E32E /* JSQInfoMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQInfoMessage.h; sourceTree = "<group>"; };
|
||||
FCFA5E151A29FE3B00C8E32E /* JSQInfoMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQInfoMessage.m; sourceTree = "<group>"; };
|
||||
FCFA5E171A2A044500C8E32E /* JSQErrorMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQErrorMessage.h; sourceTree = "<group>"; };
|
||||
FCFA5E181A2A044500C8E32E /* JSQErrorMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQErrorMessage.m; sourceTree = "<group>"; };
|
||||
FCFA5E1A1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQDisplayedMessageCollectionViewCell.h; sourceTree = "<group>"; };
|
||||
FCFA5E1B1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQDisplayedMessageCollectionViewCell.m; sourceTree = "<group>"; };
|
||||
FCFA5E1C1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JSQDisplayedMessageCollectionViewCell.xib; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -339,6 +375,7 @@
|
||||
88445B3A19E0C0B10014F889 /* XCTest.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
path = ../..;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8841B88219F4983C00EA16B6 /* Strings */ = {
|
||||
@ -354,7 +391,6 @@
|
||||
children = (
|
||||
886C33FE19F45E30006B4997 /* JSQMessagesViewController.podspec */,
|
||||
88A25F3E19D8E01A00924534 /* JSQMessagesViewController */,
|
||||
636A8663AEEE5C37B65C515D /* Frameworks */,
|
||||
88A25F2B19D8DF2500924534 /* JSQMessagesDemo */,
|
||||
88A25F1E19D8DEC500924534 /* JSQMessagesTests */,
|
||||
2BBEF3CD91C31A49E5FF9E3C /* Pods */,
|
||||
@ -434,6 +470,8 @@
|
||||
88A25F3F19D8E01A00924534 /* Assets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FCA52AFB1A2B9BAD00CCADFA /* InfoError */,
|
||||
FCA52AF01A2B6F8A00CCADFA /* Calls */,
|
||||
8841B88219F4983C00EA16B6 /* Strings */,
|
||||
8861666C19F492B70025B958 /* JSQMessagesAssets.bundle */,
|
||||
);
|
||||
@ -524,6 +562,14 @@
|
||||
88A25F8619D8E01A00924534 /* JSQPhotoMediaItem.m */,
|
||||
886C33FB19F4371E006B4997 /* JSQVideoMediaItem.h */,
|
||||
886C33FC19F4371E006B4997 /* JSQVideoMediaItem.m */,
|
||||
FC4FA0381A1E1BD100DA100A /* JSQCall.h */,
|
||||
FC4FA0391A1E1BD100DA100A /* JSQCall.m */,
|
||||
FCFA5E111A29FC1000C8E32E /* JSQDisplayedMessage.h */,
|
||||
FCFA5E121A29FC1000C8E32E /* JSQDisplayedMessage.m */,
|
||||
FCFA5E141A29FE3B00C8E32E /* JSQInfoMessage.h */,
|
||||
FCFA5E151A29FE3B00C8E32E /* JSQInfoMessage.m */,
|
||||
FCFA5E171A2A044500C8E32E /* JSQErrorMessage.h */,
|
||||
FCFA5E181A2A044500C8E32E /* JSQErrorMessage.m */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
@ -531,6 +577,7 @@
|
||||
88A25F8919D8E01A00924534 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
636A8663AEEE5C37B65C515D /* Frameworks */,
|
||||
883C11761A09FB100092A16D /* JSQMessagesCellTextView.h */,
|
||||
883C11771A09FB100092A16D /* JSQMessagesCellTextView.m */,
|
||||
88A25F8A19D8E01A00924534 /* JSQMessagesCollectionView.h */,
|
||||
@ -539,10 +586,10 @@
|
||||
88A25F8D19D8E01A00924534 /* JSQMessagesCollectionViewCell.m */,
|
||||
88A25F8E19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.h */,
|
||||
88A25F8F19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m */,
|
||||
88A25F9019D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib */,
|
||||
FC15B7AE1A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib */,
|
||||
88A25F9119D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.h */,
|
||||
88A25F9219D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.m */,
|
||||
88A25F9319D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib */,
|
||||
FC15B7AF1A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib */,
|
||||
88A25F9419D8E01A00924534 /* JSQMessagesComposerTextView.h */,
|
||||
88A25F9519D8E01A00924534 /* JSQMessagesComposerTextView.m */,
|
||||
88A25F9619D8E01A00924534 /* JSQMessagesInputToolbar.h */,
|
||||
@ -560,6 +607,12 @@
|
||||
88A25FA019D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.h */,
|
||||
88A25FA119D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.m */,
|
||||
88A25FA219D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.xib */,
|
||||
FC4FA03B1A1E81AF00DA100A /* JSQCallCollectionViewCell.h */,
|
||||
FC4FA03C1A1E81AF00DA100A /* JSQCallCollectionViewCell.m */,
|
||||
FC15B7A81A1E880900F59801 /* JSQCallCollectionViewCell.xib */,
|
||||
FCFA5E1A1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.h */,
|
||||
FCFA5E1B1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m */,
|
||||
FCFA5E1C1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -634,6 +687,27 @@
|
||||
path = ViewTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FCA52AF01A2B6F8A00CCADFA /* Calls */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FCA52AF11A2B6FAE00CCADFA /* call_canceled@2x.png */,
|
||||
FCA52AF21A2B6FAE00CCADFA /* call_failed@2x.png */,
|
||||
FCA52AF31A2B6FAE00CCADFA /* call_incoming@2x.png */,
|
||||
FCA52AF41A2B6FAE00CCADFA /* call_outgoing@2x.png */,
|
||||
FCA52AEE1A2B6ECE00CCADFA /* call_missed@2x.png */,
|
||||
);
|
||||
name = Calls;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FCA52AFB1A2B9BAD00CCADFA /* InfoError */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FCA52B001A2B9F0E00CCADFA /* warning_white@2x.png */,
|
||||
FCA52B011A2B9F0E00CCADFA /* error_white@2x.png */,
|
||||
);
|
||||
name = InfoError;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -734,14 +808,23 @@
|
||||
88E4D7131A0DBD6B000CC061 /* JSQMessages.strings in Resources */,
|
||||
886C33FF19F45E30006B4997 /* JSQMessagesViewController.podspec in Resources */,
|
||||
8861666D19F492B70025B958 /* JSQMessagesAssets.bundle in Resources */,
|
||||
88A25FCF19D8E01A00924534 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */,
|
||||
88A25FCD19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */,
|
||||
FC15B7B11A1F6AC800F59801 /* JSQMessagesCollectionViewCellOutgoing.xib in Resources */,
|
||||
88A25FD619D8E01A00924534 /* JSQMessagesToolbarContentView.xib in Resources */,
|
||||
FCA52AF71A2B6FAE00CCADFA /* call_incoming@2x.png in Resources */,
|
||||
88A25F3A19D8DF2500924534 /* Images.xcassets in Resources */,
|
||||
88A25FBC19D8E01A00924534 /* JSQMessagesViewController.xib in Resources */,
|
||||
FCA52AF81A2B6FAE00CCADFA /* call_outgoing@2x.png in Resources */,
|
||||
FCA52B021A2B9F0E00CCADFA /* warning_white@2x.png in Resources */,
|
||||
FCA52AF51A2B6FAE00CCADFA /* call_canceled@2x.png in Resources */,
|
||||
FCA52B031A2B9F0E00CCADFA /* error_white@2x.png in Resources */,
|
||||
FCA52AEF1A2B6ECE00CCADFA /* call_missed@2x.png in Resources */,
|
||||
88A25FD819D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.xib in Resources */,
|
||||
FCFA5E1E1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.xib in Resources */,
|
||||
88A25F3919D8DF2500924534 /* Main.storyboard in Resources */,
|
||||
FC15B7B01A1F6AC800F59801 /* JSQMessagesCollectionViewCellIncoming.xib in Resources */,
|
||||
88A25FD419D8E01A00924534 /* JSQMessagesLoadEarlierHeaderView.xib in Resources */,
|
||||
FC15B7A91A1E880900F59801 /* JSQCallCollectionViewCell.xib in Resources */,
|
||||
FCA52AF61A2B6FAE00CCADFA /* call_failed@2x.png in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -831,6 +914,7 @@
|
||||
8885734D19DE55D000E89D20 /* NSUserDefaults+DemoSettings.m in Sources */,
|
||||
883C11781A09FB100092A16D /* JSQMessagesCellTextView.m in Sources */,
|
||||
88A25FB919D8E01A00924534 /* UIView+JSQMessages.m in Sources */,
|
||||
FCFA5E131A29FC1000C8E32E /* JSQDisplayedMessage.m in Sources */,
|
||||
88A25FCA19D8E01A00924534 /* JSQMessagesCollectionView.m in Sources */,
|
||||
88A25FD219D8E01A00924534 /* JSQMessagesLabel.m in Sources */,
|
||||
88445B4019E1B4470014F889 /* JSQLocationMediaItem.m in Sources */,
|
||||
@ -838,19 +922,23 @@
|
||||
88A25FD519D8E01A00924534 /* JSQMessagesToolbarContentView.m in Sources */,
|
||||
88A25FC119D8E01A00924534 /* JSQMessagesCollectionViewFlowLayout.m in Sources */,
|
||||
8885734A19DE540400E89D20 /* DemoSettingsViewController.m in Sources */,
|
||||
FC4FA03A1A1E1BD100DA100A /* JSQCall.m in Sources */,
|
||||
88A25FC719D8E01A00924534 /* JSQMessagesBubbleImage.m in Sources */,
|
||||
88A25FC519D8E01A00924534 /* JSQMessage.m in Sources */,
|
||||
88A25FD719D8E01A00924534 /* JSQMessagesTypingIndicatorFooterView.m in Sources */,
|
||||
88A25FD319D8E01A00924534 /* JSQMessagesLoadEarlierHeaderView.m in Sources */,
|
||||
FC4FA03D1A1E81AF00DA100A /* JSQCallCollectionViewCell.m in Sources */,
|
||||
88A25FC819D8E01A00924534 /* JSQPhotoMediaItem.m in Sources */,
|
||||
88C4583019F5F7A0008FD427 /* JSQMessagesMediaViewBubbleImageMasker.m in Sources */,
|
||||
88A25FB819D8E01A00924534 /* UIImage+JSQMessages.m in Sources */,
|
||||
88A25FBF19D8E01A00924534 /* JSQMessagesTimestampFormatter.m in Sources */,
|
||||
88A25FE019D8E0C400924534 /* DemoModelData.m in Sources */,
|
||||
FCFA5E1D1A2A08E500C8E32E /* JSQDisplayedMessageCollectionViewCell.m in Sources */,
|
||||
88A25F3C19D8DF2500924534 /* main.m in Sources */,
|
||||
88A25F3719D8DF2500924534 /* AppDelegate.m in Sources */,
|
||||
886FFD2E19E9A65D00EB8485 /* UIDevice+JSQMessages.m in Sources */,
|
||||
88A25FB619D8E01A00924534 /* NSString+JSQMessages.m in Sources */,
|
||||
FCFA5E191A2A044500C8E32E /* JSQErrorMessage.m in Sources */,
|
||||
88A901B619F618B100F99777 /* JSQMediaItem.m in Sources */,
|
||||
88A25FCC19D8E01A00924534 /* JSQMessagesCollectionViewCellIncoming.m in Sources */,
|
||||
88A25FBE19D8E01A00924534 /* JSQMessagesBubbleImageFactory.m in Sources */,
|
||||
@ -858,6 +946,7 @@
|
||||
88A25FB719D8E01A00924534 /* UIColor+JSQMessages.m in Sources */,
|
||||
886C33FD19F4371E006B4997 /* JSQVideoMediaItem.m in Sources */,
|
||||
88A25FBA19D8E01A00924534 /* JSQMessagesKeyboardController.m in Sources */,
|
||||
FCFA5E161A29FE3B00C8E32E /* JSQInfoMessage.m in Sources */,
|
||||
88A25FC019D8E01A00924534 /* JSQMessagesToolbarButtonFactory.m in Sources */,
|
||||
88A25FC219D8E01A00924534 /* JSQMessagesCollectionViewFlowLayoutInvalidationContext.m in Sources */,
|
||||
88A25FE119D8E0C400924534 /* TableViewController.m in Sources */,
|
||||
|
||||
@ -18,6 +18,12 @@
|
||||
|
||||
#import "DemoMessagesViewController.h"
|
||||
|
||||
#import "JSQCallCollectionViewCell.h"
|
||||
#import "JSQCall.h"
|
||||
|
||||
#import "JSQDisplayedMessageCollectionViewCell.h"
|
||||
#import "JSQErrorMessage.h"
|
||||
#import "JSQInfoMessage.h"
|
||||
|
||||
@implementation DemoMessagesViewController
|
||||
|
||||
@ -158,7 +164,7 @@
|
||||
id<JSQMessageMediaData> newMediaData = nil;
|
||||
id newMediaAttachmentCopy = nil;
|
||||
|
||||
if (copyMessage.isMediaMessage) {
|
||||
if ([copyMessage isKindOfClass:[JSQMessage class]]) {
|
||||
/**
|
||||
* Last message was a media message
|
||||
*/
|
||||
@ -396,6 +402,8 @@
|
||||
*/
|
||||
JSQMessage *message = [self.demoData.messages objectAtIndex:indexPath.item];
|
||||
|
||||
if (![message isKindOfClass:[JSQCall class]] || ![message isKindOfClass:[JSQErrorMessage class]] || ![message isKindOfClass:[JSQInfoMessage class]]) return nil;
|
||||
|
||||
if ([message.senderId isEqualToString:self.senderId]) {
|
||||
if (![NSUserDefaults outgoingAvatarSetting]) {
|
||||
return nil;
|
||||
@ -406,8 +414,7 @@
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return [self.demoData.avatars objectForKey:message.senderId];
|
||||
}
|
||||
|
||||
@ -468,38 +475,34 @@
|
||||
/**
|
||||
* Override point for customizing cells
|
||||
*/
|
||||
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||
|
||||
/**
|
||||
* Configure almost *anything* on the cell
|
||||
*
|
||||
* Text colors, label text, label colors, etc.
|
||||
*
|
||||
*
|
||||
* DO NOT set `cell.textView.font` !
|
||||
* Instead, you need to set `self.collectionView.collectionViewLayout.messageBubbleFont` to the font you want in `viewDidLoad`
|
||||
*
|
||||
*
|
||||
* DO NOT manipulate cell layout information!
|
||||
* Instead, override the properties you want on `self.collectionView.collectionViewLayout` from `viewDidLoad`
|
||||
*/
|
||||
|
||||
JSQMessage *msg = [self.demoData.messages objectAtIndex:indexPath.item];
|
||||
|
||||
if (!msg.isMediaMessage) {
|
||||
|
||||
if ([msg.senderId isEqualToString:self.senderId]) {
|
||||
cell.textView.textColor = [UIColor blackColor];
|
||||
}
|
||||
else {
|
||||
cell.textView.textColor = [UIColor whiteColor];
|
||||
|
||||
if ([msg isKindOfClass:[JSQMessage class]])
|
||||
{
|
||||
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||
if (!msg.isMediaMessage) {
|
||||
if ([msg.senderId isEqualToString:self.senderId]) {
|
||||
cell.textView.textColor = [UIColor blackColor];
|
||||
}
|
||||
else {
|
||||
cell.textView.textColor = [UIColor whiteColor];
|
||||
}
|
||||
|
||||
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
|
||||
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
|
||||
}
|
||||
|
||||
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
|
||||
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
|
||||
return cell;
|
||||
|
||||
} else if ([msg isKindOfClass:[JSQCall class]]) {
|
||||
JSQCallCollectionViewCell *cell = (JSQCallCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||
return cell;
|
||||
} else {
|
||||
JSQDisplayedMessageCollectionViewCell * cell = (JSQDisplayedMessageCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||
return cell;
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
@ -521,9 +524,9 @@
|
||||
*
|
||||
* Show a timestamp for every 3rd message
|
||||
*/
|
||||
if (indexPath.item % 3 == 0) {
|
||||
return kJSQMessagesCollectionViewCellLabelHeightDefault;
|
||||
}
|
||||
// if (indexPath.item % 3 == 0) {
|
||||
// return kJSQMessagesCollectionViewCellLabelHeightDefault;
|
||||
// }
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@ -20,6 +20,9 @@
|
||||
|
||||
#import "NSUserDefaults+DemoSettings.h"
|
||||
|
||||
#import "JSQCall.h"
|
||||
#import "JSQInfoMessage.h"
|
||||
#import "JSQErrorMessage.h"
|
||||
|
||||
/**
|
||||
* This is for demo/testing purposes only.
|
||||
@ -99,11 +102,18 @@
|
||||
* You should have a mutable array or orderedSet, or something.
|
||||
*/
|
||||
self.messages = [[NSMutableArray alloc] initWithObjects:
|
||||
[[JSQCall alloc] initWithCallerId:kJSQDemoAvatarIdWoz
|
||||
callerDisplayName:kJSQDemoAvatarDisplayNameWoz
|
||||
date:[NSDate date]
|
||||
status:kCallOutgoing],
|
||||
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
|
||||
date:[NSDate distantPast]
|
||||
text:@"Welcome to JSQMessages: A messaging UI framework for iOS."],
|
||||
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
|
||||
date:[NSDate distantPast]
|
||||
text:@"Welcome to JSQMessages: A messaging UI framework for iOS."],
|
||||
|
||||
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdWoz
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameWoz
|
||||
date:[NSDate distantPast]
|
||||
@ -125,9 +135,42 @@
|
||||
text:@"It is unit-tested, free, open-source, and documented."],
|
||||
|
||||
[[JSQMessage alloc] initWithSenderId:kJSQDemoAvatarIdSquires
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
|
||||
date:[NSDate date]
|
||||
text:@"Now with media messages!"],
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameSquires
|
||||
date:[NSDate date]
|
||||
text:@"Now with media messages!"],
|
||||
[[JSQCall alloc] initWithCallerId:kJSQDemoAvatarIdWoz
|
||||
callerDisplayName:kJSQDemoAvatarDisplayNameWoz
|
||||
date:[NSDate date]
|
||||
status:kCallIncoming],
|
||||
[[JSQCall alloc] initWithCallerId:kJSQDemoAvatarIdWoz
|
||||
callerDisplayName:kJSQDemoAvatarDisplayNameWoz
|
||||
date:[NSDate date]
|
||||
status:kCallMissed],
|
||||
[[JSQInfoMessage alloc] initWithInfoType:JSQInfoMessageTypeSessionDidEnd
|
||||
senderId:kJSQDemoAvatarIdCook
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameCook
|
||||
date:[NSDate date]],
|
||||
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageMissingKeyId
|
||||
senderId:kJSQDemoAvatarIdCook
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameCook
|
||||
date:[NSDate date]],
|
||||
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageInvalidMessage
|
||||
senderId:kJSQDemoAvatarIdCook
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameCook
|
||||
date:[NSDate date]],
|
||||
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageInvalidVersion
|
||||
senderId:kJSQDemoAvatarIdCook
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameCook
|
||||
date:[NSDate date]],
|
||||
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageInvalidKeyException
|
||||
senderId:kJSQDemoAvatarIdCook
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameCook
|
||||
date:[NSDate date]],
|
||||
[[JSQErrorMessage alloc] initWithErrorType:JSQErrorMessageWrongTrustedIdentityKey
|
||||
senderId:kJSQDemoAvatarIdCook
|
||||
senderDisplayName:kJSQDemoAvatarDisplayNameCook
|
||||
date:[NSDate date]],
|
||||
|
||||
nil];
|
||||
|
||||
[self addPhotoMediaMessage];
|
||||
|
||||
BIN
JSQMessagesDemo/call_missed@2x.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
JSQMessagesViewController/Assets/call_canceled@2x.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
JSQMessagesViewController/Assets/call_failed@2x.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
JSQMessagesViewController/Assets/call_incoming@2x.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
JSQMessagesViewController/Assets/call_outgoing@2x.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
JSQMessagesViewController/Assets/error_white@2x.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
JSQMessagesViewController/Assets/warning_white@2x.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
@ -42,6 +42,22 @@
|
||||
*/
|
||||
+ (UIColor *)jsq_messageBubbleLightGrayColor;
|
||||
|
||||
/**
|
||||
* @return A color object containing HSB values similar to Signal gray bubble color.
|
||||
*/
|
||||
+ (UIColor *)jsq_messageBubbleGrayColor;
|
||||
|
||||
/**
|
||||
* @return A color object containing HSB values similar to Signal light blue bubble color.
|
||||
*/
|
||||
+ (UIColor *)jsq_messageBubbleLightBlueColor;
|
||||
|
||||
/**
|
||||
* @return A color object containing HSB values similar to Signal background gray color.
|
||||
*/
|
||||
+ (UIColor *)jsq_messageBackgroundGrayColor;
|
||||
|
||||
|
||||
#pragma mark - Utilities
|
||||
|
||||
/**
|
||||
|
||||
@ -54,6 +54,23 @@
|
||||
alpha:1.0f];
|
||||
}
|
||||
|
||||
+ (UIColor *)jsq_messageBubbleLightBlueColor
|
||||
{
|
||||
return [UIColor colorWithRed:137/255.f green:214/255.f blue:250/255.f alpha:1];
|
||||
}
|
||||
|
||||
+ (UIColor *)jsq_messageBubbleGrayColor
|
||||
{
|
||||
return [UIColor colorWithRed:230/255.f green:230/255.f blue:230/255.f alpha:1];
|
||||
}
|
||||
|
||||
+ (UIColor *)jsq_messageBackgroundGrayColor
|
||||
{
|
||||
return [UIColor colorWithRed:242.f/255 green:242.f/255 blue:242.f/255 alpha:1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - Utilities
|
||||
|
||||
- (UIColor *)jsq_colorByDarkeningColorWithValue:(CGFloat)value
|
||||
|
||||
@ -95,4 +95,5 @@
|
||||
return [UIImage jsq_bubbleImageFromBundleWithName:@"play"];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@ -143,6 +143,28 @@
|
||||
*/
|
||||
@property (copy, nonatomic) NSString *incomingMediaCellIdentifier;
|
||||
|
||||
/*
|
||||
* The collection view cell identifier used to dequeue call collection view cell.
|
||||
*
|
||||
* @discussion This cell identifier's default value is returned by [JSQCallCollectionViewCell cellReuseIdentifier]. Value must not be nil.
|
||||
*
|
||||
* @see JSQCallCollectionViewCell
|
||||
*
|
||||
*/
|
||||
|
||||
@property (copy, nonatomic) NSString *callCellIndentifier;
|
||||
|
||||
/*
|
||||
* The collection view cell identifier used to dequeue displayed message collection view cell.
|
||||
*
|
||||
* @discussion This cell identifier's default value is returned by [JSQDisplayedMessageCollectionViewCell cellReuseIdentifier]. Value must not be nil.
|
||||
*
|
||||
* @see JSQDisplayedMessageCollectionViewCell
|
||||
*
|
||||
*/
|
||||
|
||||
@property (copy, nonatomic) NSString *displayedMessageCellIndentifier;
|
||||
|
||||
/**
|
||||
* Specifies whether or not the view controller should show the typing indicator for an incoming message.
|
||||
*
|
||||
|
||||
@ -42,11 +42,16 @@
|
||||
#import "UIColor+JSQMessages.h"
|
||||
#import "UIDevice+JSQMessages.h"
|
||||
|
||||
#import "JSQCall.h"
|
||||
#import "JSQCallCollectionViewCell.h"
|
||||
|
||||
#import "JSQInfoMessage.h"
|
||||
#import "JSQErrorMessage.h"
|
||||
#import "JSQDisplayedMessageCollectionViewCell.h"
|
||||
|
||||
static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObservingContext;
|
||||
|
||||
|
||||
|
||||
@interface JSQMessagesViewController () <JSQMessagesInputToolbarDelegate,
|
||||
JSQMessagesKeyboardControllerDelegate>
|
||||
|
||||
@ -119,6 +124,7 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
- (void)jsq_configureMessagesViewController
|
||||
{
|
||||
self.view.backgroundColor = [UIColor whiteColor];
|
||||
;
|
||||
|
||||
self.jsq_isObserving = NO;
|
||||
|
||||
@ -142,6 +148,10 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
self.incomingCellIdentifier = [JSQMessagesCollectionViewCellIncoming cellReuseIdentifier];
|
||||
self.incomingMediaCellIdentifier = [JSQMessagesCollectionViewCellIncoming mediaCellReuseIdentifier];
|
||||
|
||||
self.callCellIndentifier = [JSQCallCollectionViewCell cellReuseIdentifier];
|
||||
|
||||
self.displayedMessageCellIndentifier = [JSQDisplayedMessageCollectionViewCell cellReuseIdentifier];
|
||||
|
||||
self.showTypingIndicator = NO;
|
||||
|
||||
self.showLoadEarlierMessagesHeader = NO;
|
||||
@ -340,8 +350,8 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
|
||||
[self.collectionView.collectionViewLayout invalidateLayoutWithContext:[JSQMessagesCollectionViewFlowLayoutInvalidationContext context]];
|
||||
[self.collectionView reloadData];
|
||||
|
||||
if (self.automaticallyScrollsToMostRecentMessage && ![self jsq_isMenuVisible]) {
|
||||
|
||||
if (self.automaticallyScrollsToMostRecentMessage) {
|
||||
[self scrollToBottomAnimated:animated];
|
||||
}
|
||||
}
|
||||
@ -442,14 +452,102 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
NSParameterAssert(messageSenderId != nil);
|
||||
|
||||
BOOL isOutgoingMessage = [messageSenderId isEqualToString:self.senderId];
|
||||
BOOL isMediaMessage = [messageItem isMediaMessage];
|
||||
BOOL isCall = [messageItem messageType] == TSCallAdapter;
|
||||
BOOL isInfoMessage = [messageItem messageType] == TSInfoMessageAdapter;
|
||||
BOOL isErrorMessage = [messageItem messageType] == TSErrorMessageAdapter;
|
||||
|
||||
BOOL isMediaMessage = NO;
|
||||
|
||||
if (!isCall && !isInfoMessage && !isErrorMessage )
|
||||
{
|
||||
isMediaMessage = [messageItem isMediaMessage];
|
||||
}
|
||||
|
||||
|
||||
NSString *cellIdentifier = nil;
|
||||
if (isMediaMessage) {
|
||||
|
||||
if (isCall) {
|
||||
JSQCall * call = (JSQCall*)messageItem;
|
||||
cellIdentifier = self.callCellIndentifier;
|
||||
JSQCallCollectionViewCell * callCell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
|
||||
|
||||
NSString *text = call.date != nil ? [call text] : call.senderDisplayName;
|
||||
NSString *allText = call.date != nil ? [text stringByAppendingString:[call dateText]] : text;
|
||||
const CGFloat fontSize = 14;
|
||||
UIFont *boldFont = [UIFont fontWithName:@"HelveticaNeue-Medium" size:12.0f];
|
||||
UIFont *regularFont = [UIFont fontWithName:@"HelveticaNeue-Light" size:12.0f];
|
||||
UIColor *foregroundColor = [UIColor whiteColor];
|
||||
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
boldFont, NSFontAttributeName, nil];
|
||||
|
||||
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:allText
|
||||
attributes:attrs];
|
||||
if([call date]!=nil) {
|
||||
// Not a group meta message
|
||||
NSDictionary *subAttrs = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
regularFont, NSFontAttributeName, nil];
|
||||
const NSRange range = NSMakeRange([text length],[[call dateText] length]);
|
||||
|
||||
[attributedText setAttributes:subAttrs range:range];
|
||||
BOOL isOutgoing = [self.senderId isEqualToString:call.senderId];
|
||||
if (isOutgoing)
|
||||
{
|
||||
callCell.outgoingCallImageView.image = [call thumbnailImage];
|
||||
} else {
|
||||
callCell.incomingCallImageView.image = [call thumbnailImage];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// A group meta message
|
||||
callCell.incomingCallImageView.image = [call thumbnailImage];
|
||||
}
|
||||
|
||||
callCell.cellLabel.attributedText = attributedText;
|
||||
callCell.cellLabel.lineBreakMode = UILineBreakModeWordWrap;
|
||||
callCell.cellLabel.numberOfLines = 0; // uses as many lines as it needs
|
||||
callCell.cellLabel.textColor = [UIColor colorWithRed:32.f/255.f green:144.f/255.f blue:234.f/255.f alpha:1.f];
|
||||
|
||||
|
||||
callCell.layer.shouldRasterize = YES;
|
||||
callCell.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
return callCell;
|
||||
|
||||
} else if (isInfoMessage) {
|
||||
|
||||
JSQInfoMessage * infoMessage = (JSQInfoMessage*)messageItem;
|
||||
cellIdentifier = self.displayedMessageCellIndentifier;
|
||||
JSQDisplayedMessageCollectionViewCell * infoCell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
|
||||
infoCell.delegate = collectionView;
|
||||
infoCell.cellLabel.text = [infoMessage text];
|
||||
infoCell.cellLabel.textColor = [UIColor darkGrayColor];
|
||||
infoCell.cellLabel.layer.borderColor = [[UIColor colorWithRed:239.f/255.f green:189.f/255.f blue:88.f/255.f alpha:1.0f] CGColor];
|
||||
infoCell.headerImageView.image = [UIImage imageNamed:@"warning_white"];
|
||||
infoCell.layer.shouldRasterize = YES;
|
||||
infoCell.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
return infoCell;
|
||||
|
||||
} else if (isErrorMessage) {
|
||||
|
||||
JSQErrorMessage * errorMessage = (JSQErrorMessage*)messageItem;
|
||||
cellIdentifier = self.displayedMessageCellIndentifier;
|
||||
JSQDisplayedMessageCollectionViewCell * errorCell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
|
||||
errorCell.delegate = collectionView;
|
||||
errorCell.cellLabel.text = [errorMessage text];
|
||||
errorCell.cellLabel.textColor = [UIColor darkGrayColor];
|
||||
errorCell.cellLabel.layer.borderColor = [[UIColor colorWithRed:195.f/255.f green:0 blue:22.f/255.f alpha:1.0f] CGColor];
|
||||
errorCell.headerImageView.image = [UIImage imageNamed:@"error_white"];
|
||||
errorCell.layer.shouldRasterize = YES;
|
||||
errorCell.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
return errorCell;
|
||||
|
||||
} else if (isMediaMessage) {
|
||||
|
||||
cellIdentifier = isOutgoingMessage ? self.outgoingMediaCellIdentifier : self.incomingMediaCellIdentifier;
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
|
||||
cellIdentifier = isOutgoingMessage ? self.outgoingCellIdentifier : self.incomingCellIdentifier;
|
||||
|
||||
}
|
||||
|
||||
JSQMessagesCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
|
||||
@ -511,8 +609,8 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
|
||||
cell.textView.dataDetectorTypes = UIDataDetectorTypeAll;
|
||||
|
||||
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
cell.layer.shouldRasterize = YES;
|
||||
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
|
||||
return cell;
|
||||
}
|
||||
@ -555,8 +653,16 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
|
||||
- (BOOL)collectionView:(JSQMessagesCollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
// disable menu for media messages
|
||||
// disable menu for media messages, calls, info and error messages
|
||||
id<JSQMessageData> messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
|
||||
|
||||
BOOL isErrorOrInfoMessage = messageItem.messageType == TSInfoMessageAdapter || messageItem.messageType == TSErrorMessageAdapter;
|
||||
BOOL isCall = messageItem.messageType == TSCallAdapter;
|
||||
|
||||
if (isErrorOrInfoMessage || isCall) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if ([messageItem isMediaMessage]) {
|
||||
return NO;
|
||||
}
|
||||
@ -626,6 +732,8 @@ static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObserv
|
||||
didTapCellAtIndexPath:(NSIndexPath *)indexPath
|
||||
touchLocation:(CGPoint)touchLocation { }
|
||||
|
||||
|
||||
|
||||
#pragma mark - Input toolbar delegate
|
||||
|
||||
- (void)messagesInputToolbar:(JSQMessagesInputToolbar *)toolbar didPressLeftBarButton:(UIButton *)sender
|
||||
|
||||
@ -73,4 +73,7 @@
|
||||
*/
|
||||
- (JSQMessagesBubbleImage *)incomingMessagesBubbleImageWithColor:(UIColor *)color;
|
||||
|
||||
|
||||
- (JSQMessagesBubbleImage *)outgoingMessageFailedBubbleImageWithColor:(UIColor *)color;
|
||||
|
||||
@end
|
||||
|
||||
@ -83,6 +83,11 @@
|
||||
return [self jsq_messagesBubbleImageWithColor:color flippedForIncoming:YES];
|
||||
}
|
||||
|
||||
- (JSQMessagesBubbleImage *)outgoingMessageFailedBubbleImageWithColor:(UIColor *)color
|
||||
{
|
||||
return [self jsq_messagesBubbleImageWithColor:color flippedForIncoming:NO];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (UIEdgeInsets)jsq_centerPointEdgeInsetsForImageSize:(CGSize)bubbleImageSize
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
+ (UIButton *)defaultAccessoryButtonItem
|
||||
{
|
||||
UIImage *accessoryImage = [UIImage jsq_defaultAccessoryImage];
|
||||
UIImage *normalImage = [accessoryImage jsq_imageMaskedWithColor:[UIColor lightGrayColor]];
|
||||
UIImage *normalImage = [accessoryImage jsq_imageMaskedWithColor:[UIColor colorWithRed:0 green:71/255.f blue:1.0f alpha:1.0f]];
|
||||
UIImage *highlightedImage = [accessoryImage jsq_imageMaskedWithColor:[UIColor darkGrayColor]];
|
||||
|
||||
UIButton *accessoryButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, accessoryImage.size.width, 32.0f)];
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
accessoryButton.contentMode = UIViewContentModeScaleAspectFit;
|
||||
accessoryButton.backgroundColor = [UIColor clearColor];
|
||||
accessoryButton.tintColor = [UIColor lightGrayColor];
|
||||
//accessoryButton.tintColor = [UIColor lightGrayColor];
|
||||
|
||||
return accessoryButton;
|
||||
}
|
||||
@ -51,7 +51,7 @@
|
||||
[sendButton setTitleColor:[[UIColor jsq_messageBubbleBlueColor] jsq_colorByDarkeningColorWithValue:0.1f] forState:UIControlStateHighlighted];
|
||||
[sendButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
|
||||
|
||||
sendButton.titleLabel.font = [UIFont boldSystemFontOfSize:17.0f];
|
||||
sendButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Thin" size:17.0f];
|
||||
sendButton.titleLabel.adjustsFontSizeToFitWidth = YES;
|
||||
sendButton.titleLabel.minimumScaleFactor = 0.85f;
|
||||
sendButton.contentMode = UIViewContentModeCenter;
|
||||
|
||||
@ -33,6 +33,15 @@
|
||||
|
||||
#import "UIImage+JSQMessages.h"
|
||||
|
||||
#import "JSQCall.h"
|
||||
#import "JSQCallCollectionViewCell.h"
|
||||
|
||||
#import "JSQDisplayedMessage.h"
|
||||
#import "JSQDisplayedMessageCollectionViewCell.h"
|
||||
|
||||
#import "JSQErrorMessage.h"
|
||||
#import "JSQInfoMessage.h"
|
||||
|
||||
|
||||
const CGFloat kJSQMessagesCollectionViewCellLabelHeightDefault = 20.0f;
|
||||
const CGFloat kJSQMessagesCollectionViewAvatarSizeDefault = 30.0f;
|
||||
@ -440,38 +449,46 @@ const CGFloat kJSQMessagesCollectionViewAvatarSizeDefault = 30.0f;
|
||||
|
||||
CGSize finalSize = CGSizeZero;
|
||||
|
||||
if ([messageItem isMediaMessage]) {
|
||||
finalSize = [[messageItem media] mediaViewDisplaySize];
|
||||
}
|
||||
else {
|
||||
CGSize avatarSize = [self jsq_avatarSizeForIndexPath:indexPath];
|
||||
if (messageItem.messageType != TSCallAdapter && messageItem.messageType != TSErrorMessageAdapter && messageItem.messageType != TSInfoMessageAdapter) {
|
||||
if ([messageItem isMediaMessage]) {
|
||||
finalSize = [[messageItem media] mediaViewDisplaySize];
|
||||
}
|
||||
else {
|
||||
CGSize avatarSize = [self jsq_avatarSizeForIndexPath:indexPath];
|
||||
|
||||
// from the cell xibs, there is a 2 point space between avatar and bubble
|
||||
CGFloat spacingBetweenAvatarAndBubble = 2.0f;
|
||||
CGFloat horizontalContainerInsets = self.messageBubbleTextViewTextContainerInsets.left + self.messageBubbleTextViewTextContainerInsets.right;
|
||||
CGFloat horizontalFrameInsets = self.messageBubbleTextViewFrameInsets.left + self.messageBubbleTextViewFrameInsets.right;
|
||||
// from the cell xibs, there is a 2 point space between avatar and bubble
|
||||
CGFloat spacingBetweenAvatarAndBubble = 2.0f;
|
||||
CGFloat horizontalContainerInsets = self.messageBubbleTextViewTextContainerInsets.left + self.messageBubbleTextViewTextContainerInsets.right;
|
||||
CGFloat horizontalFrameInsets = self.messageBubbleTextViewFrameInsets.left + self.messageBubbleTextViewFrameInsets.right;
|
||||
|
||||
CGFloat horizontalInsetsTotal = horizontalContainerInsets + horizontalFrameInsets + spacingBetweenAvatarAndBubble;
|
||||
CGFloat maximumTextWidth = self.itemWidth - avatarSize.width - self.messageBubbleLeftRightMargin - horizontalInsetsTotal;
|
||||
CGFloat horizontalInsetsTotal = horizontalContainerInsets + horizontalFrameInsets + spacingBetweenAvatarAndBubble;
|
||||
CGFloat maximumTextWidth = self.itemWidth - avatarSize.width - self.messageBubbleLeftRightMargin - horizontalInsetsTotal;
|
||||
|
||||
CGRect stringRect = [[messageItem text] boundingRectWithSize:CGSizeMake(maximumTextWidth, CGFLOAT_MAX)
|
||||
CGRect stringRect = [[messageItem text] boundingRectWithSize:CGSizeMake(maximumTextWidth, CGFLOAT_MAX)
|
||||
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
|
||||
attributes:@{ NSFontAttributeName : self.messageBubbleFont }
|
||||
context:nil];
|
||||
|
||||
CGSize stringSize = CGRectIntegral(stringRect).size;
|
||||
CGSize stringSize = CGRectIntegral(stringRect).size;
|
||||
|
||||
CGFloat verticalContainerInsets = self.messageBubbleTextViewTextContainerInsets.top + self.messageBubbleTextViewTextContainerInsets.bottom;
|
||||
CGFloat verticalFrameInsets = self.messageBubbleTextViewFrameInsets.top + self.messageBubbleTextViewFrameInsets.bottom;
|
||||
CGFloat verticalContainerInsets = self.messageBubbleTextViewTextContainerInsets.top + self.messageBubbleTextViewTextContainerInsets.bottom;
|
||||
CGFloat verticalFrameInsets = self.messageBubbleTextViewFrameInsets.top + self.messageBubbleTextViewFrameInsets.bottom;
|
||||
|
||||
// add extra 2 points of space, because `boundingRectWithSize:` is slightly off
|
||||
// not sure why. magix. (shrug) if you know, submit a PR
|
||||
CGFloat verticalInsets = verticalContainerInsets + verticalFrameInsets + 2.0f;
|
||||
CGFloat verticalInsets = verticalContainerInsets + verticalFrameInsets + 2.0f;
|
||||
|
||||
// same as above, an extra 2 points of magix
|
||||
CGFloat finalWidth = MAX(stringSize.width + horizontalInsetsTotal, self.bubbleImageAssetWidth) + 2.0f;
|
||||
CGFloat finalWidth = MAX(stringSize.width + horizontalInsetsTotal, self.bubbleImageAssetWidth) + 2.0f;
|
||||
|
||||
finalSize = CGSizeMake(finalWidth, stringSize.height + verticalInsets);
|
||||
finalSize = CGSizeMake(finalWidth, stringSize.height + verticalInsets);
|
||||
}
|
||||
}
|
||||
else if (messageItem.messageType == TSCallAdapter)
|
||||
{
|
||||
finalSize = CGSizeMake(kCallCellWidth, kCallCellHeight);
|
||||
} else {
|
||||
finalSize = CGSizeMake(kDisplayedMessageCellWidth, kDisplayedMessageCellHeight);
|
||||
}
|
||||
|
||||
[self.messageBubbleCache setObject:[NSValue valueWithCGSize:finalSize] forKey:@(messageItem.hash)];
|
||||
|
||||
70
JSQMessagesViewController/Model/JSQCall.h
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// JSQCall.h
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 20/11/14.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "JSQMessageData.h"
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
kCallOutgoing = 1,
|
||||
kCallIncoming = 2,
|
||||
kCallMissed = 3,
|
||||
kGroupUpdateJoin = 4,
|
||||
kGroupUpdateLeft = 5,
|
||||
kGroupUpdate = 6
|
||||
} CallStatus;
|
||||
|
||||
|
||||
|
||||
@interface JSQCall : NSObject <JSQMessageData, NSCoding, NSCopying>
|
||||
|
||||
/*
|
||||
* Returns the string Id of the user who initiated the call
|
||||
*/
|
||||
@property (copy, nonatomic, readonly) NSString *senderId;
|
||||
|
||||
|
||||
/*
|
||||
* Returns the display name for user who initiated the call
|
||||
*/
|
||||
@property (copy, nonatomic, readonly) NSString *senderDisplayName;
|
||||
|
||||
/*
|
||||
* Returns date of the call
|
||||
*/
|
||||
@property (copy, nonatomic, readonly) NSDate *date;
|
||||
|
||||
/*
|
||||
* Returns the call status
|
||||
* @see CallStatus
|
||||
*/
|
||||
@property (nonatomic) CallStatus status;
|
||||
|
||||
/*
|
||||
* Returns message type for adapter
|
||||
*/
|
||||
@property (nonatomic) TSMessageAdapterType messageType;
|
||||
|
||||
/*
|
||||
* User can configure whether a thumbnail is used in the display of this cell or not
|
||||
*/
|
||||
@property (nonatomic) BOOL useThumbnail;
|
||||
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithCallerId:(NSString *)callerId
|
||||
callerDisplayName:(NSString *)callerDisplayName
|
||||
date:(NSDate *)date
|
||||
status:(CallStatus)status;
|
||||
|
||||
-(NSString*)text;
|
||||
-(NSString*)dateText;
|
||||
|
||||
-(UIImage*)thumbnailImage;
|
||||
|
||||
@end
|
||||
171
JSQMessagesViewController/Model/JSQCall.m
Normal file
@ -0,0 +1,171 @@
|
||||
//
|
||||
// JSQCall.m
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 20/11/14.
|
||||
//
|
||||
|
||||
#import "JSQCall.h"
|
||||
|
||||
#import "JSQMessagesTimestampFormatter.h"
|
||||
#import "UIImage+JSQMessages.h"
|
||||
|
||||
@implementation JSQCall
|
||||
|
||||
#pragma mark - Initialzation
|
||||
|
||||
-(instancetype)initWithCallerId:(NSString *)senderId
|
||||
callerDisplayName:(NSString *)senderDisplayName
|
||||
date:(NSDate *)date
|
||||
status:(CallStatus)status
|
||||
{
|
||||
NSParameterAssert(senderId != nil);
|
||||
NSParameterAssert(senderDisplayName != nil);
|
||||
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_senderId = [senderId copy];
|
||||
_senderDisplayName = [senderDisplayName copy];
|
||||
_date = [date copy];
|
||||
_status = status;
|
||||
_messageType = TSCallAdapter;
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(id)init
|
||||
{
|
||||
NSAssert(NO,@"%s is not a valid initializer for %@. Use %@ instead", __PRETTY_FUNCTION__, [self class], NSStringFromSelector(@selector(initWithCallerId:callerDisplayName:date:status:)));
|
||||
return nil;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
_senderId = nil;
|
||||
_senderDisplayName = nil;
|
||||
_date = nil;
|
||||
}
|
||||
|
||||
-(NSString*)text
|
||||
{
|
||||
NSString *name = _senderDisplayName;
|
||||
|
||||
switch (self.status) {
|
||||
case kCallMissed:
|
||||
return [NSString stringWithFormat:@"Missed call from %@. ", name];
|
||||
case kCallIncoming:
|
||||
return [NSString stringWithFormat:@"You received a call from %@. ", name];
|
||||
case kCallOutgoing:
|
||||
return [NSString stringWithFormat:@"You called %@. ", name];
|
||||
default:
|
||||
return nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(NSString*)dateText
|
||||
{
|
||||
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
||||
dateFormatter.timeStyle = NSDateFormatterShortStyle;
|
||||
dateFormatter.dateStyle = NSDateFormatterMediumStyle;
|
||||
dateFormatter.doesRelativeDateFormatting = YES;
|
||||
return [dateFormatter stringFromDate:_date];
|
||||
}
|
||||
|
||||
-(UIImage*)thumbnailImage {
|
||||
// This relies on those assets being in the project
|
||||
if(!_useThumbnail) {
|
||||
return nil;
|
||||
}
|
||||
switch (_status) {
|
||||
case kCallOutgoing:
|
||||
return [UIImage imageNamed:@"statCallOutgoing--blue"];
|
||||
break;
|
||||
case kCallIncoming:
|
||||
case kCallMissed:
|
||||
return [UIImage imageNamed:@"statCallIncoming--blue"];
|
||||
break;
|
||||
case kGroupUpdate:
|
||||
return [UIImage imageNamed:@"statRefreshedGroup--blue"];
|
||||
break;
|
||||
case kGroupUpdateLeft:
|
||||
return [UIImage imageNamed:@"statLeftGroup--blue"];
|
||||
break;
|
||||
case kGroupUpdateJoin:
|
||||
return [UIImage imageNamed:@"statJoinedGroup--blue"];
|
||||
break;
|
||||
default:
|
||||
return nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
-(BOOL)isEqual:(id)object
|
||||
{
|
||||
if (self==object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[self class]])
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
JSQCall * aCall = (JSQCall*)object;
|
||||
|
||||
return [self.senderId isEqualToString:aCall.senderId]
|
||||
&& [self.senderDisplayName isEqualToString:aCall.senderDisplayName]
|
||||
&& ([self.date compare:aCall.date] == NSOrderedSame)
|
||||
&& self.status == aCall.status;
|
||||
}
|
||||
|
||||
-(NSUInteger)hash
|
||||
{
|
||||
return self.senderId.hash ^ self.date.hash;
|
||||
}
|
||||
|
||||
-(NSString*)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: senderId=%@, senderDisplayName=%@, date=%@>",
|
||||
[self class], self.senderId, self.senderDisplayName, self.date];
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
-(instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_senderId = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(senderId))];
|
||||
_senderDisplayName = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(senderDisplayName))];
|
||||
_date = [aDecoder decodeObjectForKey:NSStringFromSelector(@selector(date))];
|
||||
_status = [aDecoder decodeIntegerForKey:NSStringFromSelector(@selector(status))];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder
|
||||
{
|
||||
[aCoder encodeObject:self.senderId forKey:NSStringFromSelector(@selector(senderId))];
|
||||
[aCoder encodeObject:self.senderDisplayName forKey:NSStringFromSelector(@selector(senderDisplayName))];
|
||||
[aCoder encodeObject:self.date forKey:NSStringFromSelector(@selector(date))];
|
||||
[aCoder encodeDouble:self.status forKey:NSStringFromSelector(@selector(status))];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
-(instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return [[[self class] allocWithZone:zone]initWithCallerId:self.senderId
|
||||
callerDisplayName:self.senderDisplayName
|
||||
date:self.date
|
||||
status:self.status];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
44
JSQMessagesViewController/Model/JSQDisplayedMessage.h
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// JSQDisplayedMessage.h
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "JSQMessageData.h"
|
||||
|
||||
/* JSQDisplayed message is the parent class for displaying information to the user
|
||||
* from within the conversation view. Do not use directly :
|
||||
*
|
||||
* @see JSQInfoMessage
|
||||
* @see JSQErrorMessage
|
||||
*
|
||||
*/
|
||||
|
||||
@interface JSQDisplayedMessage : NSObject <JSQMessageData>
|
||||
|
||||
/*
|
||||
* Returns the unique identifier of the person affected by the displayed message
|
||||
*/
|
||||
@property (copy, nonatomic, readonly) NSString *senderId;
|
||||
|
||||
|
||||
/*
|
||||
* Returns the name of the person affected by the displayed message
|
||||
*/
|
||||
@property (copy, nonatomic, readonly) NSString *senderDisplayName;
|
||||
|
||||
/*
|
||||
* Returns date of the displayed message
|
||||
*/
|
||||
@property (copy, nonatomic, readonly) NSDate *date;
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
-(instancetype)initWithSenderId:(NSString*)senderId
|
||||
senderDisplayName:(NSString*)senderDisplayName
|
||||
date:(NSDate*)date;
|
||||
|
||||
@end
|
||||
35
JSQMessagesViewController/Model/JSQDisplayedMessage.m
Normal file
@ -0,0 +1,35 @@
|
||||
//
|
||||
// JSQDisplayedMessage.m
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JSQDisplayedMessage.h"
|
||||
|
||||
@implementation JSQDisplayedMessage
|
||||
|
||||
-(id)init
|
||||
{
|
||||
NSAssert(NO,@"%s is not a valid initializer for %@. Use %@ instead", __PRETTY_FUNCTION__, [self class], NSStringFromSelector(@selector(initWithSenderId:senderDisplayName:date:)));
|
||||
return nil;
|
||||
}
|
||||
|
||||
-(instancetype)initWithSenderId:(NSString*)senderId
|
||||
senderDisplayName:(NSString*)senderDisplayName
|
||||
date:(NSDate*)date
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_senderId = [senderId copy];
|
||||
_senderDisplayName = [senderDisplayName copy];
|
||||
_date = [date copy];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
36
JSQMessagesViewController/Model/JSQErrorMessage.h
Normal file
@ -0,0 +1,36 @@
|
||||
//
|
||||
// JSQErrorMessage.h
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JSQDisplayedMessage.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, JSQErrorMessageType){
|
||||
JSQErrorMessageNoSession,
|
||||
JSQErrorMessageWrongTrustedIdentityKey,
|
||||
JSQErrorMessageInvalidKeyException,
|
||||
JSQErrorMessageMissingKeyId,
|
||||
JSQErrorMessageInvalidMessage,
|
||||
JSQErrorMessageDuplicateMessage,
|
||||
JSQErrorMessageInvalidVersion
|
||||
};
|
||||
|
||||
@interface JSQErrorMessage : JSQDisplayedMessage
|
||||
|
||||
@property (nonatomic) JSQErrorMessageType errorMessageType;
|
||||
|
||||
@property (nonatomic) TSMessageAdapterType messageType;
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithErrorType:(JSQErrorMessageType)messageType
|
||||
senderId:(NSString*)senderId
|
||||
senderDisplayName:(NSString*)senderDisplayName
|
||||
date:(NSDate*)date;
|
||||
|
||||
- (NSString*)text;
|
||||
|
||||
@end
|
||||
75
JSQMessagesViewController/Model/JSQErrorMessage.m
Normal file
@ -0,0 +1,75 @@
|
||||
//
|
||||
// JSQErrorMessage.m
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JSQErrorMessage.h"
|
||||
|
||||
@implementation JSQErrorMessage
|
||||
|
||||
- (instancetype)initWithErrorType:(JSQErrorMessageType)messageType
|
||||
senderId:(NSString *)senderId
|
||||
senderDisplayName:(NSString *)senderDisplayName
|
||||
date:(NSDate *)date
|
||||
{
|
||||
self = [super initWithSenderId:senderId senderDisplayName:senderDisplayName date:date];
|
||||
|
||||
if (self) {
|
||||
_errorMessageType = messageType;
|
||||
_messageType = TSErrorMessageAdapter;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString*)text
|
||||
{
|
||||
switch (self.errorMessageType) {
|
||||
case JSQErrorMessageNoSession:
|
||||
return [NSString stringWithFormat:@"No session error"];
|
||||
break;
|
||||
case JSQErrorMessageWrongTrustedIdentityKey:
|
||||
return [NSString stringWithFormat:@"Error : Wrong trusted identity key for %@.", self.senderDisplayName];
|
||||
break;
|
||||
case JSQErrorMessageInvalidKeyException:
|
||||
return [NSString stringWithFormat:@"Error : Invalid key exception for %@.", self.senderDisplayName];
|
||||
break;
|
||||
case JSQErrorMessageMissingKeyId:
|
||||
return [NSString stringWithFormat:@"Error: Missing key identifier for %@", self.senderDisplayName];
|
||||
break;
|
||||
case JSQErrorMessageInvalidMessage:
|
||||
return [NSString stringWithFormat:@"Error: Invalid message"];
|
||||
break;
|
||||
case JSQErrorMessageDuplicateMessage:
|
||||
return [NSString stringWithFormat:@"Error: Duplicate message"];
|
||||
break;
|
||||
case JSQErrorMessageInvalidVersion:
|
||||
return [NSString stringWithFormat:@"Error: Invalid version for contact %@.", self.senderDisplayName];
|
||||
break;
|
||||
|
||||
default:
|
||||
return nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSUInteger)hash
|
||||
{
|
||||
return self.senderId.hash ^ self.date.hash;
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: senderId=%@, senderDisplayName=%@, date=%@, type=%ld>",
|
||||
[self class], self.senderId, self.senderDisplayName, self.date, self.errorMessageType];
|
||||
}
|
||||
|
||||
-(TSMessageAdapterType)messageType
|
||||
{
|
||||
return TSErrorMessageAdapter;
|
||||
}
|
||||
|
||||
@end
|
||||
31
JSQMessagesViewController/Model/JSQInfoMessage.h
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// JSQInfoMessage.h
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JSQDisplayedMessage.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, JSQInfoMessageType){
|
||||
JSQInfoMessageTypeSessionDidEnd,
|
||||
};
|
||||
|
||||
@interface JSQInfoMessage : JSQDisplayedMessage
|
||||
|
||||
@property (nonatomic) JSQInfoMessageType infoMessageType;
|
||||
|
||||
@property (nonatomic) TSMessageAdapterType messageType;
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (instancetype)initWithInfoType:(JSQInfoMessageType)messageType
|
||||
senderId:(NSString*)senderId
|
||||
senderDisplayName:(NSString*)senderDisplayName
|
||||
date:(NSDate*)date;
|
||||
|
||||
- (NSString*)text;
|
||||
|
||||
|
||||
@end
|
||||
54
JSQMessagesViewController/Model/JSQInfoMessage.m
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// JSQInfoMessage.m
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JSQInfoMessage.h"
|
||||
|
||||
@implementation JSQInfoMessage
|
||||
|
||||
- (instancetype)initWithInfoType:(JSQInfoMessageType)messageType
|
||||
senderId:(NSString *)senderId
|
||||
senderDisplayName:(NSString *)senderDisplayName
|
||||
date:(NSDate *)date
|
||||
{
|
||||
//@discussion: NSParameterAssert() ?
|
||||
|
||||
self = [super initWithSenderId:senderId senderDisplayName:senderDisplayName date:date];
|
||||
|
||||
if (self) {
|
||||
_infoMessageType = messageType;
|
||||
_messageType = TSInfoMessageAdapter;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSString*)text
|
||||
{
|
||||
switch (self.infoMessageType) {
|
||||
case JSQInfoMessageTypeSessionDidEnd:
|
||||
return [NSString stringWithFormat:@"Session with %@ ended.", self.senderDisplayName];
|
||||
break;
|
||||
|
||||
default:
|
||||
return nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(NSUInteger)hash
|
||||
{
|
||||
return self.senderId.hash ^ self.date.hash;
|
||||
}
|
||||
|
||||
-(NSString*)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: senderId=%@, senderDisplayName=%@, date=%@, type=%ld>",
|
||||
[self class], self.senderId, self.senderDisplayName, self.date, self.infoMessageType];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -20,6 +20,15 @@
|
||||
|
||||
#import "JSQMessageData.h"
|
||||
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
kMessageNone,
|
||||
kMessageSent,
|
||||
kMessageRead,
|
||||
kMessageReceived,
|
||||
kMesageFailed
|
||||
} MessageStatus;
|
||||
|
||||
/**
|
||||
* The `JSQMessage` class is a concrete class for message model objects that represents a single user message.
|
||||
* The message can be a text message or media message, depending on how it is initialized.
|
||||
@ -51,6 +60,8 @@
|
||||
*/
|
||||
@property (assign, nonatomic, readonly) BOOL isMediaMessage;
|
||||
|
||||
@property (nonatomic) MessageStatus status;
|
||||
|
||||
/**
|
||||
* Returns the body text of the message, or `nil` if the message is a media message.
|
||||
* That is, if `isMediaMessage` is equal to `YES` then this value will be `nil`.
|
||||
@ -64,6 +75,9 @@
|
||||
@property (copy, nonatomic, readonly) id<JSQMessageMediaData> media;
|
||||
|
||||
|
||||
@property (nonatomic) TSMessageAdapterType messageType;
|
||||
|
||||
|
||||
#pragma mark - Initialization
|
||||
|
||||
/**
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#import "JSQMessage.h"
|
||||
|
||||
|
||||
|
||||
@interface JSQMessage ()
|
||||
|
||||
- (instancetype)initWithSenderId:(NSString *)senderId
|
||||
@ -29,7 +30,6 @@
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@implementation JSQMessage
|
||||
|
||||
#pragma mark - Initialization
|
||||
@ -97,6 +97,7 @@
|
||||
_senderDisplayName = [senderDisplayName copy];
|
||||
_date = [date copy];
|
||||
_isMediaMessage = isMedia;
|
||||
_messageType = TSGenericTextMessageAdapter;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -112,6 +113,7 @@
|
||||
_senderId = nil;
|
||||
_senderDisplayName = nil;
|
||||
_date = nil;
|
||||
_status = kMessageNone;
|
||||
_text = nil;
|
||||
_media = nil;
|
||||
}
|
||||
|
||||
@ -20,6 +20,16 @@
|
||||
|
||||
#import "JSQMessageMediaData.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, TSMessageAdapterType) {
|
||||
TSIncomingMessageAdapter,
|
||||
TSOutgoingMessageAdapter,
|
||||
TSCallAdapter,
|
||||
TSInfoMessageAdapter,
|
||||
TSErrorMessageAdapter,
|
||||
TSMediaAttachmentAdapter,
|
||||
TSGenericTextMessageAdapter, //Used when message direction is unknown (outgoing or incoming)
|
||||
};
|
||||
|
||||
/**
|
||||
* The `JSQMessageData` protocol defines the common interface through which
|
||||
* a `JSQMessagesViewController` and `JSQMessagesCollectionView` interact with message model objects.
|
||||
@ -61,19 +71,7 @@
|
||||
*/
|
||||
- (NSDate *)date;
|
||||
|
||||
/**
|
||||
* This method is used to determine if the message data item contains text or media.
|
||||
* If this method returns `YES`, an instance of `JSQMessagesViewController` will ignore
|
||||
* the `text` method of this protocol when dequeuing a `JSQMessagesCollectionViewCell`
|
||||
* and only call the `media` method.
|
||||
*
|
||||
* Similarly, if this method returns `NO` then the `media` method will be ignored and
|
||||
* and only the `text` method will be called.
|
||||
*
|
||||
* @return A boolean value specifying whether or not this is a media message or a text message.
|
||||
* Return `YES` if this item is a media message, and `NO` if it is a text message.
|
||||
*/
|
||||
- (BOOL)isMediaMessage;
|
||||
|
||||
|
||||
/**
|
||||
* @return An integer that can be used as a table address in a hash table structure.
|
||||
@ -96,4 +94,38 @@
|
||||
*/
|
||||
- (id<JSQMessageMediaData>)media;
|
||||
|
||||
/**
|
||||
* This method is used to determine if the message data item contains text or media.
|
||||
* If this method returns `YES`, an instance of `JSQMessagesViewController` will ignore
|
||||
* the `text` method of this protocol when dequeuing a `JSQMessagesCollectionViewCell`
|
||||
* and only call the `media` method.
|
||||
*
|
||||
* Similarly, if this method returns `NO` then the `media` method will be ignored and
|
||||
* and only the `text` method will be called.
|
||||
*
|
||||
* @return A boolean value specifying whether or not this is a media message or a text message.
|
||||
* Return `YES` if this item is a media message, and `NO` if it is a text message.
|
||||
*/
|
||||
- (BOOL)isMediaMessage;
|
||||
|
||||
|
||||
/*
|
||||
* Returns the message's state (eg for Signal :
|
||||
* TSOutgoingMessageStateAttemptingOut,
|
||||
* TSOutgoingMessageStateUnsent,
|
||||
* TSOutgoingMessageStateSent,
|
||||
* TSOutgoingMessageStateDelivered)
|
||||
*/
|
||||
- (NSInteger) messageState;
|
||||
|
||||
/*
|
||||
* Returns the type of message.
|
||||
* Does not need to be implemented for JSQMessage,
|
||||
* only for children JSQOutgoingMessage or JSQIncomingMessage.
|
||||
*
|
||||
* @see TSMessageType
|
||||
*/
|
||||
|
||||
- (TSMessageAdapterType) messageType;
|
||||
|
||||
@end
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
_cachedImageView = nil;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Setters
|
||||
|
||||
- (void)setImage:(UIImage *)image
|
||||
|
||||
30
JSQMessagesViewController/Views/JSQCallCollectionViewCell.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// JSQCallCollectionViewCell.h
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 20/11/14.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "JSQMessagesLabel.h"
|
||||
|
||||
#define kCallCellHeight 40.0f
|
||||
#define kCallCellWidth 400.0f
|
||||
|
||||
@interface JSQCallCollectionViewCell : UICollectionViewCell
|
||||
|
||||
@property (weak, nonatomic, readonly) JSQMessagesLabel *cellLabel;
|
||||
|
||||
@property (weak, nonatomic, readonly) UIImageView *outgoingCallImageView;
|
||||
|
||||
@property (weak, nonatomic, readonly) UIImageView *incomingCallImageView;
|
||||
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (UINib *)nib;
|
||||
|
||||
+ (NSString *)cellReuseIdentifier;
|
||||
|
||||
@end
|
||||
95
JSQMessagesViewController/Views/JSQCallCollectionViewCell.m
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// JSQCallCollectionViewCell.m
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 20/11/14.
|
||||
//
|
||||
|
||||
#import "JSQCallCollectionViewCell.h"
|
||||
|
||||
#import "UIView+JSQMessages.h"
|
||||
|
||||
|
||||
@interface JSQCallCollectionViewCell ()
|
||||
|
||||
@property (weak, nonatomic) IBOutlet JSQMessagesLabel *cellLabel;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *outgoingCallImageView;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView *incomingCallImageView;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *cellLabelHeightConstraint;
|
||||
|
||||
- (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFloat)constant;
|
||||
|
||||
@end
|
||||
|
||||
@implementation JSQCallCollectionViewCell
|
||||
|
||||
#pragma mark - Class Methods
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
+ (NSString *)cellReuseIdentifier
|
||||
{
|
||||
return NSStringFromClass([self class]);
|
||||
}
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
|
||||
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
self.cellLabelHeightConstraint.constant = 0.0f;
|
||||
|
||||
self.cellLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.cellLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14.0f];
|
||||
self.cellLabel.textColor = [UIColor lightGrayColor];
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
_cellLabel = nil;
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - Collection view cell
|
||||
|
||||
-(void)prepareForReuse
|
||||
{
|
||||
[super prepareForReuse];
|
||||
|
||||
self.cellLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
||||
{
|
||||
[super applyLayoutAttributes:layoutAttributes];
|
||||
|
||||
[self jsq_updateConstraint:self.cellLabelHeightConstraint
|
||||
withConstant:kCallCellHeight];
|
||||
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Utilities
|
||||
|
||||
- (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFloat)constant
|
||||
{
|
||||
if (constraint.constant == constant) {
|
||||
return;
|
||||
}
|
||||
|
||||
constraint.constant = constant;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
||||
@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14C68k" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
|
||||
</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="Efo-Hk-7Hw" customClass="JSQCallCollectionViewCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="YEr-eC-P6i" customClass="JSQMessagesLabel">
|
||||
<rect key="frame" x="39" y="0.0" width="242" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="7nw-w2-91p"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="o2l-Ms-1mk">
|
||||
<rect key="frame" x="281" y="0.0" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="78L-mQ-gEo"/>
|
||||
<constraint firstAttribute="width" constant="20" id="olH-5o-XyR"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="H8m-r4-eEC">
|
||||
<rect key="frame" x="19" y="0.0" width="20" height="20"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="20" id="Qay-jM-aBk"/>
|
||||
<constraint firstAttribute="width" constant="20" id="RpE-jJ-cYX"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="centerY" secondItem="o2l-Ms-1mk" secondAttribute="centerY" id="8wg-Tg-9Nh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YEr-eC-P6i" secondAttribute="trailing" constant="39" id="Hj7-z5-WMM"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="leading" secondItem="H8m-r4-eEC" secondAttribute="trailing" id="ZZJ-jL-10d"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="top" secondItem="Efo-Hk-7Hw" secondAttribute="top" id="rEI-cY-6lx"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="leading" secondItem="Efo-Hk-7Hw" secondAttribute="leading" constant="39" id="uNd-aK-1hE"/>
|
||||
<constraint firstItem="YEr-eC-P6i" firstAttribute="centerY" secondItem="H8m-r4-eEC" secondAttribute="centerY" id="wg8-V9-pBf"/>
|
||||
<constraint firstItem="o2l-Ms-1mk" firstAttribute="leading" secondItem="YEr-eC-P6i" secondAttribute="trailing" id="wmR-MD-QeR"/>
|
||||
</constraints>
|
||||
<size key="customSize" width="320" height="20"/>
|
||||
<connections>
|
||||
<outlet property="cellLabel" destination="YEr-eC-P6i" id="jii-8O-zLL"/>
|
||||
<outlet property="cellLabelHeightConstraint" destination="7nw-w2-91p" id="3IA-T6-4Eo"/>
|
||||
<outlet property="incomingCallImageView" destination="H8m-r4-eEC" id="hVW-Ng-BnU"/>
|
||||
<outlet property="outgoingCallImageView" destination="o2l-Ms-1mk" id="Q5m-uX-80H"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="219" y="435"/>
|
||||
</collectionViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
@ -0,0 +1,49 @@
|
||||
//
|
||||
// JSQDisplayedMessageCollectionViewCell.h
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "JSQMessagesLabel.h"
|
||||
|
||||
#define kDisplayedMessageCellTextLabelHeight 50.0f
|
||||
#define kDisplayedMessageCellHeight 70.0f
|
||||
#define kDisplayedMessageCellWidth 200.0f
|
||||
|
||||
@class JSQDisplayedMessageCollectionViewCell;
|
||||
|
||||
@protocol JSQDisplayedCollectionViewCellDelegate <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
|
||||
/**
|
||||
* Tells the delegate that the error/info message bubble has been tapped.
|
||||
*
|
||||
* @param cell The cell that received the tap touch event.
|
||||
*/
|
||||
|
||||
- (void)displayedCollectionViewCellDidTapMessage:(JSQDisplayedMessageCollectionViewCell *)cell;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@interface JSQDisplayedMessageCollectionViewCell : UICollectionViewCell
|
||||
|
||||
@property (weak, nonatomic, readonly) JSQMessagesLabel * cellLabel;
|
||||
|
||||
@property (weak, nonatomic, readonly) UIImageView * headerImageView;
|
||||
|
||||
@property (weak, nonatomic) id<JSQDisplayedCollectionViewCellDelegate> delegate;
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (UINib *) nib;
|
||||
|
||||
+ (NSString *) cellReuseIdentifier;
|
||||
|
||||
@end
|
||||
@ -0,0 +1,125 @@
|
||||
//
|
||||
// JSQDisplayedMessageCollectionViewCell.m
|
||||
// JSQMessages
|
||||
//
|
||||
// Created by Dylan Bourgeois on 29/11/14.
|
||||
// Copyright (c) 2014 Hexed Bits. All rights reserved.
|
||||
//
|
||||
|
||||
#import "JSQDisplayedMessageCollectionViewCell.h"
|
||||
|
||||
#import "UIView+JSQMessages.h"
|
||||
|
||||
@interface JSQDisplayedMessageCollectionViewCell ()
|
||||
|
||||
@property(weak, nonatomic) IBOutlet JSQMessagesLabel* cellLabel;
|
||||
|
||||
@property(weak, nonatomic) IBOutlet NSLayoutConstraint* cellLabelHeightConstraint;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIImageView* headerImageView;
|
||||
|
||||
- (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFloat)constant;
|
||||
|
||||
@end
|
||||
|
||||
@implementation JSQDisplayedMessageCollectionViewCell
|
||||
|
||||
#pragma mark - Class Methods
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:[NSBundle mainBundle]];
|
||||
}
|
||||
|
||||
+ (NSString *)cellReuseIdentifier
|
||||
{
|
||||
return NSStringFromClass([self class]);
|
||||
}
|
||||
|
||||
#pragma mark - Initializer
|
||||
|
||||
-(void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
|
||||
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
self.cellLabelHeightConstraint.constant = 0.0f;
|
||||
|
||||
self.cellLabel.layer.borderColor = [[UIColor lightGrayColor] CGColor];
|
||||
self.cellLabel.layer.borderWidth = 0.75f;
|
||||
self.cellLabel.layer.cornerRadius = 5.0f;
|
||||
self.cellLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.cellLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14.0f];
|
||||
self.cellLabel.textColor = [UIColor lightGrayColor];
|
||||
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(jsq_handleTapGesture:)];
|
||||
[self addGestureRecognizer:tap];
|
||||
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
_cellLabel = nil;
|
||||
|
||||
_delegate = nil;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - Collection view cell
|
||||
|
||||
-(void)prepareForReuse
|
||||
{
|
||||
[super prepareForReuse];
|
||||
|
||||
self.cellLabel.text = nil;
|
||||
}
|
||||
|
||||
-(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes
|
||||
{
|
||||
[super applyLayoutAttributes:layoutAttributes];
|
||||
|
||||
[self jsq_updateConstraint:self.cellLabelHeightConstraint
|
||||
withConstant:kDisplayedMessageCellTextLabelHeight];
|
||||
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Utilities
|
||||
|
||||
- (void)jsq_updateConstraint:(NSLayoutConstraint *)constraint withConstant:(CGFloat)constant
|
||||
{
|
||||
if (constraint.constant == constant) {
|
||||
return;
|
||||
}
|
||||
|
||||
constraint.constant = constant;
|
||||
}
|
||||
|
||||
#pragma mark - Gesture recognizers
|
||||
|
||||
-(void)jsq_handleTapGesture:(UITapGestureRecognizer *)tap
|
||||
{
|
||||
CGPoint touchPoint = [tap locationInView:self];
|
||||
|
||||
if (CGRectContainsPoint(self.contentView.frame, touchPoint))
|
||||
{
|
||||
[self.delegate displayedCollectionViewCellDidTapMessage:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
|
||||
{
|
||||
CGPoint touchPt = [touch locationInView:self];
|
||||
|
||||
if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
|
||||
return CGRectContainsPoint(self.contentView.frame, touchPt);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14C68k" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
|
||||
</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="eMU-z2-CzM" customClass="JSQDisplayedMessageCollectionViewCell">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OVa-Xw-5vl" customClass="JSQMessagesLabel">
|
||||
<rect key="frame" x="8" y="20" width="304" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="fed-2c-dqd"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="warning_white.png" translatesAutoresizingMaskIntoConstraints="NO" id="ePO-Cy-jUE">
|
||||
<rect key="frame" x="143" y="-3" width="35" height="35"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="35" id="Llx-81-oyV"/>
|
||||
<constraint firstAttribute="width" constant="35" id="Nth-3D-Wo9"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstItem="OVa-Xw-5vl" firstAttribute="top" secondItem="eMU-z2-CzM" secondAttribute="top" id="2E8-Lm-cti"/>
|
||||
<constraint firstItem="OVa-Xw-5vl" firstAttribute="top" secondItem="ePO-Cy-jUE" secondAttribute="bottom" constant="-12" id="4ie-2d-9cn"/>
|
||||
<constraint firstAttribute="trailing" secondItem="OVa-Xw-5vl" secondAttribute="trailing" constant="8" id="5Mk-DE-t1M"/>
|
||||
<constraint firstItem="OVa-Xw-5vl" firstAttribute="leading" secondItem="eMU-z2-CzM" secondAttribute="leading" constant="8" id="E3N-dw-XQG"/>
|
||||
<constraint firstItem="OVa-Xw-5vl" firstAttribute="top" secondItem="ePO-Cy-jUE" secondAttribute="bottom" id="Yy0-Kd-Lu4"/>
|
||||
<constraint firstItem="ePO-Cy-jUE" firstAttribute="top" secondItem="eMU-z2-CzM" secondAttribute="top" id="ZSC-Dm-tsL"/>
|
||||
<constraint firstAttribute="bottom" secondItem="OVa-Xw-5vl" secondAttribute="bottom" id="jaG-ZH-h7s"/>
|
||||
<constraint firstItem="OVa-Xw-5vl" firstAttribute="centerX" secondItem="ePO-Cy-jUE" secondAttribute="centerX" id="rdy-5p-ndu"/>
|
||||
</constraints>
|
||||
<size key="customSize" width="320" height="55"/>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="2E8-Lm-cti"/>
|
||||
<exclude reference="Yy0-Kd-Lu4"/>
|
||||
<exclude reference="ZSC-Dm-tsL"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<connections>
|
||||
<outlet property="cellLabel" destination="OVa-Xw-5vl" id="7PC-oj-dQZ"/>
|
||||
<outlet property="cellLabelHeightConstraint" destination="fed-2c-dqd" id="98O-NG-4yI"/>
|
||||
<outlet property="headerImageView" destination="ePO-Cy-jUE" id="4uq-2C-V7U"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="219" y="433"/>
|
||||
</collectionViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="warning_white.png" width="100" height="100"/>
|
||||
</resources>
|
||||
</document>
|
||||
@ -22,6 +22,8 @@
|
||||
#import "JSQMessagesCollectionViewDelegateFlowLayout.h"
|
||||
#import "JSQMessagesCollectionViewDataSource.h"
|
||||
#import "JSQMessagesCollectionViewCell.h"
|
||||
#import "JSQDisplayedMessageCollectionViewCell.h"
|
||||
|
||||
|
||||
@class JSQMessagesTypingIndicatorFooterView;
|
||||
@class JSQMessagesLoadEarlierHeaderView;
|
||||
@ -31,7 +33,7 @@
|
||||
* The `JSQMessagesCollectionView` class manages an ordered collection of message data items and presents
|
||||
* them using a specialized layout for messages.
|
||||
*/
|
||||
@interface JSQMessagesCollectionView : UICollectionView <JSQMessagesCollectionViewCellDelegate>
|
||||
@interface JSQMessagesCollectionView : UICollectionView <JSQMessagesCollectionViewCellDelegate, JSQDisplayedCollectionViewCellDelegate>
|
||||
|
||||
/**
|
||||
* The object that provides the data for the collection view.
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
#import "UIColor+JSQMessages.h"
|
||||
|
||||
#import "JSQCallCollectionViewCell.h"
|
||||
|
||||
@interface JSQMessagesCollectionView () <JSQMessagesLoadEarlierHeaderViewDelegate>
|
||||
|
||||
@ -67,6 +68,12 @@
|
||||
[self registerNib:[JSQMessagesLoadEarlierHeaderView nib]
|
||||
forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
|
||||
withReuseIdentifier:[JSQMessagesLoadEarlierHeaderView headerReuseIdentifier]];
|
||||
|
||||
[self registerNib:[JSQCallCollectionViewCell nib]
|
||||
forCellWithReuseIdentifier:[JSQCallCollectionViewCell cellReuseIdentifier]];
|
||||
|
||||
[self registerNib:[JSQDisplayedMessageCollectionViewCell nib]
|
||||
forCellWithReuseIdentifier:[JSQDisplayedMessageCollectionViewCell cellReuseIdentifier]];
|
||||
|
||||
_typingIndicatorDisplaysOnLeft = YES;
|
||||
_typingIndicatorMessageBubbleColor = [UIColor jsq_messageBubbleLightGrayColor];
|
||||
@ -165,4 +172,15 @@
|
||||
touchLocation:position];
|
||||
}
|
||||
|
||||
- (void)displayedCollectionViewCellDidTapMessage:(JSQDisplayedMessageCollectionViewCell *)cell
|
||||
{
|
||||
NSIndexPath * indexPath = [self indexPathForCell:cell];
|
||||
|
||||
if (indexPath == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self.delegate collectionView:self didTapMessageBubbleAtIndexPath:indexPath];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#import "UIView+JSQMessages.h"
|
||||
#import "UIDevice+JSQMessages.h"
|
||||
#import "UIColor+JSQMessages.h"
|
||||
|
||||
|
||||
@interface JSQMessagesCollectionViewCell ()
|
||||
@ -95,7 +96,6 @@
|
||||
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
self.cellTopLabelHeightConstraint.constant = 0.0f;
|
||||
self.messageBubbleTopLabelHeightConstraint.constant = 0.0f;
|
||||
self.cellBottomLabelHeightConstraint.constant = 0.0f;
|
||||
|
||||
0
JSQMessagesViewController/Views/JSQMessagesCollectionViewCellIncoming.xib
Normal file → Executable file
2
JSQMessagesViewController/Views/JSQMessagesCollectionViewCellOutgoing.xib
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="14C68k" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
|
||||
|
||||
@ -48,9 +48,10 @@
|
||||
CGFloat cornerRadius = 6.0f;
|
||||
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
self.layer.borderWidth = 0.5f;
|
||||
self.layer.borderColor = [UIColor lightGrayColor].CGColor;
|
||||
self.layer.cornerRadius = cornerRadius;
|
||||
//Signal: Comment out elements of Composer view
|
||||
// self.layer.borderWidth = 0.5f;
|
||||
// self.layer.borderColor = [UIColor lightGrayColor].CGColor;
|
||||
// self.layer.cornerRadius = cornerRadius;
|
||||
|
||||
self.scrollIndicatorInsets = UIEdgeInsetsMake(cornerRadius, 0.0f, cornerRadius, 0.0f);
|
||||
|
||||
@ -61,7 +62,8 @@
|
||||
self.scrollsToTop = NO;
|
||||
self.userInteractionEnabled = YES;
|
||||
|
||||
self.font = [UIFont systemFontOfSize:16.0f];
|
||||
self.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:16.0f];
|
||||
// self.font = [UIFont systemFontOfSize:16.0f];
|
||||
self.textColor = [UIColor blackColor];
|
||||
self.textAlignment = NSTextAlignmentNatural;
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ static void * kJSQMessagesInputToolbarKeyValueObservingContext = &kJSQMessagesIn
|
||||
- (void)toggleSendButtonEnabled
|
||||
{
|
||||
BOOL hasText = [self.contentView.textView hasText];
|
||||
|
||||
|
||||
if (self.sendButtonOnRight) {
|
||||
self.contentView.rightBarButtonItem.enabled = hasText;
|
||||
}
|
||||
|
||||
@ -10,4 +10,4 @@ SPEC CHECKSUMS:
|
||||
JSQSystemSoundPlayer: c98443b1cbb3b45db09d0d3d6c2355cf78294981
|
||||
OCMock: f6cb8c162ab9d5620dddf411282c7b2c0ee78854
|
||||
|
||||
COCOAPODS: 0.34.4
|
||||
COCOAPODS: 0.35.0
|
||||
|
||||