Attachments handling

- Sends image rotated
- If message is delete, delete the attachment db object and file
- Delete attachment from detail view
This commit is contained in:
Frederic Jacobs 2014-12-26 23:18:54 +01:00
parent f2217cacd7
commit 402df72306
24 changed files with 275 additions and 81 deletions

View File

@ -348,6 +348,8 @@
B66DBF4A19D5BBC8006EA940 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B66DBF4919D5BBC8006EA940 /* Images.xcassets */; };
B67ADDC41989FF8700E1A773 /* RPServerRequestsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B67ADDC31989FF8700E1A773 /* RPServerRequestsManager.m */; };
B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; };
B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */; };
B68112ED1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m in Sources */ = {isa = PBXBuildFile; fileRef = B68112EC1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m */; };
B684A46D19C3446200B11029 /* PushManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = B684A46C19C3446200B11029 /* PushManagerTest.m */; };
B6850E5A1995A4710068E715 /* whisperFake.cer in Resources */ = {isa = PBXBuildFile; fileRef = B6850E591995A4710068E715 /* whisperFake.cer */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
@ -972,6 +974,10 @@
B67ADDC21989FF8700E1A773 /* RPServerRequestsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RPServerRequestsManager.h; sourceTree = "<group>"; };
B67ADDC31989FF8700E1A773 /* RPServerRequestsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RPServerRequestsManager.m; sourceTree = "<group>"; };
B67EBF5C19194AC60084CCFD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = SettingsBundle/Settings.bundle; sourceTree = SOURCE_ROOT; };
B68112E81A4D9EC400BA82FF /* UIImage+normalizeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+normalizeImage.h"; path = "util/UIImage+normalizeImage.h"; sourceTree = "<group>"; };
B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIImage+normalizeImage.m"; path = "util/UIImage+normalizeImage.m"; sourceTree = "<group>"; };
B68112EB1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "JSQMessagesCollectionViewCell+menuBarItems.h"; path = "views/JSQMessagesCollectionViewCell+menuBarItems.h"; sourceTree = "<group>"; };
B68112EC1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "JSQMessagesCollectionViewCell+menuBarItems.m"; path = "views/JSQMessagesCollectionViewCell+menuBarItems.m"; sourceTree = "<group>"; };
B684A46C19C3446200B11029 /* PushManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PushManagerTest.m; path = Signal/test/push/PushManagerTest.m; sourceTree = SOURCE_ROOT; };
B6850E591995A4710068E715 /* whisperFake.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = whisperFake.cer; sourceTree = "<group>"; };
B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
@ -2711,6 +2717,10 @@
FCFA64B31A24F3880007FB87 /* UIColor+OWS.m */,
FCFA64B51A24F6730007FB87 /* UIFont+OWS.h */,
FCFA64B61A24F6730007FB87 /* UIFont+OWS.m */,
B68112E81A4D9EC400BA82FF /* UIImage+normalizeImage.h */,
B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */,
B68112EB1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.h */,
B68112EC1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m */,
);
name = "UI Categories";
path = ..;
@ -3209,6 +3219,7 @@
76EB05EA18170B33006006FC /* CallProgress.m in Sources */,
FCFA64B41A24F3880007FB87 /* UIColor+OWS.m in Sources */,
76EB05C218170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */,
B68112ED1A4DA30300BA82FF /* JSQMessagesCollectionViewCell+menuBarItems.m in Sources */,
B6B096701A1D25ED008BFAA6 /* TSInfoMessage.m in Sources */,
B6C93C4E199567AD00EDF894 /* DebugLogger.m in Sources */,
76EB063218170B33006006FC /* Crc32.m in Sources */,
@ -3275,6 +3286,7 @@
B6B0968C1A1D25ED008BFAA6 /* TSDatabaseView.m in Sources */,
B6B0966A1A1D25ED008BFAA6 /* IncomingPushMessageSignal.pb.m in Sources */,
BFB074C919A5611000F2947C /* ObservableValue.m in Sources */,
B68112EA1A4D9EC400BA82FF /* UIImage+normalizeImage.m in Sources */,
B6B0968E1A1D25ED008BFAA6 /* TSStorageManager.m in Sources */,
FCB11D8A1A1284BB002F93FB /* SettingsTableViewCell.m in Sources */,
76EB05C818170B33006006FC /* HelloPacket.m in Sources */,

