Skip to content

Commit f238ecc

Browse files
adubrjessesquires
authored andcommitted
Added accessory button to message cell (jessesquires#1719), close jessesquires#1519
1 parent 05b5ae5 commit f238ecc

22 files changed

+252
-41
lines changed

JSQMessages.xcodeproj/project.pbxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
54271E3F1C905D1600294290 /* JSQAudioMediaItemTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQAudioMediaItemTests.m; sourceTree = "<group>"; };
131131
544A321F1CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQAudioMediaViewAttributes.h; sourceTree = "<group>"; };
132132
544A32201CB2EE380084BFC0 /* JSQAudioMediaViewAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQAudioMediaViewAttributes.m; sourceTree = "<group>"; };
133+
58620BCC6ABA99E3C6FD36F5 /* JSQMessagesViewAccessoryButtonDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesViewAccessoryButtonDelegate.h; sourceTree = "<group>"; };
133134
88078A9B19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesMediaPlaceholderView.h; sourceTree = "<group>"; };
134135
88078A9C19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaPlaceholderView.m; sourceTree = "<group>"; };
135136
88324C3319F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaViewBubbleImageMaskerTests.m; sourceTree = "<group>"; };
@@ -497,6 +498,7 @@
497498
88A25F8619D8E01A00924534 /* JSQPhotoMediaItem.m */,
498499
886C33FB19F4371E006B4997 /* JSQVideoMediaItem.h */,
499500
886C33FC19F4371E006B4997 /* JSQVideoMediaItem.m */,
501+
58620BCC6ABA99E3C6FD36F5 /* JSQMessagesViewAccessoryButtonDelegate.h */,
500502
);
501503
path = Model;
502504
sourceTree = "<group>";

JSQMessagesDemo/Base.lproj/Main.storyboard

Lines changed: 52 additions & 17 deletions
Large diffs are not rendered by default.

JSQMessagesDemo/DemoMessagesViewController.m

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
//
1818

1919
#import "DemoMessagesViewController.h"
20+
#import "JSQMessagesViewAccessoryButtonDelegate.h"
21+
22+
@interface DemoMessagesViewController () <JSQMessagesViewAccessoryButtonDelegate>
23+
@end
2024

2125
@implementation DemoMessagesViewController
2226

@@ -44,7 +48,12 @@ - (void)viewDidLoad
4448
*/
4549
self.demoData = [[DemoModelData alloc] init];
4650

47-
51+
52+
/**
53+
* Set up message accessory button delegate and configuration
54+
*/
55+
self.collectionView.accessoryDelegate = self;
56+
4857
/**
4958
* You can set custom avatar sizes
5059
*/
@@ -563,10 +572,16 @@ - (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collection
563572
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
564573
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
565574
}
575+
576+
cell.accessoryButton.hidden = ![self shouldShowAccessoryButtonForMessage:msg];
566577

567578
return cell;
568579
}
569580

581+
- (BOOL)shouldShowAccessoryButtonForMessage:(id<JSQMessageData>)message
582+
{
583+
return ([message isMediaMessage] && [NSUserDefaults accessoryButtonForMediaMessages]);
584+
}
570585

571586

