diff --git a/CHANGELOG.md b/CHANGELOG.md
index c022d5967..e28ff95f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@ Group changes to describe their impact on the project, as follows:
### Added
- Auto-layout of images in chat messages
+- Selection of multiple images to send in a chat message
+- Sending text with image
- Latest Calls widget
- Latest Chatrooms widget
- Homescreen quick action : New message
diff --git a/Classes/Base.lproj/ChatConversationView.xib b/Classes/Base.lproj/ChatConversationView.xib
index 604c03dc1..90c5815cd 100644
--- a/Classes/Base.lproj/ChatConversationView.xib
+++ b/Classes/Base.lproj/ChatConversationView.xib
@@ -18,6 +18,8 @@
+
+
@@ -269,6 +271,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Classes/ChatConversationView.h b/Classes/ChatConversationView.h
index 7a264ca8e..0a2f99c0c 100644
--- a/Classes/ChatConversationView.h
+++ b/Classes/ChatConversationView.h
@@ -27,12 +27,13 @@
#import "UIRoundedImageView.h"
#import "UIBackToCallButton.h"
#import "Utils/HPGrowingTextView/HPGrowingTextView.h"
+#import "UIImageViewDeletable.h"
#include "linphone/linphonecore.h"
@interface ChatConversationView
: TPMultiLayoutViewController {
+ UIDocumentInteractionControllerDelegate, UISearchBarDelegate, UIImageViewDeletableDelegate, UICollectionViewDataSource> {
OrderedDictionary *imageQualities;
BOOL scrollOnGrowingEnabled;
BOOL composingVisible;
@@ -60,6 +61,12 @@
@property (weak, nonatomic) IBOutlet UIIconButton *infoButton;
@property (weak, nonatomic) IBOutlet UILabel *particpantsLabel;
@property (nonatomic, strong) UIDocumentInteractionController *documentInteractionController;
+@property NSMutableArray *imagesArray;
+@property NSMutableArray *assetIdsArray;
+@property NSMutableArray *qualitySettingsArray;
+@property (weak, nonatomic) IBOutlet UICollectionView *imagesCollectionView;
+@property (weak, nonatomic) IBOutlet UIView *imagesView;
+
+ (void)markAsRead:(LinphoneChatRoom *)chatRoom;
- (void)configureForRoom:(BOOL)editing;
@@ -74,5 +81,6 @@
- (IBAction)onEditionChangeClick:(id)sender;
- (void)update;
- (void)openResults:(NSString *) filePath;
+- (void)clearMessageView;
@end
diff --git a/Classes/ChatConversationView.m b/Classes/ChatConversationView.m
index 54077999b..09acbb8f8 100644
--- a/Classes/ChatConversationView.m
+++ b/Classes/ChatConversationView.m
@@ -101,6 +101,8 @@ static UICompositeViewDescription *compositeDescription = nil;
_messageField.contentInset = UIEdgeInsetsMake(-15, 0, 0, 0);
// _messageField.internalTextView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 0, 10);
[_tableController setChatRoomDelegate:self];
+ [_imagesCollectionView registerClass:[UIImageViewDeletable class] forCellWithReuseIdentifier:NSStringFromClass([UIImageViewDeletable class])];
+ [_imagesCollectionView setDataSource:self];
}
- (void)viewWillAppear:(BOOL)animated {
@@ -125,6 +127,24 @@ static UICompositeViewDescription *compositeDescription = nil;
selector:@selector(callUpdateEvent:)
name:kLinphoneCallUpdate
object:nil];
+
+ if ([_imagesArray count] > 0) {
+ [UIView animateWithDuration:0
+ delay:0
+ options:UIViewAnimationOptionBeginFromCurrentState
+ animations:^{
+ // resizing imagesView
+ CGRect imagesFrame = [_imagesView frame];
+ imagesFrame.origin.y = [_messageView frame].origin.y - 100;
+ imagesFrame.size.height = 100;
+ [_imagesView setFrame:imagesFrame];
+ // resizing chatTable
+ CGRect tableViewFrame = [_tableController.tableView frame];
+ tableViewFrame.size.height -= 100;
+ [_tableController.tableView setFrame:tableViewFrame];
+ }
+ completion:nil];
+ }
}
- (void)viewWillDisappear:(BOOL)animated {
@@ -153,6 +173,7 @@ static UICompositeViewDescription *compositeDescription = nil;
[self configureForRoom:true];
_backButton.hidden = _tableController.isEditing;
[_tableController scrollToBottom:true];
+ [self refreshImageDrawer];
}
#pragma mark -
@@ -203,7 +224,6 @@ static UICompositeViewDescription *compositeDescription = nil;
_messageField.editable = !linphone_chat_room_has_been_left(_chatRoom);
_pictureButton.enabled = !linphone_chat_room_has_been_left(_chatRoom);
_messageView.userInteractionEnabled = !linphone_chat_room_has_been_left(_chatRoom);
- [_messageField setText:@""];
[_tableController setChatRoom:_chatRoom];
_chatView.hidden = NO;
@@ -222,7 +242,12 @@ static UICompositeViewDescription *compositeDescription = nil;
//share photo
NSData *data = dict[@"nsData"];
UIImage *image = [[UIImage alloc] initWithData:data];
- [self chooseImageQuality:image assetId:nil];
+ NSString *filename = dict[@"url"];
+ if (filename) {
+ NSMutableDictionary * assetDict = [LinphoneUtils photoAssetsDictionary];
+ [self chooseImageQuality:image assetId:[[assetDict objectForKey:filename] localIdentifier]];
+ } else
+ [self chooseImageQuality:image assetId:@""];
[defaults removeObjectForKey:@"img"];
} else if (dictWeb) {
//share url, if local file, then upload file
@@ -311,7 +336,11 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (void)saveAndSend:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality{
- [self startImageUpload:image assetId:phAssetId withQuality:quality];
+
+ [_imagesArray addObject:image];
+ [_assetIdsArray addObject:phAssetId];
+ [_qualitySettingsArray addObject:@(quality)];
+ [self refreshImageDrawer];
}
- (void)chooseImageQuality:(UIImage *)image assetId:(NSString *)phAssetId {
@@ -456,6 +485,12 @@ static UICompositeViewDescription *compositeDescription = nil;
messageRect.size.height += diff;
[_messageView setFrame:messageRect];
+ if ([_imagesArray count] > 0) {
+ CGRect _imagesRect = [_imagesView frame];
+ _imagesRect.origin.y -= diff;
+ [_imagesView setFrame:_imagesRect];
+ }
+
// Always stay at bottom
if (scrollOnGrowingEnabled) {
CGRect tableFrame = [_tableController.view frame];
@@ -493,6 +528,15 @@ static UICompositeViewDescription *compositeDescription = nil;
}
- (IBAction)onSendClick:(id)event {
+ if ([_imagesArray count] > 0) {
+ int i = 0;
+ for (i = 0; i < [_imagesArray count] - 1; ++i) {
+ [self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue];
+ }
+ [self startImageUpload:[_imagesArray objectAtIndex:i] assetId:[_assetIdsArray objectAtIndex:i] withQuality:[_qualitySettingsArray objectAtIndex:i].floatValue andMessage:[self.messageField text]];
+ [self clearMessageView];
+ return;
+ }
if ([self sendMessage:[_messageField text] withExterlBodyUrl:nil withInternalURL:nil]) {
scrollOnGrowingEnabled = FALSE;
[_messageField setText:@""];
@@ -583,6 +627,14 @@ static UICompositeViewDescription *compositeDescription = nil;
return TRUE;
}
+- (BOOL)startImageUpload:(UIImage *)image assetId:(NSString *)phAssetId withQuality:(float)quality andMessage:(NSString *)message {
+ FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
+ [fileTransfer setText:message];
+ [fileTransfer upload:image withassetId:phAssetId forChatRoom:_chatRoom withQuality:quality];
+ [_tableController scrollToBottom:true];
+ return TRUE;
+}
+
- (BOOL)startFileUpload:(NSData *)data withUrl:(NSURL *)url {
FileTransferDelegate *fileTransfer = [[FileTransferDelegate alloc] init];
[fileTransfer uploadFile:data forChatRoom:_chatRoom withUrl:url];
@@ -624,6 +676,9 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)keyboardWillHide:(NSNotification *)notif {
NSTimeInterval duration = [[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
+
+ int heightDiff = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? 55 : 105;
+
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
@@ -667,6 +722,19 @@ static UICompositeViewDescription *compositeDescription = nil;
}
}
}
+
+
+ if ([_imagesArray count] > 0){
+ // resizing imagesView
+ CGRect imagesFrame = [_imagesView frame];
+ imagesFrame.origin.y = [_messageView frame].origin.y - heightDiff;
+ imagesFrame.size.height = heightDiff;
+ [_imagesView setFrame:imagesFrame];
+ // resizing chatTable
+ CGRect tableViewFrame = [_tableController.tableView frame];
+ tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
+ [_tableController.tableView setFrame:tableViewFrame];
+ }
}
completion:^(BOOL finished){
@@ -675,7 +743,9 @@ static UICompositeViewDescription *compositeDescription = nil;
- (void)keyboardWillShow:(NSNotification *)notif {
NSTimeInterval duration = [[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
-
+
+ int heightDiff = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? 55 : 105;
+
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
@@ -722,6 +792,18 @@ static UICompositeViewDescription *compositeDescription = nil;
[_messageView frame].origin.y - tableFrame.origin.y - composeIndicatorCompensation;
[_tableController.view setFrame:tableFrame];
}
+
+ if ([_imagesArray count] > 0){
+ // resizing imagesView
+ CGRect imagesFrame = [_imagesView frame];
+ imagesFrame.origin.y = [_messageView frame].origin.y - heightDiff;
+ imagesFrame.size.height = heightDiff;
+ [_imagesView setFrame:imagesFrame];
+ // resizing chatTable
+ CGRect tableViewFrame = [_tableController.tableView frame];
+ tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
+ [_tableController.tableView setFrame:tableViewFrame];
+ }
// Scroll
NSInteger lastSection = [_tableController.tableView numberOfSections] - 1;
@@ -734,8 +816,10 @@ static UICompositeViewDescription *compositeDescription = nil;
animated:FALSE];
}
}
+
}
completion:^(BOOL finished){
+
}];
}
@@ -839,4 +923,80 @@ void on_chat_room_conference_left(LinphoneChatRoom *cr, const LinphoneEventLog *
}
}
+- (void)deleteImageWithAssetId:(NSString *)assetId {
+ NSUInteger key = [_assetIdsArray indexOfObject:assetId];
+ [_imagesArray removeObjectAtIndex:key];
+ [_assetIdsArray removeObjectAtIndex:key];
+ [self refreshImageDrawer];
+}
+
+- (void)clearMessageView {
+ [_messageField setText:@""];
+ _imagesArray = [NSMutableArray array];
+ _assetIdsArray = [NSMutableArray array];
+
+ [self refreshImageDrawer];
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+ return [_imagesArray count];
+}
+
+- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+ UIImageViewDeletable *imgView = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([UIImageViewDeletable class]) forIndexPath:indexPath];
+ CGRect imgFrame = imgView.frame;
+ imgFrame.origin.y = 5;
+ if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
+ imgFrame.size.height = 50;
+ } else {
+ imgFrame.size.height = 100;
+ }
+ [imgView.image setImage:[UIImage resizeImage:[_imagesArray objectAtIndex:[indexPath item]] withMaxWidth:imgFrame.size.width andMaxHeight:imgFrame.size.height]];
+ [imgView setAssetId:[_assetIdsArray objectAtIndex:[indexPath item]]];
+ [imgView setDeleteDelegate:self];
+ [imgView setFrame:imgFrame];
+ [_sendButton setEnabled:TRUE];
+ return imgView;
+}
+
+- (void)refreshImageDrawer {
+ int heightDiff = UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) ? 55 : 105;
+
+ if ([_imagesArray count] == 0) {
+ [UIView animateWithDuration:0
+ delay:0
+ options:UIViewAnimationOptionBeginFromCurrentState
+ animations:^{
+ // resizing imagesView
+ CGRect imagesFrame = [_imagesView frame];
+ imagesFrame.origin.y = [_messageView frame].origin.y;
+ imagesFrame.size.height = 0;
+ [_imagesView setFrame:imagesFrame];
+ // resizing chatTable
+ CGRect tableViewFrame = [_tableController.tableView frame];
+ tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
+ [_tableController.tableView setFrame:tableViewFrame];
+ }
+ completion:nil];
+ if ([_messageField.text isEqualToString:@""])
+ [_sendButton setEnabled:FALSE];
+ } else {
+ [UIView animateWithDuration:0
+ delay:0
+ options:UIViewAnimationOptionBeginFromCurrentState
+ animations:^{
+ // resizing imagesView
+ CGRect imagesFrame = [_imagesView frame];
+ imagesFrame.origin.y = [_messageView frame].origin.y - heightDiff;
+ imagesFrame.size.height = heightDiff;
+ [_imagesView setFrame:imagesFrame];
+ // resizing chatTable
+ CGRect tableViewFrame = [_tableController.tableView frame];
+ tableViewFrame.size.height = imagesFrame.origin.y - tableViewFrame.origin.y;
+ [_tableController.tableView setFrame:tableViewFrame];
+ }
+ completion:^(BOOL result){[_imagesCollectionView reloadData];}];
+ }
+}
+
@end
diff --git a/Classes/LinphoneUI/Base.lproj/UIChatBubblePhotoCell.xib b/Classes/LinphoneUI/Base.lproj/UIChatBubblePhotoCell.xib
index ec2e12142..50403d66f 100644
--- a/Classes/LinphoneUI/Base.lproj/UIChatBubblePhotoCell.xib
+++ b/Classes/LinphoneUI/Base.lproj/UIChatBubblePhotoCell.xib
@@ -28,6 +28,7 @@
+
@@ -37,15 +38,15 @@
-
+
-
+
-
+
@@ -65,11 +66,11 @@
-
+
-
+
@@ -82,15 +83,15 @@
-
+
-
+
-
-
+
+
-
+
@@ -147,7 +148,7 @@
-
+
@@ -159,15 +160,22 @@
+
+
+
+
+
+
+
-
+
@@ -180,7 +188,7 @@
-
+
diff --git a/Classes/LinphoneUI/Base.lproj/UIChatBubbleTextCell.xib b/Classes/LinphoneUI/Base.lproj/UIChatBubbleTextCell.xib
index d268ae5b5..3540175ea 100644
--- a/Classes/LinphoneUI/Base.lproj/UIChatBubbleTextCell.xib
+++ b/Classes/LinphoneUI/Base.lproj/UIChatBubbleTextCell.xib
@@ -1,11 +1,11 @@
-
+
-
+
diff --git a/Classes/LinphoneUI/UIChatBubblePhotoCell.m b/Classes/LinphoneUI/UIChatBubblePhotoCell.m
index 99c85c91e..b10d52f2e 100644
--- a/Classes/LinphoneUI/UIChatBubblePhotoCell.m
+++ b/Classes/LinphoneUI/UIChatBubblePhotoCell.m
@@ -38,7 +38,6 @@
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
- // TODO: remove text cell subview
NSArray *arrayOfViews =
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
// resize cell to match .nib size. It is needed when resized the cell to
@@ -119,7 +118,7 @@
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:options
resultHandler:^(UIImage *image, NSDictionary * info) {
if (image) {
- imageSize = [UIChatBubbleTextCell getMediaMessageSizefromOriginalSize:[image size] withWidth:chatTableView.tableView.frame.size.width];
+ imageSize = [UIChatBubbleTextCell getMediaMessageSizefromOriginalSize:[image size] withWidth:chatTableView.tableView.frame.size.width - 40];
UIImage *newImage = [UIImage UIImageResize:image toSize:imageSize];
[chatTableView.imagesInChatroom setObject:newImage forKey:[asset localIdentifier]];
[self loadImageAsset:asset image:newImage];
@@ -167,13 +166,25 @@
});
}
+- (void) loadPlaceholder {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // Change this to load placeholder image when no asset id
+ //[_finalImage setImage:image];
+ //[_messageImageView setAsset:asset];
+ [_messageImageView stopLoading];
+ _messageImageView.hidden = YES;
+ _imageGestureRecognizer.enabled = YES;
+ _finalImage.hidden = NO;
+ [self layoutSubviews];
+ });
+}
+
- (void)update {
if (self.message == nil) {
LOGW(@"Cannot update message room cell: NULL message");
return;
}
- [super update];
-
+ [super update];
const char *url = linphone_chat_message_get_external_body_url(self.message);
BOOL is_external =
(url && (strstr(url, "http") == url)) || linphone_chat_message_get_file_transfer_information(self.message);
@@ -203,7 +214,7 @@
PHFetchResult *assets = [PHAsset fetchAssetsWithLocalIdentifiers:[NSArray arrayWithObject:localImage] options:nil];
UIImage *img = [chatTableView.imagesInChatroom objectForKey:localImage];
if (![assets firstObject])
- return;
+ [self loadPlaceholder];
PHAsset *asset = [assets firstObject];
if (img)
[self loadImageAsset:asset image:img];
@@ -397,7 +408,6 @@
}
- (void)layoutSubviews {
- //[super layoutSubviews];
BOOL is_outgoing = linphone_chat_message_is_outgoing(super.message);
CGRect bubbleFrame = super.bubbleView.frame;
int origin_x;
@@ -415,6 +425,28 @@
bubbleFrame.origin.x = origin_x;
super.bubbleView.frame = bubbleFrame;
+
+ // Resizing Image view
+ if (_finalImage.image) {
+ CGRect imgFrame = self.finalAssetView.frame;
+ imgFrame.size = [UIChatBubbleTextCell getMediaMessageSizefromOriginalSize:[_finalImage.image size] withWidth:chatTableView.tableView.frame.size.width - 40];
+ imgFrame.origin.x = (bubbleFrame.size.width - imgFrame.size.width)/2;
+ self.finalAssetView.frame = imgFrame;
+
+ // Positioning text message
+ const char *utf8Text = linphone_chat_message_get_text_content(self.message);
+
+ CGRect textFrame = self.messageText.frame;
+ textFrame.origin = CGPointMake(textFrame.origin.x, self.finalAssetView.frame.origin.y + self.finalAssetView.frame.size.height);
+ if (!utf8Text) {
+ textFrame.size.height = 0;
+ } else {
+ textFrame.size.height = bubbleFrame.size.height - textFrame.origin.x;
+ }
+
+ self.messageText.frame = textFrame;
+ LOGD([NSString stringWithFormat:@"Text of the photoCell: %@, size of the text of the photoCell: %@", [self.messageText text], NSStringFromCGSize(textFrame.size)]);
+ }
}
@end
diff --git a/Classes/LinphoneUI/UIChatBubbleTextCell.h b/Classes/LinphoneUI/UIChatBubbleTextCell.h
index 26966cbb5..18f5d879c 100644
--- a/Classes/LinphoneUI/UIChatBubbleTextCell.h
+++ b/Classes/LinphoneUI/UIChatBubbleTextCell.h
@@ -55,5 +55,6 @@
+ (CGSize)ViewHeightForMessage:(LinphoneChatMessage *)chat withWidth:(int)width;
+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message;
+ (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font;
++ (NSString *)ContactDateForChat:(LinphoneChatMessage *)message;
@end
diff --git a/Classes/LinphoneUI/UIChatBubbleTextCell.m b/Classes/LinphoneUI/UIChatBubbleTextCell.m
index 3ba03cf5f..0623e4204 100644
--- a/Classes/LinphoneUI/UIChatBubbleTextCell.m
+++ b/Classes/LinphoneUI/UIChatBubbleTextCell.m
@@ -96,9 +96,11 @@
const LinphoneContent *last_content = linphone_chat_message_get_file_transfer_information(message);
// Last message was a file transfer (image) so display a picture...
if (url || last_content) {
+ if (linphone_chat_message_get_text_content(message))
+ return [NSString stringWithUTF8String:linphone_chat_message_get_text_content(message)];
return @"🗻";
} else {
- const char *text = linphone_chat_message_get_text_content(message) ?: "";
+ const char *text = linphone_chat_message_get_text_content(message) ?: "";
return [NSString stringWithUTF8String:text] ?: [NSString stringWithCString:text encoding:NSASCIIStringEncoding]
?: NSLocalizedString(@"(invalid string)", nil);
}
@@ -127,6 +129,7 @@
_statusInProgressSpinner.accessibilityLabel = @"Delivery in progress";
if (_messageText) {
+ LOGD(_messageText.text);
[_messageText setHidden:FALSE];
/* We need to use an attributed string here so that data detector don't mess
* with the text style. See http://stackoverflow.com/a/20669356 */
@@ -338,8 +341,6 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 52; // 44;
[[UIChatBubbleTextCell alloc] initWithIdentifier:NSStringFromClass(UIChatBubbleTextCell.class)];
messageFont = cell.messageText.font;
}
- // UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
- // if (tableView.isEditing)
width -= 40; /*checkbox */
CGSize size;
const char *url = linphone_chat_message_get_external_body_url(chat);
@@ -372,7 +373,16 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 52; // 44;
CGSize originalImageSize = CGSizeMake([asset pixelWidth], [asset pixelHeight]);
size = [self getMediaMessageSizefromOriginalSize:originalImageSize withWidth:width];
//This fixes the image being too small. I think the issue comes form the fact that the display is retina. This should probably be changed in the future.
- size.height += CELL_MESSAGE_X_MARGIN;
+ size.height += 40;
+ size.width -= CELL_MESSAGE_X_MARGIN;
+
+ if (![messageText isEqualToString:@"🗻"]) {
+ CGSize textSize = [self computeBoundingBox:messageText
+ size:CGSizeMake(width - CELL_MESSAGE_X_MARGIN - 4, CGFLOAT_MAX)
+ font:messageFont];
+ size.height += textSize.height;
+ size.width = MAX(textSize.width, size.width);
+ }
}
}
@@ -424,7 +434,7 @@ static const CGFloat CELL_MESSAGE_Y_MARGIN = 52; // 44;
+ (CGSize)getMediaMessageSizefromOriginalSize:(CGSize)originalSize withWidth:(int)width {
CGSize mediaSize = CGSizeMake(0, 0);
- int availableWidth = width - CELL_MESSAGE_X_MARGIN;
+ int availableWidth = width;
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
availableWidth = availableWidth /3;
}
diff --git a/Classes/LinphoneUI/UIImageViewDeletable.h b/Classes/LinphoneUI/UIImageViewDeletable.h
new file mode 100644
index 000000000..f036fd6b7
--- /dev/null
+++ b/Classes/LinphoneUI/UIImageViewDeletable.h
@@ -0,0 +1,26 @@
+//
+// UIImageViewDeletable.h
+// linphone
+//
+// Created by benjamin_verdier on 28/06/2018.
+//
+
+#import
+
+@protocol UIImageViewDeletableDelegate
+
+@required
+
+- (void)deleteImageWithAssetId:(NSString *)assetId;
+
+@end
+
+@interface UIImageViewDeletable : UICollectionViewCell
+
+@property NSString *assetId;
+@property(nonatomic, strong) id deleteDelegate;
+@property (weak, nonatomic) IBOutlet UIImageView *image;
+
+- (IBAction)onDeletePressed;
+
+@end
diff --git a/Classes/LinphoneUI/UIImageViewDeletable.m b/Classes/LinphoneUI/UIImageViewDeletable.m
new file mode 100644
index 000000000..157dd640a
--- /dev/null
+++ b/Classes/LinphoneUI/UIImageViewDeletable.m
@@ -0,0 +1,59 @@
+//
+// UIImageViewDeletable.m
+// linphone
+//
+// Created by benjamin_verdier on 28/06/2018.
+//
+
+#import "UIImageViewDeletable.h"
+
+@interface UIImageViewDeletable ()
+
+@end
+
+@implementation UIImageViewDeletable
+
+- (UIImageViewDeletable *)init {
+ self = [super init];
+ if (self) {
+ NSArray *arrayOfViews =
+ [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
+ // resize cell to match .nib size. It is needed when resized the cell to
+ // correctly adapt its height too
+ UIView *sub = ((UIView *)[arrayOfViews objectAtIndex:arrayOfViews.count - 1]);
+ [self setFrame:CGRectMake(0, 0, sub.frame.size.width, sub.frame.size.height)];
+ [self addSubview:sub];
+ }
+ return self;
+}
+
+
+- (UIImageViewDeletable *)initWithFrame:(CGRect)frame {
+ self = [super initWithFrame:frame];
+ if (self) {
+ NSArray *arrayOfViews =
+ [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil];
+ // resize cell to match .nib size. It is needed when resized the cell to
+ // correctly adapt its height too
+ UIView *sub = ((UIView *)[arrayOfViews objectAtIndex:arrayOfViews.count - 1]);
+ [self setFrame:frame];
+ [self addSubview:sub];
+ }
+ return self;
+}
+
+- (IBAction)onDeletePressed {
+ [_deleteDelegate deleteImageWithAssetId:_assetId];
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ // Get the new view controller using [segue destinationViewController].
+ // Pass the selected object to the new view controller.
+}
+*/
+
+@end
diff --git a/Classes/LinphoneUI/UIImageViewDeletable.xib b/Classes/LinphoneUI/UIImageViewDeletable.xib
new file mode 100644
index 000000000..2fa5d17e1
--- /dev/null
+++ b/Classes/LinphoneUI/UIImageViewDeletable.xib
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Classes/PhoneMainView.m b/Classes/PhoneMainView.m
index 860c0599a..1f35fae2a 100644
--- a/Classes/PhoneMainView.m
+++ b/Classes/PhoneMainView.m
@@ -934,6 +934,8 @@ static RootViewManager *rootViewManagerInstance = nil;
linphone_chat_room_remove_callbacks(view.chatRoom, view.chatRoomCbs);
view.chatRoomCbs = NULL;
+ if (view.chatRoom != cr)
+ [view clearMessageView];
view.chatRoom = cr;
self.currentRoom = view.chatRoom;
if (PhoneMainView.instance.currentView == view.compositeViewDescription)
diff --git a/Classes/Utils/FileTransferDelegate.h b/Classes/Utils/FileTransferDelegate.h
index 34a63df2a..17a4bcc5a 100644
--- a/Classes/Utils/FileTransferDelegate.h
+++ b/Classes/Utils/FileTransferDelegate.h
@@ -19,4 +19,5 @@
- (void)stopAndDestroy;
@property() LinphoneChatMessage *message;
+@property() NSString *text;
@end
diff --git a/Classes/Utils/FileTransferDelegate.m b/Classes/Utils/FileTransferDelegate.m
index 7b620e216..9268ff0d6 100644
--- a/Classes/Utils/FileTransferDelegate.m
+++ b/Classes/Utils/FileTransferDelegate.m
@@ -208,8 +208,8 @@ static LinphoneBuffer *linphone_iphone_file_transfer_send(LinphoneChatMessage *m
linphone_content_set_subtype(content, [subtype UTF8String]);
linphone_content_set_name(content, [name UTF8String]);
linphone_content_set_size(content, _data.length);
-
_message = linphone_chat_room_create_file_transfer_message(chatRoom, content);
+ linphone_chat_message_add_text_content(_message, [_text UTF8String]);
linphone_content_unref(content);
linphone_chat_message_cbs_set_file_transfer_send(linphone_chat_message_get_callbacks(_message),
diff --git a/Classes/Utils/Utils.h b/Classes/Utils/Utils.h
index 9ac9722bf..aa3ceeda7 100644
--- a/Classes/Utils/Utils.h
+++ b/Classes/Utils/Utils.h
@@ -49,6 +49,8 @@ typedef enum {
+ (NSString *)durationToString:(int)duration;
+ (NSString *)intervalToString:(NSTimeInterval)interval ;
++ (NSMutableDictionary *)photoAssetsDictionary;
+
@end
@interface NSNumber (HumanReadableSize)
diff --git a/Classes/Utils/Utils.m b/Classes/Utils/Utils.m
index 3123b02ac..e5e9c8f2c 100644
--- a/Classes/Utils/Utils.m
+++ b/Classes/Utils/Utils.m
@@ -55,6 +55,24 @@
return [formatter stringFromTimeInterval:interval];
}
+
++ (NSMutableDictionary *)photoAssetsDictionary {
+ NSMutableDictionary *assetDict = [NSMutableDictionary dictionary];
+
+ PHFetchOptions *options = [[PHFetchOptions alloc] init];
+ [options setIncludeHiddenAssets:YES];
+ [options setIncludeAllBurstAssets:YES];
+
+ PHFetchResult *fetchRes = [PHAsset fetchAssetsWithOptions:options];
+
+ for (PHAsset *asset in fetchRes) {
+ NSString *key = [asset valueForKey:@"filename"];
+ [assetDict setObject:asset forKey:[[key componentsSeparatedByString:@"."] firstObject]];
+ }
+
+ return assetDict;
+}
+
+ (NSString *)timeToString:(time_t)time withFormat:(LinphoneDateFormat)format {
NSString *formatstr;
NSDate *todayDate = [[NSDate alloc] init];
diff --git a/Resources/images/delete_img.png b/Resources/images/delete_img.png
new file mode 100644
index 000000000..b9aaa86c9
Binary files /dev/null and b/Resources/images/delete_img.png differ
diff --git a/linphone.xcodeproj/project.pbxproj b/linphone.xcodeproj/project.pbxproj
index e7ceca8a3..cac5397ec 100755
--- a/linphone.xcodeproj/project.pbxproj
+++ b/linphone.xcodeproj/project.pbxproj
@@ -743,6 +743,9 @@
8CF25D9D1F9F76BD00BEA0C1 /* chat_group_informations.png in Resources */ = {isa = PBXBuildFile; fileRef = 8CF25D9B1F9F76BC00BEA0C1 /* chat_group_informations.png */; };
8CF25D9E1F9F76BD00BEA0C1 /* chat_group_informations@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8CF25D9C1F9F76BD00BEA0C1 /* chat_group_informations@2x.png */; };
C90FAA7915AF54E6002091CB /* HistoryDetailsView.m in Sources */ = {isa = PBXBuildFile; fileRef = C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */; };
+ CF15F21E20E4F9A3008B1DE6 /* UIImageViewDeletable.m in Sources */ = {isa = PBXBuildFile; fileRef = CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */; };
+ CF15F21F20E4F9A3008B1DE6 /* UIImageViewDeletable.xib in Resources */ = {isa = PBXBuildFile; fileRef = CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */; };
+ CFBD7A2A20E504AE007C5286 /* delete_img.png in Resources */ = {isa = PBXBuildFile; fileRef = CFBD7A2320E504AD007C5286 /* delete_img.png */; };
D306459E1611EC2A00BB571E /* UILoadingImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D306459D1611EC2900BB571E /* UILoadingImageView.m */; };
D3128FE115AABC7E00A2147A /* ContactDetailsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D3128FDF15AABC7E00A2147A /* ContactDetailsView.m */; };
D31AAF5E159B3919002C6B02 /* CallPausedTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = D31AAF5D159B3919002C6B02 /* CallPausedTableView.m */; };
@@ -1845,6 +1848,10 @@
C90FAA7615AF54E6002091CB /* HistoryDetailsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryDetailsView.h; sourceTree = ""; };
C90FAA7715AF54E6002091CB /* HistoryDetailsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryDetailsView.m; sourceTree = ""; };
C9B3A6FD15B485DB006F52EE /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = Utils/Utils.h; sourceTree = ""; };
+ CF15F21B20E4F9A3008B1DE6 /* UIImageViewDeletable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIImageViewDeletable.h; sourceTree = ""; };
+ CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UIImageViewDeletable.m; sourceTree = ""; };
+ CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UIImageViewDeletable.xib; sourceTree = ""; };
+ CFBD7A2320E504AD007C5286 /* delete_img.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = delete_img.png; sourceTree = ""; };
D306459C1611EC2900BB571E /* UILoadingImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UILoadingImageView.h; sourceTree = ""; };
D306459D1611EC2900BB571E /* UILoadingImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UILoadingImageView.m; sourceTree = ""; };
D3128FDE15AABC7E00A2147A /* ContactDetailsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactDetailsView.h; sourceTree = ""; };
@@ -2317,6 +2324,9 @@
2214EB7012F84668002A5394 /* LinphoneUI */ = {
isa = PBXGroup;
children = (
+ CF15F21B20E4F9A3008B1DE6 /* UIImageViewDeletable.h */,
+ CF15F21C20E4F9A3008B1DE6 /* UIImageViewDeletable.m */,
+ CF15F21D20E4F9A3008B1DE6 /* UIImageViewDeletable.xib */,
63F1DF421BCE618E00EDED90 /* UIAddressTextField.h */,
63F1DF431BCE618E00EDED90 /* UIAddressTextField.m */,
63C441C11BBC23ED0053DC5E /* UIAssistantTextField.h */,
@@ -2673,6 +2683,7 @@
633FEBE11D3CD5570014B822 /* images */ = {
isa = PBXGroup;
children = (
+ CFBD7A2320E504AD007C5286 /* delete_img.png */,
24BFAA9B209B062F004F47A7 /* callkit_logo.png */,
24BFAA99209B062E004F47A7 /* contacts_sip_default.png */,
24BFAA94209B062C004F47A7 /* contacts_sip_default@2x.png */,
@@ -3741,6 +3752,7 @@
633FEE401D3CD5590014B822 /* contacts_all_selected.png in Resources */,
633FEE0C1D3CD5590014B822 /* chat_attachment_disabled.png in Resources */,
633FEF001D3CD55A0014B822 /* options_default.png in Resources */,
+ CF15F21F20E4F9A3008B1DE6 /* UIImageViewDeletable.xib in Resources */,
633FEE951D3CD55A0014B822 /* micro_default@2x.png in Resources */,
633FEE6A1D3CD5590014B822 /* footer_dialer_default.png in Resources */,
633FEEC91D3CD55A0014B822 /* numpad_5~ipad.png in Resources */,
@@ -3873,6 +3885,7 @@
633FEED71D3CD55A0014B822 /* numpad_7_over~ipad.png in Resources */,
633FEF2A1D3CD55A0014B822 /* route_earpiece_disabled.png in Resources */,
633FEDDB1D3CD5590014B822 /* call_start_body_disabled@2x.png in Resources */,
+ CFBD7A2A20E504AE007C5286 /* delete_img.png in Resources */,
633FEDFD1D3CD5590014B822 /* camera_switch_default@2x.png in Resources */,
633FEEC51D3CD55A0014B822 /* numpad_5_over.png in Resources */,
633FEE721D3CD5590014B822 /* history_all_default.png in Resources */,
@@ -4342,6 +4355,7 @@
1D60589B0D05DD56006BFB54 /* main.m in Sources */,
8CD99A3C2090B9FA008A7CDA /* ChatConversationImdnView.m in Sources */,
1D3623260D0F684500981E51 /* LinphoneAppDelegate.m in Sources */,
+ CF15F21E20E4F9A3008B1DE6 /* UIImageViewDeletable.m in Sources */,
22F2508E107141E100AC9B3F /* DialerView.m in Sources */,
633756451B67D2B200E21BAD /* SideMenuView.m in Sources */,
8CD99A422090CE6F008A7CDA /* UIChatConversationImdnTableViewCell.m in Sources */,
diff --git a/linphoneExtension/ShareViewController.m b/linphoneExtension/ShareViewController.m
index ae71c00c3..33a1c06c4 100644
--- a/linphoneExtension/ShareViewController.m
+++ b/linphoneExtension/ShareViewController.m
@@ -25,9 +25,11 @@ static NSString* groupName = @"group.belledonne-communications.linphone";
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *provider in item.attachments) {
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:groupName];
-
+ // TODO: Use [provider registeredTypeIdentifiersWithFileOptions:0]; to get all type identifiers of the provider instead of this if/else if structure
if ([provider hasItemConformingToTypeIdentifier:@"public.jpeg"]) {
[self loadItem:provider typeIdentifier:@"public.jpeg" defaults:defaults key:@"img"];
+ } else if ([provider hasItemConformingToTypeIdentifier:@"com.compuserve.gif"]) {
+ [self loadItem:provider typeIdentifier:@"com.compuserve.gif" defaults:defaults key:@"img"];
} else if ([provider hasItemConformingToTypeIdentifier:@"public.url"]) {
[self loadItem:provider typeIdentifier:@"public.url" defaults:defaults key:@"web"];
} else if ([provider hasItemConformingToTypeIdentifier:@"public.movie"]) {
@@ -55,11 +57,31 @@ static NSString* groupName = @"group.belledonne-communications.linphone";
- (void)loadItem:(NSItemProvider *)provider typeIdentifier:(NSString *)typeIdentifier defaults:(NSUserDefaults *)defaults key:(NSString *)key {
[provider loadItemForTypeIdentifier:typeIdentifier options:nil completionHandler:^(id _Nullable item, NSError * _Null_unspecified error) {
- if([(NSObject*)item isKindOfClass:[NSURL class]]) {
- NSData *nsData = [NSData dataWithContentsOfURL:(NSURL*)item];
+ if([(NSObject*)item isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *dico = (NSDictionary *)item;
+ if (dico) {
+ return;
+ }
+ } else if([(NSObject*)item isKindOfClass:[NSURL class]]) {
+ NSURL *url = (NSURL *)item;
+ NSData *nsData = [NSData dataWithContentsOfURL:url];
if (nsData) {
- NSDictionary *dict = @{@"nsData" : nsData,
- @"url" : [(NSURL*)item absoluteString]};
+ NSDictionary *dict;
+ // We get the corresponding PHAsset identifier so we can display the image in the app without having to duplicate it.
+ NSString *imgPath = url.path;
+ if ([imgPath hasPrefix:@"/var/mobile/Media/"] && ![imgPath containsString:@"OutgoingTemp"]) { // The image comes from the photos app
+ NSString *filename;
+ for ( NSString *comp in [imgPath componentsSeparatedByString:@"/"] ) {
+ if ([comp containsString:@"IMG_"]) {
+ filename = [[comp componentsSeparatedByString:@"."] firstObject];
+ break;
+ }
+ }
+ dict = @{@"nsData" : nsData,
+ @"url" : filename};
+ } else {
+ dict = @{@"nsData" : nsData};
+ }
[defaults setObject:dict forKey:key];
} else {
NSLog(@"NSExtensionItem Error, provider = %@", provider);
@@ -67,6 +89,7 @@ static NSString* groupName = @"group.belledonne-communications.linphone";
}
}
else if ([(NSObject*)item isKindOfClass:[UIImage class]]) {
+ NSLog(@"SHARED PHOTO UIIMAGE");
NSData *imgData = UIImagePNGRepresentation((UIImage*)item);
if (imgData) {
NSDictionary *dict = @{@"nsData" : imgData,
@@ -78,6 +101,7 @@ static NSString* groupName = @"group.belledonne-communications.linphone";
}
}
else {
+ NSLog(@"SHARED PHOTO OTHER");
NSDictionary *dict = @{@"name" : self.contentText};
[defaults setObject:dict forKey:key];
}