View File

@ -10,9 +10,10 @@ typedef NS_ENUM(NSUInteger, NotificationType) {
};
typedef NS_ENUM(NSUInteger, TSImageQuality) {
TSImageQualityHigh,
TSImageQualityMedium,
TSImageQualityLow
TSImageQualityUncropped = 1,
TSImageQualityHigh = 2,
TSImageQualityMedium = 3,
TSImageQualityLow = 4
};
@class PhoneNumber;

View File

@ -135,7 +135,7 @@
if (preference) {
return [preference unsignedIntegerValue];
} else {
return TSImageQualityMedium;
return TSImageQualityUncropped;
}
}

View File

@ -7,8 +7,6 @@
//
#import <Foundation/Foundation.h>
#import <YapDatabase/YapDatabaseRelationshipNode.h>
#import "TSYapDatabaseObject.h"
typedef NS_ENUM(NSInteger, TSLastActionType) {

View File

@ -8,7 +8,7 @@
#import "TSAttachment.h"
@interface TSAttachmentStream : TSAttachment
@interface TSAttachmentStream : TSAttachment <YapDatabaseRelationshipNode>
- (instancetype)initWithIdentifier:(NSString*)identifier
data:(NSData*)data

View File

@ -7,10 +7,13 @@
//
#import "TSAttachmentStream.h"
#import "UIImage+contentTypes.h"
NSString * const TSAttachementFileRelationshipEdge = @"TSAttachementFileEdge";
@interface TSAttachmentStream ()
@property (nonatomic) NSString *path;
@property (nonatomic) NSString *attachmentPath;
@end
@ -21,9 +24,8 @@
key:(NSData*)key
contentType:(NSString*)contentType{
self = [super initWithIdentifier:identifier encryptionKey:key contentType:contentType];
NSString *path = [self filePath];
[[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
[[NSFileManager defaultManager] createFileAtPath:_attachmentPath contents:data attributes:nil];
return self;
}
@ -32,10 +34,18 @@
return YES;
}
- (NSArray *)yapDatabaseRelationshipEdges {
YapDatabaseRelationshipEdge *attachmentFileEdge = [YapDatabaseRelationshipEdge edgeWithName:TSAttachementFileRelationshipEdge
destinationFilePath:[self filePath]
nodeDeleteRules:YDB_DeleteDestinationIfSourceDeleted];
return @[attachmentFileEdge];
}
+ (NSString*)attachmentsFolder {
NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL *fileURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString *path = [fileURL path];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL *fileURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString *path = [fileURL path];
NSString *attachmentFolder = [path stringByAppendingFormat:@"/Attachments"];
NSError * error = nil;
@ -46,7 +56,7 @@
if (error != nil) {
DDLogError(@"Failed to create attachments directory: %@", error.description);
}
return attachmentFolder;
}
@ -75,7 +85,7 @@
return nil;
}
return [UIImage imageWithContentsOfFile:[self filePath]];
return [UIImage imageWithContentsOfFile:self.filePath];
}
@end

View File