572587
#pragma mark - UICollectionView Delegate
@@ -682,7 +697,6 @@ - (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapCellAtI
682697

683698
#pragma mark - JSQMessagesComposerTextViewPasteDelegate methods
684699

685-
686700
- (BOOL)composerTextView:(JSQMessagesComposerTextView *)textView shouldPasteWithSender:(id)sender
687701
{
688702
if ([UIPasteboard generalPasteboard].image) {
@@ -699,4 +713,11 @@ - (BOOL)composerTextView:(JSQMessagesComposerTextView *)textView shouldPasteWith
699713
return YES;
700714
}
701715

716+
#pragma mark - JSQMessagesViewAccessoryDelegate methods
717+
718+
- (void)messageView:(JSQMessagesCollectionView *)view didTapAccessoryButtonAtIndexPath:(NSIndexPath *)path
719+
{
720+
NSLog(@"Tapped accessory button!");
721+
}
722+
702723
@end

JSQMessagesDemo/DemoSettingsViewController.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,6 @@
3939

4040
@property (weak, nonatomic) IBOutlet UISwitch *springySwitch;
4141

42+
@property (weak, nonatomic) IBOutlet UISwitch *accessoryButtonSwitch;
43+
4244
@end

JSQMessagesDemo/DemoSettingsViewController.m

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ - (void)viewDidLoad
3636
self.extraMessagesSwitch.on = [NSUserDefaults extraMessagesSetting];
3737
self.longMessageSwitch.on = [NSUserDefaults longMessageSetting];
3838
self.emptySwitch.on = [NSUserDefaults emptyMessagesSetting];
39+
self.accessoryButtonSwitch.on = [NSUserDefaults accessoryButtonForMediaMessages];
3940

4041
self.incomingAvatarsSwitch.on = [NSUserDefaults incomingAvatarSetting];
4142
self.outgoingAvatarsSwitch.on = [NSUserDefaults outgoingAvatarSetting];
@@ -47,14 +48,16 @@ - (IBAction)didTapSwitch:(UISwitch *)sender
4748
{
4849
if (sender == self.extraMessagesSwitch) {
4950
[NSUserDefaults saveExtraMessagesSetting:sender.on];
50-
5151
}
5252
else if (sender == self.longMessageSwitch) {
5353
[NSUserDefaults saveLongMessageSetting:sender.on];
5454
}
5555
else if (sender == self.emptySwitch) {
5656
[NSUserDefaults saveEmptyMessagesSetting:sender.on];
5757
}
58+
else if (sender == self.accessoryButtonSwitch) {
59+
[NSUserDefaults saveAccessoryButtonForMediaMessages:sender.on];
60+
}
5861
else if (sender == self.incomingAvatarsSwitch) {
5962
[NSUserDefaults saveIncomingAvatarSetting:sender.on];
6063
}

JSQMessagesDemo/NSUserDefaults+DemoSettings.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,7 @@
3838
+ (void)saveIncomingAvatarSetting:(BOOL)value;
3939
+ (BOOL)incomingAvatarSetting;
4040

41+
+ (void)saveAccessoryButtonForMediaMessages:(BOOL)value;
42+
+ (BOOL)accessoryButtonForMediaMessages;
43+
4144
@end

JSQMessagesDemo/NSUserDefaults+DemoSettings.m

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818

1919
#import "NSUserDefaults+DemoSettings.h"
2020

21-
static NSString * const kSettingExtraMessages = @"kSettingExtraMessages";
22-
static NSString * const kSettingLongMessage = @"kSettingLongMessage";
23-
static NSString * const kSettingEmptyMessages = @"kSettingEmptyMessages";
24-
static NSString * const kSettingSpringiness = @"kSettingSpringiness";
25-
static NSString * const kSettingIncomingAvatar = @"kSettingIncomingAvatar";
26-
static NSString * const kSettingOutgoingAvatar = @"kSettingOutgoingAvatar";
27-
21+
static NSString * const kSettingExtraMessages = @"kSettingExtraMessages";
22+
static NSString * const kSettingLongMessage = @"kSettingLongMessage";
23+
static NSString * const kSettingEmptyMessages = @"kSettingEmptyMessages";
24+
static NSString * const kSettingSpringiness = @"kSettingSpringiness";
25+
static NSString * const kSettingIncomingAvatar = @"kSettingIncomingAvatar";
26+
static NSString * const kSettingOutgoingAvatar = @"kSettingOutgoingAvatar";
27+
static NSString * const kSettingAccessoryButtonForMedia = @"kSettingAccessoryButtonForMedia";
2828

2929
@implementation NSUserDefaults (DemoSettings)
3030

@@ -88,4 +88,13 @@ + (BOOL)incomingAvatarSetting
8888
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingIncomingAvatar];
8989
}
9090

91+
+ (BOOL)accessoryButtonForMediaMessages
92+
{
93+
return [[NSUserDefaults standardUserDefaults] boolForKey:kSettingAccessoryButtonForMedia];
94+
}
95+
96+
+ (void)saveAccessoryButtonForMediaMessages:(BOOL)value
97+
{
98+
[[NSUserDefaults standardUserDefaults] setBool:value forKey:kSettingAccessoryButtonForMedia];
99+
}
91100
@end

JSQMessagesDemo/he.lproj/Main.strings

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
/* Class = "UILabel"; text = "Outgoing avatars"; ObjectID = "9Rr-S8-Uae"; */
99
"9Rr-S8-Uae.text" = "אווטאר בהודעות יוצאות";
1010

11+
/* Class = "UILabel"; text = "Accessory button for media messages"; ObjectID = "Cae-FY-b5Q"; */
12+
"Cae-FY-b5Q.text" = "Accessory button for media messages";
13+
1114
/* Class = "UILabel"; text = "Empty view, no messages"; ObjectID = "DoU-SU-Nek"; */
1215
"DoU-SU-Nek.text" = "מסך רייק ללא הודעות";
1316

JSQMessagesTests/CategoryTests/JSQMessagesUIImageTests.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ - (void)testImageAssets
5858
XCTAssertNotNil([UIImage jsq_defaultAccessoryImage]);
5959

6060
XCTAssertNotNil([UIImage jsq_defaultTypingIndicatorImage]);
61-
61+
6262
XCTAssertNotNil([UIImage jsq_defaultPlayImage]);
63+
64+
XCTAssertNotNil([UIImage jsq_shareActionImage]);
6365
}
6466

