Skip to content

Commit

Permalink
Issue jessesquires#693 - Copying images, location to pasteboard.
Browse files Browse the repository at this point in the history
  • Loading branch information
pstasiak committed Feb 15, 2016
1 parent c296dac commit af36c20
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 15 deletions.
22 changes: 13 additions & 9 deletions JSQMessages.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1F0EFE0F1AC23D7E003FF3DB /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F0EFE0E1AC23D7E003FF3DB /* MobileCoreServices.framework */; };
88078A9D19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88078A9C19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m */; };
88324C3419F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88324C3319F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m */; };
883C11781A09FB100092A16D /* JSQMessagesCellTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 883C11771A09FB100092A16D /* JSQMessagesCellTextView.m */; };
Expand Down Expand Up @@ -120,9 +121,9 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
0B4D05069814EB50FB0F4229 /* Pods-JSQMessagesTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.release.xcconfig"; sourceTree = "<group>"; };
1D4D3B82D90888BCEAF890D3 /* Pods-JSQMessagesTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.debug.xcconfig"; sourceTree = "<group>"; };
3BA6237809BE0D008CFE3697 /* 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>"; };
1F0EFE0E1AC23D7E003FF3DB /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
242A2BCAF25E39CC1DAF654E /* Pods-JSQMessagesTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.release.xcconfig"; sourceTree = "<group>"; };
4D257782A244F7688A2F6AA8 /* 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>"; };
88078A9B19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSQMessagesMediaPlaceholderView.h; sourceTree = "<group>"; };
88078A9C19D8FEB5005B4595 /* JSQMessagesMediaPlaceholderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaPlaceholderView.m; sourceTree = "<group>"; };
88324C3319F6301C00BC732D /* JSQMessagesMediaViewBubbleImageMaskerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSQMessagesMediaViewBubbleImageMaskerTests.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -271,13 +272,15 @@
AD6E75315517DE46FE495B65 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
C3F882AA48978C11F64DC2DF /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
E23238C8D8DF79244DEE1787 /* libPods-JSQMessagesTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JSQMessagesTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F68D899A0AE7E8180C89579D /* Pods-JSQMessagesTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JSQMessagesTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-JSQMessagesTests/Pods-JSQMessagesTests.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
88A25EFF19D8DEC400924534 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1F0EFE0F1AC23D7E003FF3DB /* MobileCoreServices.framework in Frameworks */,
88445B4419E1B5110014F889 /* MapKit.framework in Frameworks */,
88445B4219E1B50B0014F889 /* CoreLocation.framework in Frameworks */,
88445B3719E0AE5C0014F889 /* QuartzCore.framework in Frameworks */,
Expand Down Expand Up @@ -310,6 +313,7 @@
636A8663AEEE5C37B65C515D /* Frameworks */ = {
isa = PBXGroup;
children = (
1F0EFE0E1AC23D7E003FF3DB /* MobileCoreServices.framework */,
88445B3419E0AE4A0014F889 /* CoreGraphics.framework */,
88445B4119E1B50B0014F889 /* CoreLocation.framework */,
88445B3219E0AE450014F889 /* Foundation.framework */,
Expand All @@ -326,10 +330,10 @@
842892590A65F355D8619D29 /* Pods */ = {
isa = PBXGroup;
children = (
3BA6237809BE0D008CFE3697 /* Pods.debug.xcconfig */,
AD6E75315517DE46FE495B65 /* Pods.release.xcconfig */,
1D4D3B82D90888BCEAF890D3 /* Pods-JSQMessagesTests.debug.xcconfig */,
0B4D05069814EB50FB0F4229 /* Pods-JSQMessagesTests.release.xcconfig */,
4D257782A244F7688A2F6AA8 /* Pods.debug.xcconfig */,
F68D899A0AE7E8180C89579D /* Pods-JSQMessagesTests.debug.xcconfig */,
242A2BCAF25E39CC1DAF654E /* Pods-JSQMessagesTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
Expand Down Expand Up @@ -1030,7 +1034,7 @@
};
88A25F2619D8DEC500924534 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3BA6237809BE0D008CFE3697 /* Pods.debug.xcconfig */;
baseConfigurationReference = 4D257782A244F7688A2F6AA8 /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
Expand Down Expand Up @@ -1068,7 +1072,7 @@
};
88A25F2919D8DEC500924534 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 1D4D3B82D90888BCEAF890D3 /* Pods-JSQMessagesTests.debug.xcconfig */;
baseConfigurationReference = F68D899A0AE7E8180C89579D /* Pods-JSQMessagesTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
Expand All @@ -1087,7 +1091,7 @@
};
88A25F2A19D8DEC500924534 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0B4D05069814EB50FB0F4229 /* Pods-JSQMessagesTests.release.xcconfig */;
baseConfigurationReference = 242A2BCAF25E39CC1DAF654E /* Pods-JSQMessagesTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
Expand Down
11 changes: 11 additions & 0 deletions JSQMessagesTests/ModelTests/JSQLocationMediaItemTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#import "JSQLocationMediaItem.h"

#import <MobileCoreServices/UTCoreTypes.h>

@interface JSQLocationMediaItemTests : XCTestCase

Expand Down Expand Up @@ -61,4 +62,14 @@ - (void)testMediaDataProtocol
XCTAssertNotNil([item mediaView], @"Media view should NOT be nil once item has media data");
}

- (void)testCopyableItemInMediaProtocol {
JSQLocationMediaItem *item = [[JSQLocationMediaItem alloc] initWithLocation:self.location];
XCTAssertNotNil(item);

XCTAssertEqualObjects((NSString *)kUTTypeURL, [item mediaDataType]);

NSURL *locationURL = [[NSURL alloc] initWithString:@"http://maps.google.com/maps?z=12&t=m&q=loc:37.795313+-122.393757"];
XCTAssertEqualObjects(locationURL, [item mediaData]);
}

@end
10 changes: 10 additions & 0 deletions JSQMessagesTests/ModelTests/JSQPhotoMediaItemTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#import "JSQPhotoMediaItem.h"

#import <MobileCoreServices/UTCoreTypes.h>

@interface JSQPhotoMediaItemTests : XCTestCase

Expand Down Expand Up @@ -73,4 +74,13 @@ - (void)testMediaDataProtocol
XCTAssertNotNil([item mediaView], @"Media view should NOT be nil once item has media data");
}

- (void)testCopyableItemInMediaProtocol {
JSQPhotoMediaItem *item = [[JSQPhotoMediaItem alloc] initWithImage:[UIImage imageNamed:@"demo_avatar_jobs"]];
XCTAssertNotNil(item);
XCTAssertEqual([item mediaDataType], (NSString *)kUTTypeJPEG);

UIImage *itemImage = [[UIImage alloc] initWithData:[item mediaData]];
XCTAssertNotNil(itemImage);
}

@end
3 changes: 1 addition & 2 deletions JSQMessagesViewController.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ Pod::Spec.new do |s|
s.source_files = 'JSQMessagesViewController/**/*.{h,m}'

s.resources = ['JSQMessagesViewController/Assets/JSQMessagesAssets.bundle', 'JSQMessagesViewController/**/*.{xib}']

s.frameworks = 'QuartzCore', 'CoreGraphics', 'CoreLocation', 'MapKit', 'UIKit', 'Foundation'
s.frameworks = 'QuartzCore', 'CoreGraphics', 'CoreLocation', 'MapKit', 'UIKit', 'Foundation', 'MobileCoreServices'
s.requires_arc = true

s.dependency 'JSQSystemSoundPlayer', '~> 2.0.1'
Expand Down
21 changes: 19 additions & 2 deletions JSQMessagesViewController/Controllers/JSQMessagesViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#import "UIDevice+JSQMessages.h"
#import "NSBundle+JSQMessages.h"

#import <MobileCoreServices/UTCoreTypes.h>


static void * kJSQMessagesKeyValueObservingContext = &kJSQMessagesKeyValueObservingContext;

Expand Down Expand Up @@ -572,6 +574,11 @@ - (BOOL)collectionView:(JSQMessagesCollectionView *)collectionView shouldShowMen
// disable menu for media messages
id<JSQMessageData> messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
if ([messageItem isMediaMessage]) {

if ([[messageItem media] respondsToSelector:@selector(mediaDataType)]) {
return YES;
}

return NO;
}

Expand Down Expand Up @@ -599,8 +606,18 @@ - (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)
- (void)collectionView:(JSQMessagesCollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(copy:)) {
id<JSQMessageData> messageData = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
[[UIPasteboard generalPasteboard] setString:[messageData text]];

id<JSQMessageData> messageData = [self collectionView:collectionView messageDataForItemAtIndexPath:indexPath];

if ([messageData isMediaMessage]) {
id<JSQMessageMediaData> mediaData = [messageData media];
if ([messageData respondsToSelector:@selector(mediaDataType)]) {
[[UIPasteboard generalPasteboard] setValue:[mediaData mediaData]
forPasteboardType:[mediaData mediaDataType]];
}
} else {
[[UIPasteboard generalPasteboard] setString:[messageData text]];
}
}
else if (action == @selector(delete:)) {
[collectionView.dataSource collectionView:collectionView didDeleteMessageAtIndexPath:indexPath];
Expand Down
15 changes: 15 additions & 0 deletions JSQMessagesViewController/Model/JSQLocationMediaItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#import "JSQMessagesMediaPlaceholderView.h"
#import "JSQMessagesMediaViewBubbleImageMasker.h"

#import <MobileCoreServices/UTCoreTypes.h>


@interface JSQLocationMediaItem ()

Expand Down Expand Up @@ -158,6 +160,19 @@ - (NSUInteger)mediaHash
return self.hash;
}

- (NSString *)mediaDataType
{
return (NSString *)kUTTypeURL;
}

- (id)mediaData
{
NSString *locationAsGoogleMapsString = [NSString stringWithFormat:@"http://maps.google.com/maps?z=12&t=m&q=loc:%f+%f", self.coordinate.latitude, self.coordinate.longitude ];
NSURL *locationURL = [[NSURL alloc] initWithString:locationAsGoogleMapsString];
return locationURL;
}


#pragma mark - NSObject

- (BOOL)isEqual:(id)object
Expand Down
2 changes: 0 additions & 2 deletions JSQMessagesViewController/Model/JSQMessageData.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@
*/
- (NSUInteger)messageHash;

@optional

/**
* @return The body text of the message.
*
Expand Down
20 changes: 20 additions & 0 deletions JSQMessagesViewController/Model/JSQMessageMediaData.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,24 @@
*/
- (NSUInteger)mediaHash;

@optional

/**
* @return String which identifies type of the data returned by `mediaData` method.
*
* @discussion If implemented, you must not return `nil` from this, as well as `copyableData`, method.
* This type is frequently, but not necessarily, a UTI (Uniform Type Identifier). It identifies a
* representation of the data on the pasteboard. Apps can define their own types for custom data,
* however, in this case, only those apps that know of the type could understand the data written to the pasteboard.
*/
- (NSString *)mediaDataType;

/**
* @return Data object of class corresponding to type returned by `mediaDataType`.
*
* @discussion You should return an object that is of a class type appropriate to the representation type,
* which typically is a UTI.
*/
- (id)mediaData;

@end
11 changes: 11 additions & 0 deletions JSQMessagesViewController/Model/JSQPhotoMediaItem.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#import "JSQMessagesMediaPlaceholderView.h"
#import "JSQMessagesMediaViewBubbleImageMasker.h"

#import <MobileCoreServices/UTCoreTypes.h>

@interface JSQPhotoMediaItem ()

Expand Down Expand Up @@ -89,6 +90,16 @@ - (NSUInteger)mediaHash
return self.hash;
}

- (NSString *)mediaDataType
{
return (NSString *)kUTTypeJPEG;
}

- (id)mediaData
{
return UIImageJPEGRepresentation(self.image, 1);
}

#pragma mark - NSObject

- (NSUInteger)hash
Expand Down

0 comments on commit af36c20

Please sign in to comment.