@ -33,6 +33,6 @@ typedef NS_ENUM(NSInteger, TSGroupMetaMessage){
- (void)addattachments:(NSArray*)attachments;
- (void)addattachment:(NSString*)attachment;
- (BOOL)hasattachments;
- (BOOL)hasAttachments;
@end

View File

@ -7,7 +7,9 @@
//
#import "TSMessage.h"
#import "TSAttachment.h"
NSString * const TSAttachementsRelationshipEdgeName = @"TSAttachmentEdge";
@implementation TSMessage
@ -25,10 +27,25 @@
[self.attachments addObject:attachment];
}
- (NSArray *)yapDatabaseRelationshipEdges {
NSMutableArray *edges = [[super yapDatabaseRelationshipEdges] mutableCopy];
if ([self hasAttachments]) {
for (NSString *attachmentId in self.attachments) {
YapDatabaseRelationshipEdge *fileEdge = [[YapDatabaseRelationshipEdge alloc] initWithName:TSAttachementsRelationshipEdgeName
destinationKey:attachmentId
collection:[TSAttachment collection]
nodeDeleteRules:YDB_DeleteDestinationIfAllSourcesDeleted];
[edges addObject:fileEdge];
}
}
return edges;
}
- (instancetype)initWithTimestamp:(uint64_t)timestamp
inThread:(TSThread*)thread
messageBody:(NSString*)body
attachments:(NSArray*)attachments
attachments:(NSArray*)attachments
{
self = [super initWithTimestamp:timestamp inThread:thread];
@ -39,13 +56,13 @@
return self;
}
- (BOOL)hasattachments{
- (BOOL)hasAttachments{
return self.attachments?(self.attachments.count>0):false;
}
- (NSString *)description{
if(self.attachments > 0){
return @"attachment";
return @"Attachment";
} else {
return self.body;
}

View File

@ -46,6 +46,7 @@ dispatch_queue_t attachmentsQueue() {
for (PushMessageContentAttachmentPointer *pointer in content.attachments) {
TSAttachmentPointer *attachmentPointer = [[TSAttachmentPointer alloc] initWithIdentifier:pointer.id key:pointer.key contentType:pointer.contentType relay:message.relay];
[attachmentPointer saveWithTransaction:transaction];
dispatch_async(attachmentsQueue(), ^{
[self retrieveAttachment:attachmentPointer];
});
@ -57,7 +58,7 @@ dispatch_queue_t attachmentsQueue() {
}
- (void)sendAttachment:(NSData*)attachmentData contentType:(NSString*)contentType thread:(TSThread*)thread {
TSRequest *allocateAttachment = [[TSAllocAttachmentRequest alloc] init];
[[TSNetworkManager sharedManager] queueAuthenticatedRequest:allocateAttachment success:^(NSURLSessionDataTask *task, id responseObject) {
dispatch_async(attachmentsQueue(), ^{
@ -174,4 +175,5 @@ dispatch_queue_t attachmentsQueue() {
return success;
}
@end

View File

@ -0,0 +1,15 @@
//
// UIImage+normalizeImage.h
// Signal
//
// Created by Frederic Jacobs on 26/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIImage (normalizeImage)
- (UIImage *)normalizedImage;
@end

View File

@ -0,0 +1,23 @@
//
// UIImage+normalizeImage.m
// Signal
//
// Created by Frederic Jacobs on 26/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "UIImage+normalizeImage.h"
@implementation UIImage (normalizeImage)
- (UIImage *)normalizedImage {
if (self.imageOrientation == UIImageOrientationUp) return self;
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
[self drawInRect:(CGRect){0, 0, self.size}];
UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return normalizedImage;
}
@end

View File

@ -2,6 +2,8 @@
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIImage+normalizeImage.h"
#import "UIImage+contentTypes.h"
/**
*

View File

@ -4,7 +4,6 @@
@implementation UIUtil
+ (void)applyRoundedBorderToImageView:(UIImageView *__strong*)imageView {
[[*imageView layer] setBorderWidth:CONTACT_PICTURE_VIEW_BORDER_WIDTH];
[[*imageView layer] setBorderColor:[[UIColor lightGrayColor] CGColor]];

View File

@ -7,11 +7,13 @@
//
#import <UIKit/UIKit.h>
#import "TSAttachmentStream.h"
#import "TSInteraction.h"
@interface FullImageViewController : UIViewController
- (instancetype)initWithImage:(UIImage*)image fromRect:(CGRect)rect;
- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment fromRect:(CGRect)rect forInteraction:(TSInteraction*)interaction;
-(void)presentFromViewController:(UIViewController*)viewController;
- (void)presentFromViewController:(UIViewController*)viewController;
@end

View File

@ -8,6 +8,7 @@
#import "FullImageViewController.h"
#import "DJWActionSheet.h"
#import "TSAttachmentStream.h"
#define kImageViewCornerRadius 5.0f
@ -24,7 +25,6 @@
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIImage* image;
@property (nonatomic, strong) UITapGestureRecognizer *singleTap;
@property (nonatomic, strong) UITapGestureRecognizer *doubleTap;
@ -34,23 +34,31 @@
@property CGRect originRect;
@property BOOL isPresenting;
@property TSAttachmentStream *attachment;
@property TSInteraction *interaction;
@end
@implementation FullImageViewController
- (instancetype)initWithImage:(UIImage*)image fromRect:(CGRect)rect {
- (instancetype)initWithAttachment:(TSAttachmentStream*)attachment fromRect:(CGRect)rect forInteraction:(TSInteraction*)interaction {
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.image = image;
self.imageView.image = image;
self.originRect = rect;
self.attachment = attachment;
self.imageView.image = self.image;
self.originRect = rect;
self.interaction = interaction;
}
return self;
}
- (UIImage*)image{
return self.attachment.image;
}
- (void)viewDidLoad {
[super viewDidLoad];
@ -353,11 +361,14 @@
{
[DJWActionSheet showInView:self.view withTitle:nil cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete" otherButtonTitles:@[@"Save to Camera Roll", @"Copy"] tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex){
__block TSInteraction *interaction = [self interaction];
[self dismissViewControllerAnimated:YES completion:^{
[interaction remove];
}];
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
#warning Unimplemented deleting attachments from FullImageView
NSLog(@"Destructive button tapped");
}else {
} else {
switch (tappedButtonIndex) {
case 0:
UIImageWriteToSavedPhotosAlbum(self.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

View File

@ -11,11 +11,12 @@
#import "GroupModel.h"
@class TSThread;
@interface MessagesViewController : JSQMessagesViewController <UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@interface MessagesViewController : JSQMessagesViewController <UIImagePickerControllerDelegate,
UINavigationControllerDelegate,
UITextViewDelegate>
- (void)setupWithThread:(TSThread*)thread;
- (void)setupWithTSIdentifier:(NSString*)identifier;
- (void)setupWithTSGroup:(GroupModel*)model;
@end

View File

@ -133,7 +133,6 @@ typedef enum : NSUInteger {
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.automaticallyScrollsToMostRecentMessage = YES;
[self scrollToBottomAnimated:NO];
}
@ -164,7 +163,7 @@ typedef enum : NSUInteger {
-(void)initializeNavigationBar
{
self.title = self.thread.name;
if (!isGroupConversation && [self isRedPhoneReachable]) {
UIBarButtonItem * lockButton = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"lock"] style:UIBarButtonItemStylePlain target:self action:@selector(showFingerprint)];
UIBarButtonItem * callButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"call_tab"] style:UIBarButtonItemStylePlain target:self action:@selector(callAction)];
@ -197,7 +196,7 @@ typedef enum : NSUInteger {
self.collectionView.showsVerticalScrollIndicator = NO;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.automaticallyScrollsToMostRecentMessage = NO;
self.automaticallyScrollsToMostRecentMessage = YES;
self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
@ -298,24 +297,18 @@ typedef enum : NSUInteger {
switch (msg.messageType) {
case TSIncomingMessageAdapter:
return [self loadIncomingMessageCellForMessage:msg atIndexPath:indexPath];
break;
case TSOutgoingMessageAdapter:
return [self loadOutgoingCellForMessage:msg atIndexPath:indexPath];
break;
case TSCallAdapter:
return [self loadCallCellForCall:msg atIndexPath:indexPath];
break;
case TSInfoMessageAdapter:
return [self loadInfoMessageCellForMessage:msg atIndexPath:indexPath];
break;
case TSErrorMessageAdapter:
return [self loadErrorMessageCellForMessage:msg atIndexPath:indexPath];
break;
default:
NSLog(@"Something went wrong");
return nil;
break;
}
}
@ -325,7 +318,8 @@ typedef enum : NSUInteger {
{
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
if (!message.isMediaMessage) {
cell.textView.textColor = [UIColor blackColor];
cell.textView.textColor = [UIColor blackColor];
cell.textView.selectable = NO;
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
}
@ -338,7 +332,8 @@ typedef enum : NSUInteger {
JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:self.collectionView cellForItemAtIndexPath:indexPath];
if (!message.isMediaMessage)
{
cell.textView.textColor = [UIColor whiteColor];
cell.textView.textColor = [UIColor whiteColor];
cell.textView.selectable = NO;
cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
}
@ -497,6 +492,7 @@ typedef enum : NSUInteger {
TSMessageAdapter *messageItem = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];
TSInteraction *interaction = [self interactionAtIndexPath:indexPath];
switch (messageItem.messageType) {
case TSOutgoingMessageAdapter:
if (messageItem.messageState == TSOutgoingMessageStateUnsent) {
@ -507,15 +503,21 @@ typedef enum : NSUInteger {
BOOL isMediaMessage = [messageItem isMediaMessage];
if (isMediaMessage) {
TSAttachmentAdapter * messageMedia = (TSAttachmentAdapter*)[messageItem media];
TSAttachmentAdapter* messageMedia = (TSAttachmentAdapter*)[messageItem media];
if ([messageMedia isImage]) {
//is a photo
tappedImage = ((UIImageView*)[messageMedia mediaView]).image ;
tappedImage = ((UIImageView*)[messageMedia mediaView]).image;
CGRect convertedRect = [self.collectionView convertRect:[collectionView cellForItemAtIndexPath:indexPath].frame toView:nil];
FullImageViewController * vc = [[FullImageViewController alloc]initWithImage:tappedImage fromRect:convertedRect];
[vc presentFromViewController:self];
__block TSAttachment *attachment = nil;
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
attachment = [TSAttachment fetchObjectWithUniqueID:messageMedia.attachmentId transaction:transaction];
}];
if ([attachment isKindOfClass:[TSAttachmentStream class]]) {
TSAttachmentStream *attStream = (TSAttachmentStream*)attachment;
FullImageViewController * vc = [[FullImageViewController alloc] initWithAttachment:attStream fromRect:convertedRect forInteraction:[self interactionAtIndexPath:indexPath]];
[vc presentFromViewController:self];
}
} else {
DDLogWarn(@"Currently unsupported");
}
@ -550,6 +552,13 @@ typedef enum : NSUInteger {
}];
}
- (void)deleteMessageAtIndexPath:(NSIndexPath*)indexPath {
[self.editingDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
TSInteraction *interaction = [self interactionAtIndexPath:indexPath];
[interaction removeWithTransaction:transaction];
}];
}
- (void)handleErrorMessageTap:(TSErrorMessage*)message{
if (message.errorType == TSErrorMessageWrongTrustedIdentityKey) {
NSString *newKeyFingerprint = [message newIdentityKey];
@ -615,9 +624,8 @@ typedef enum : NSUInteger {
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera])
{
picker.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *)kUTTypeMovie, kUTTypeImage, kUTTypeVideo, nil];
UIImagePickerControllerSourceTypeCamera]) {
picker.mediaTypes = @[(NSString*)kUTTypeImage];
[self presentViewController:picker animated:YES completion:NULL];
}
@ -655,7 +663,7 @@ typedef enum : NSUInteger {
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *picture_camera = [info objectForKey:UIImagePickerControllerOriginalImage];
UIImage *picture_camera = [[info objectForKey:UIImagePickerControllerOriginalImage] normalizedImage];
NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
@ -680,6 +688,9 @@ typedef enum : NSUInteger {
{
CGFloat correctedWidth;
switch ([Environment.preferences imageUploadQuality]) {
case TSImageQualityUncropped:
return image;
case TSImageQualityHigh:
correctedWidth = 2048;
break;
@ -721,15 +732,14 @@ typedef enum : NSUInteger {
-(CGFloat)compressionRate
{
switch ([Environment.preferences imageUploadQuality]) {
case TSImageQualityUncropped:
return 1;
case TSImageQualityHigh:
return 0.9f;
break;
case TSImageQualityMedium:
return 0.5f;
break;
case TSImageQualityLow:
return 0.3f;
break;
default:
break;
}
@ -853,7 +863,7 @@ typedef enum : NSUInteger {
withTitle:nil
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@[@"Update group", @"Leave group", @"Delete thread"]
otherButtonTitles:@[@"Update group", @"Leave group"]
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
NSLog(@"User Cancelled");
@ -867,12 +877,9 @@ typedef enum : NSUInteger {
break;
case 1:
DDLogDebug(@"leave group picket");
DDLogDebug(@"leave group picked");
break;
case 2:
DDLogDebug(@"delete thread");
break;
default:
break;
}
@ -893,12 +900,12 @@ typedef enum : NSUInteger {
withTitle:nil
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@[@"Take Photo or Video", @"Choose existing Photo", @"Choose existing Video", @"Send file"]
otherButtonTitles:@[@"Take Photo", @"Choose existing Photo"]
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
NSLog(@"User Cancelled");
DDLogVerbose(@"User Cancelled");
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
NSLog(@"Destructive button tapped");
DDLogVerbose(@"Destructive button tapped");
}else {
switch (tappedButtonIndex) {
case 0:
@ -907,10 +914,6 @@ typedef enum : NSUInteger {
case 1:
[self chooseFromLibrary:kMediaTypePicture];
break;
case 2:
[self chooseFromLibrary:kMediaTypeVideo];
break;
default:
break;
}
@ -932,6 +935,26 @@ typedef enum : NSUInteger {
}];
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(delete:)) {
return YES;
}
return [super collectionView:collectionView canPerformAction:action forItemAtIndexPath:indexPath withSender:sender];
}
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(delete:)) {
[self deleteMessageAtIndexPath:indexPath];
}
else {
[super collectionView:collectionView performAction:action forItemAtIndexPath:indexPath withSender:sender];
}
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

View File

@ -43,6 +43,9 @@
-(void)updateImageQualityLabel
{
switch ([Environment.preferences imageUploadQuality]) {
case TSImageQualityUncropped:
self.detailLabel.text = @"Full";
break;
case TSImageQualityHigh:
self.detailLabel.text = @"High";
break;

View File

@ -125,7 +125,7 @@ typedef enum {
withTitle:nil
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@[@"High", @"Medium", @"Low"]
otherButtonTitles:@[@"Uncompressed", @"High", @"Medium", @"Low"]
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
@ -136,12 +136,15 @@ typedef enum {
}else {
switch (tappedButtonIndex) {
case 0:
[Environment.preferences setImageUploadQuality:TSImageQualityHigh];
[Environment.preferences setImageUploadQuality:TSImageQualityUncropped];
break;
case 1:
[Environment.preferences setImageUploadQuality:TSImageQualityMedium];
[Environment.preferences setImageUploadQuality:TSImageQualityHigh];
break;
case 2:
[Environment.preferences setImageUploadQuality:TSImageQualityMedium];
break;
case 3:
[Environment.preferences setImageUploadQuality:TSImageQualityLow];
break;
default:

View File

@ -16,4 +16,6 @@
- (BOOL)isImage;
@property NSString *attachmentId;
@end

View File

@ -16,8 +16,6 @@
@property UIImage *image;
@property (strong, nonatomic) UIImageView *cachedImageView;
@property (assign, nonatomic, readonly) BOOL isImageAttachment;
@end
@implementation TSAttachmentAdapter
@ -26,9 +24,9 @@
self = [super init];
if (self) {
_image = [UIImage imageWithCGImage:attachment.image.CGImage];
_image = attachment.image;
_cachedImageView = nil;
_isImageAttachment = YES;
_attachmentId = attachment.uniqueId;
}
return self;
}
@ -73,7 +71,7 @@
-(BOOL)isImage
{
return _isImageAttachment;
return YES;
}
#pragma mark - Utility
@ -100,7 +98,6 @@
return ratio > 1.0f ? [self smallPortraitSize] : [self smallLandscapeSize];
}
- (CGSize)largePortraitSize
{
return CGSizeMake(220.0f, 310.0f);

View File

@ -15,6 +15,7 @@
#import "TSattachment.h"
#import "TSAttachmentStream.h"
#import "TSAttachmentAdapter.h"
#import "TSAttachmentPointer.h"
@interface TSMessageAdapter ()
@ -92,13 +93,23 @@
for (NSString *attachmentID in message.attachments) {
TSAttachment *attachment = [TSAttachment fetchObjectWithUniqueID:attachmentID];
if ([attachment isKindOfClass:[TSAttachmentStream class]]) {
TSAttachmentStream *stream = (TSAttachmentStream*)attachment;
if ([stream isImage]) {
adapter.mediaItem = [[TSAttachmentAdapter alloc] initWithAttachment:stream];
adapter.mediaItem.appliesMediaViewMaskAsOutgoing = [interaction isKindOfClass:[TSOutgoingMessage class]];
break;
} else {
DDLogWarn(@"We have a TSAttachmentStream for an unsupported media type");
}
} else if ([attachment isKindOfClass:[TSAttachmentPointer class]]){
//TSAttachmentPointer *pointer = (TSAttachmentPointer*)attachment;
//TODO: Change this status when download failed;
adapter.messageBody = @"Attachment is downloading";
adapter.messageType = TSInfoMessageAdapter;
} else {
DDLogError(@"We retreived an attachment that doesn't have a known type : %@", NSStringFromClass([attachment class]));
}
}
}

View File

@ -0,0 +1,13 @@
//
// JSQMessagesCollectionViewCell+menuBarItems.h
// Signal
//
// Created by Frederic Jacobs on 26/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "JSQMessagesCollectionViewCell.h"
@interface JSQMessagesCollectionViewCell (menuBarItems)
@end

View File

@ -0,0 +1,49 @@
//
// JSQMessagesCollectionViewCell+menuBarItems.m
// Signal
//
// Created by Frederic Jacobs on 26/12/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "JSQMessagesCollectionViewCell+menuBarItems.h"
@implementation JSQMessagesCollectionViewCell (menuBarItems)
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(delete:)) {
return YES;
}
return [super canPerformAction:action withSender:sender];
}
- (void)delete:(id)sender
{
[self performSelectorOnParentCollectionView:@selector(delete:)
withSender:sender];
}
- (void)performSelectorOnParentCollectionView:(SEL)selector
withSender:(id)sender {
UIView *view = self;
do {
view = view.superview;
} while (![view isKindOfClass:[UICollectionView class]]);
UICollectionView *collectionView = (UICollectionView *)view;
NSIndexPath *indexPath = [collectionView indexPathForCell:self];
if (collectionView.delegate &&
[collectionView.delegate respondsToSelector:@selector(collectionView:
performAction:
forItemAtIndexPath:
withSender:)])
[collectionView.delegate collectionView:collectionView
performAction:selector
forItemAtIndexPath:indexPath
withSender:sender];
}
@end