6567
@end
Loading
Loading
Loading

JSQMessagesViewController/Categories/UIImage+JSQMessages.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ NS_ASSUME_NONNULL_BEGIN
8383
*/
8484
+ (UIImage *)jsq_defaultPauseImage;
8585

86+
/**
87+
* @return The standard share icon image.
88+
*
89+
* @discussion This is the default icon for the message accessory button.
90+
*/
91+
+ (UIImage *)jsq_shareActionImage;
92+
8693
@end
8794

8895
NS_ASSUME_NONNULL_END

JSQMessagesViewController/Categories/UIImage+JSQMessages.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,8 @@ + (UIImage *)jsq_defaultPauseImage
105105
return [UIImage jsq_bubbleImageFromBundleWithName:@"pause"];
106106
}
107107

108+
+ (UIImage *)jsq_shareActionImage
109+
{
110+
return [UIImage jsq_bubbleImageFromBundleWithName:@"UIButtonBarActionSmall"];
111+
}
108112
@end

JSQMessagesViewController/Controllers/JSQMessagesViewController.m

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,9 @@
3030
#import "JSQMessagesTypingIndicatorFooterView.h"
3131
#import "JSQMessagesLoadEarlierHeaderView.h"
3232

33-
#import "JSQMessagesToolbarContentView.h"
34-
#import "JSQMessagesInputToolbar.h"
35-
#import "JSQMessagesComposerTextView.h"
36-
3733
#import "NSString+JSQMessages.h"
38-
#import "UIColor+JSQMessages.h"
3934
#import "NSBundle+JSQMessages.h"
4035

41-
#import <MobileCoreServices/UTCoreTypes.h>
42-
4336
#import <objc/runtime.h>
4437

4538

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// Created by Jesse Squires
3+
// http://www.jessesquires.com
4+
//
5+
// Documentation
6+
// http://cocoadocs.org/docsets/JSQMessagesViewController
7+
//
8+
//
9+
// GitHub
10+
// https://github.com/jessesquires/JSQMessagesViewController
11+
//
12+
//
13+
// License
14+
// Copyright (c) 2014 Jesse Squires
15+
// Released under an MIT license: http://opensource.org/licenses/MIT
16+
//
17+
18+
#import <Foundation/Foundation.h>
19+
20+
NS_ASSUME_NONNULL_BEGIN
21+
22+
@class JSQMessagesCollectionView;
23+
24+
/**
25+
* The `JSQMessagesViewAccessoryButtonDelegate` protocol defines methods that allow you to
26+
* handle accessory actions for the collection view.
27+
*/
28+
@protocol JSQMessagesViewAccessoryButtonDelegate <NSObject>
29+
30+
@required
31+
32+
/**
33+
* Notifies the delegate that the accessory button at the specified indexPath did receive a tap event.
34+
*
35+
* @param messageView The collection view object that is notifying the delegate of the tap event.
36+
* @param indexPath The index path of the item for which the accessory button was tapped.
37+
*/
38+
- (void)messageView:(JSQMessagesCollectionView *)messageView didTapAccessoryButtonAtIndexPath:(NSIndexPath *)path;
39+
40+
@end
41+
42+
NS_ASSUME_NONNULL_END

JSQMessagesViewController/Views/JSQMessagesCollectionView.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
@class JSQMessagesTypingIndicatorFooterView;
2727
@class JSQMessagesLoadEarlierHeaderView;
28+
@protocol JSQMessagesViewAccessoryButtonDelegate;
2829

2930
NS_ASSUME_NONNULL_BEGIN
3031

@@ -46,6 +47,12 @@ NS_ASSUME_NONNULL_BEGIN
4647
*/
4748
@property (weak, nonatomic, nullable) id<JSQMessagesCollectionViewDelegateFlowLayout> delegate;
4849

50+
/**
51+
* The object that handles accessory actions for the collection view.
52+
* It must adopt the `JSQMessagesViewAccessoryButtonDelegate` protocol.
53+
*/
54+
@property (weak, nonatomic, nullable) id<JSQMessagesViewAccessoryButtonDelegate> accessoryDelegate;
55+
4956
/**
5057
* The layout used to organize the collection view’s items.
5158
*/

JSQMessagesViewController/Views/JSQMessagesCollectionView.m

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
#import "JSQMessagesCollectionView.h"
2020

21-
#import "JSQMessagesCollectionViewFlowLayout.h"
21+
#import "JSQMessagesViewAccessoryButtonDelegate.h"
22+
2223
#import "JSQMessagesCollectionViewCellIncoming.h"
2324
#import "JSQMessagesCollectionViewCellOutgoing.h"
2425

@@ -183,4 +184,14 @@ - (void)messagesCollectionViewCell:(JSQMessagesCollectionViewCell *)cell didPerf
183184
withSender:sender];
184185
}
185186

187+
- (void)messagesCollectionViewCellDidTapAccessoryButton:(JSQMessagesCollectionViewCell *)cell
188+
{
189+
NSIndexPath *indexPath = [self indexPathForCell:cell];
190+
if (indexPath == nil) {
191+
return;
192+
}
193+
194+
[self.accessoryDelegate messageView:self didTapAccessoryButtonAtIndexPath:indexPath];
195+
}
196+
186197
@end

JSQMessagesViewController/Views/JSQMessagesCollectionViewCell.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ NS_ASSUME_NONNULL_BEGIN
7474
*/
7575
- (void)messagesCollectionViewCell:(JSQMessagesCollectionViewCell *)cell didPerformAction:(SEL)action withSender:(id)sender;
7676

77+
/**
78+
* Tells the delegate that the accessory button of the cell has been tapped.
79+
*
80+
* @param cell The cell that the accessory button belongs to.
81+
*/
82+
- (void)messagesCollectionViewCellDidTapAccessoryButton:(JSQMessagesCollectionViewCell *)cell;
83+
7784
@end
7885

7986

@@ -156,6 +163,16 @@ NS_ASSUME_NONNULL_BEGIN
156163
*/
157164
@property (weak, nonatomic, readonly, nullable) UIView *avatarContainerView;
158165

166+
/**
167+
* Returns the accessory button of the cell.
168+
*/
169+
@property (weak, nonatomic, readonly, nullable) UIButton *accessoryButton;
170+
171+
/**
172+
* Sets an image for the accessory button of the cell.
173+
*/
174+
- (void)setAccessoryButtonImage:(UIImage *)image;
175+
159176
/**
160177
* The media view of the cell. This view displays the contents of a media message.
161178
*

0 commit comments

Comments
 (0)