diff --git a/Classes/Base.lproj/ChatConversationView.xib b/Classes/Base.lproj/ChatConversationView.xib
index 9013e94af..336e81e40 100644
--- a/Classes/Base.lproj/ChatConversationView.xib
+++ b/Classes/Base.lproj/ChatConversationView.xib
@@ -148,7 +148,7 @@
-
+
diff --git a/Classes/ChatConversationTableView.m b/Classes/ChatConversationTableView.m
index 581d4f670..856ebf480 100644
--- a/Classes/ChatConversationTableView.m
+++ b/Classes/ChatConversationTableView.m
@@ -179,6 +179,9 @@
cell = [[NSClassFromString(kCellId) alloc] initWithIdentifier:kCellId];
}
[cell setChatMessage:chat];
+ if (chat) {
+ [cell update];
+ }
[cell setChatRoomDelegate:_chatRoomDelegate];
[super accessoryForCell:cell atPath:indexPath];
return cell;
@@ -204,8 +207,8 @@
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
- UIChatBubbleTextCell *cell = (UIChatBubbleTextCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];
- return [cell viewSizeWithWidth:self.view.frame.size.width].height;
+ LinphoneChatMessage *chat = ms_list_nth_data(messageList, (int)[indexPath row]);
+ return [UIChatBubbleTextCell ViewSizeForMessage:chat withWidth:self.view.frame.size.width].height;
}
diff --git a/Classes/ContactDetailsTableView.h b/Classes/ContactDetailsTableView.h
index e521dc505..72777fc20 100644
--- a/Classes/ContactDetailsTableView.h
+++ b/Classes/ContactDetailsTableView.h
@@ -26,11 +26,11 @@ typedef enum _ContactSections {
ContactSections_None = 0, // first section is empty because we cannot set header for first section
ContactSections_First_Name,
ContactSections_Last_Name,
- ContactSections_Number,
ContactSections_Sip,
+ ContactSections_Number,
ContactSections_Email,
ContactSections_MAX
-} ContactSections_e;
+} ContactSections;
@interface ContactDetailsTableView : UITableViewController {
@private
diff --git a/Classes/ContactDetailsTableView.m b/Classes/ContactDetailsTableView.m
index 9f0bd405d..abbd1f9a8 100644
--- a/Classes/ContactDetailsTableView.m
+++ b/Classes/ContactDetailsTableView.m
@@ -48,10 +48,6 @@
@implementation ContactDetailsTableView
-static const ContactSections_e contactSections[ContactSections_MAX] = {
- ContactSections_None, ContactSections_First_Name, ContactSections_Last_Name,
- ContactSections_Sip, ContactSections_Number, ContactSections_Email};
-
@synthesize contactDetailsDelegate;
@synthesize contact;
@@ -102,11 +98,11 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
}
- (NSMutableArray *)getSectionData:(NSInteger)section {
- if (contactSections[section] == ContactSections_Number) {
+ if (section == ContactSections_Number) {
return [dataCache objectAtIndex:0];
- } else if (contactSections[section] == ContactSections_Sip) {
+ } else if (section == ContactSections_Sip) {
return [dataCache objectAtIndex:1];
- } else if (contactSections[section] == ContactSections_Email) {
+ } else if (section == ContactSections_Email) {
if ([[LinphoneManager instance] lpConfigBoolForKey:@"show_contacts_emails_preference"] == true) {
return [dataCache objectAtIndex:2];
} else {
@@ -116,7 +112,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
return nil;
}
-- (ABPropertyID)propertyIDForSection:(ContactSections_e)section {
+- (ABPropertyID)propertyIDForSection:(ContactSections)section {
switch (section) {
case ContactSections_First_Name:
return kABPersonFirstNameProperty;
@@ -313,7 +309,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
NSUInteger count = [sectionArray count];
CFErrorRef error = NULL;
bool added = TRUE;
- if (contactSections[section] == ContactSections_Number) {
+ if (section == ContactSections_Number) {
ABMultiValueIdentifier identifier;
ABMultiValueRef lcMap = ABRecordCopyValue(contact, kABPersonPhoneProperty);
ABMutableMultiValueRef lMap;
@@ -336,7 +332,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
LOGI(@"Can't add entry: %@", [(__bridge NSError *)error localizedDescription]);
}
CFRelease(lMap);
- } else if (contactSections[section] == ContactSections_Sip) {
+ } else if (section == ContactSections_Sip) {
Entry *entry = [self setOrCreateSipContactEntry:nil withValue:value];
if (entry) {
[sectionArray addObject:entry];
@@ -345,7 +341,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
added = false;
LOGE(@"Can't add entry for value: %@", value);
}
- } else if (contactSections[section] == ContactSections_Email) {
+ } else if (section == ContactSections_Email) {
ABMultiValueIdentifier identifier;
ABMultiValueRef lcMap = ABRecordCopyValue(contact, kABPersonEmailProperty);
ABMutableMultiValueRef lMap;
@@ -392,7 +388,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
if (row >= 0) {
Entry *entry = [sectionDict objectAtIndex:row];
- ABPropertyID property = [self propertyIDForSection:contactSections[section]];
+ ABPropertyID property = [self propertyIDForSection:(ContactSections)section];
if (property != kABInvalidPropertyType) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, property);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
@@ -425,7 +421,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
- (void)removeEntry:(UITableView *)tableview path:(NSIndexPath *)indexPath animated:(BOOL)animated {
NSMutableArray *sectionArray = [self getSectionData:[indexPath section]];
Entry *entry = [sectionArray objectAtIndex:[indexPath row]];
- ABPropertyID property = [self propertyIDForSection:contactSections[indexPath.section]];
+ ABPropertyID property = [self propertyIDForSection:(ContactSections)indexPath.section];
if (property != kABInvalidPropertyType) {
ABMultiValueRef lcMap = ABRecordCopyValue(contact, property);
@@ -459,22 +455,22 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
}
- (void)addPhoneField:(NSString *)number {
- int i = 0;
- while (i < ContactSections_MAX && contactSections[i] != ContactSections_Number)
+ ContactSections i = 0;
+ while (i != ContactSections_MAX && i != ContactSections_Number)
++i;
[self addEntry:[self tableView] section:i animated:FALSE value:number];
}
- (void)addSipField:(NSString *)address {
- int i = 0;
- while (i < ContactSections_MAX && contactSections[i] != ContactSections_Sip)
+ ContactSections i = 0;
+ while (i != ContactSections_MAX && i != ContactSections_Sip)
++i;
[self addEntry:[self tableView] section:i animated:FALSE value:address];
}
- (void)addEmailField:(NSString *)address {
- int i = 0;
- while (i < ContactSections_MAX && contactSections[i] != ContactSections_Email)
+ ContactSections i = 0;
+ while (i != ContactSections_MAX && i != ContactSections_Email)
++i;
[self addEntry:[self tableView] section:i animated:FALSE value:address];
}
@@ -486,8 +482,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
- if (contactSections[section] == ContactSections_First_Name ||
- contactSections[section] == ContactSections_Last_Name) {
+ if (section == ContactSections_First_Name || section == ContactSections_Last_Name) {
return (self.tableView.isEditing) ? 1 : 0 /*no first and last name when not editting */;
} else {
return [[self getSectionData:section] count];
@@ -510,17 +505,17 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
NSString *label = [FastAddressBook localizedLabel:[labelArray objectAtIndex:0]];
[cell hideDeleteButton:NO];
- if (contactSections[indexPath.section] == ContactSections_First_Name) {
+ if (indexPath.section == ContactSections_First_Name) {
value =
(__bridge NSString *)(ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_First_Name]));
label = nil;
[cell hideDeleteButton:YES];
- } else if (contactSections[indexPath.section] == ContactSections_Last_Name) {
+ } else if (indexPath.section == ContactSections_Last_Name) {
value =
(__bridge NSString *)(ABRecordCopyValue(contact, [self propertyIDForSection:ContactSections_Last_Name]));
label = nil;
[cell hideDeleteButton:YES];
- } else if (contactSections[[indexPath section]] == ContactSections_Number) {
+ } else if ([indexPath section] == ContactSections_Number) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, kABPersonPhoneProperty);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
NSString *labelRef = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(lMap, index));
@@ -532,7 +527,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
value = [FastAddressBook localizedLabel:valueRef];
}
CFRelease(lMap);
- } else if (contactSections[[indexPath section]] == ContactSections_Sip) {
+ } else if ([indexPath section] == ContactSections_Sip) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, kABPersonInstantMessageProperty);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
@@ -556,7 +551,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
}
CFRelease(lDict);
CFRelease(lMap);
- } else if (contactSections[[indexPath section]] == ContactSections_Email) {
+ } else if ([indexPath section] == ContactSections_Email) {
ABMultiValueRef lMap = ABRecordCopyValue(contact, kABPersonEmailProperty);
NSInteger index = ABMultiValueGetIndexForIdentifier(lMap, [entry identifier]);
NSString *labelRef = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(lMap, index));
@@ -570,11 +565,11 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
CFRelease(lMap);
}
[cell setAddress:value];
- if (contactSections[[indexPath section]] == ContactSections_Number) {
+ if ([indexPath section] == ContactSections_Number) {
[cell.editTextfield setKeyboardType:UIKeyboardTypePhonePad];
- } else if (contactSections[[indexPath section]] == ContactSections_Sip) {
+ } else if ([indexPath section] == ContactSections_Sip) {
[cell.editTextfield setKeyboardType:UIKeyboardTypeASCIICapable];
- } else if (contactSections[[indexPath section]] == ContactSections_Email) {
+ } else if ([indexPath section] == ContactSections_Email) {
[cell.editTextfield setKeyboardType:UIKeyboardTypeASCIICapable];
} else {
[cell.editTextfield setKeyboardType:UIKeyboardTypeDefault];
@@ -588,7 +583,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
Entry *entry = [sectionDict objectAtIndex:[indexPath row]];
if ([self isEditing]) {
NSString *key = nil;
- ABPropertyID property = [self propertyIDForSection:contactSections[indexPath.section]];
+ ABPropertyID property = [self propertyIDForSection:(ContactSections)indexPath.section];
if (property != kABInvalidPropertyType && property != kABPersonFirstNameProperty &&
property != kABPersonLastNameProperty) {
@@ -629,8 +624,8 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
if (editing) {
// add phone/SIP/email entries so that the user can add new data
for (int section = 0; section < [self numberOfSectionsInTableView:[self tableView]]; ++section) {
- if (contactSections[section] == ContactSections_Number || contactSections[section] == ContactSections_Sip ||
- (showEmails && contactSections[section] == ContactSections_Email)) {
+ if (section == ContactSections_Number || section == ContactSections_Sip ||
+ (showEmails && section == ContactSections_Email)) {
[self addEntry:self.tableView section:section animated:animated];
}
}
@@ -639,8 +634,8 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
// remove empty phone numbers
for (int section = 0; section < [self numberOfSectionsInTableView:[self tableView]]; ++section) {
// remove phony entries that were not filled by the user
- if (contactSections[section] == ContactSections_Number || contactSections[section] == ContactSections_Sip ||
- (showEmails && contactSections[section] == ContactSections_Email)) {
+ if (section == ContactSections_Number || section == ContactSections_Sip ||
+ (showEmails && section == ContactSections_Email)) {
[self removeEmptyEntry:self.tableView section:section animated:animated];
if ([[self getSectionData:section] count] == 0 && animated) { // the section is empty -> remove titles
@@ -665,20 +660,20 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
NSString *text = nil;
BOOL canAddEntry = self.tableView.isEditing;
NSString *addEntryName = nil;
- if (contactSections[section] == ContactSections_First_Name && self.tableView.isEditing) {
+ if (section == ContactSections_First_Name && self.tableView.isEditing) {
text = NSLocalizedString(@"First name", nil);
canAddEntry = NO;
- } else if (contactSections[section] == ContactSections_Last_Name && self.tableView.isEditing) {
+ } else if (section == ContactSections_Last_Name && self.tableView.isEditing) {
text = NSLocalizedString(@"Last name", nil);
canAddEntry = NO;
} else if ([self getSectionData:section].count > 0 || self.tableView.isEditing) {
- if (contactSections[section] == ContactSections_Number) {
+ if (section == ContactSections_Number) {
text = NSLocalizedString(@"Phone numbers", nil);
addEntryName = NSLocalizedString(@"Add new phone number", nil);
- } else if (contactSections[section] == ContactSections_Sip) {
+ } else if (section == ContactSections_Sip) {
text = NSLocalizedString(@"SIP addresses", nil);
addEntryName = NSLocalizedString(@"Add new SIP address", nil);
- } else if (contactSections[section] == ContactSections_Email &&
+ } else if (section == ContactSections_Email &&
[LinphoneManager.instance lpConfigBoolForKey:@"show_contacts_emails_preference"]) {
text = NSLocalizedString(@"Email addresses", nil);
addEntryName = NSLocalizedString(@"Add new email", nil);
@@ -780,7 +775,7 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
NSIndexPath *path = [self.tableView indexPathForCell:cell];
NSMutableArray *sectionDict = [self getSectionData:[path section]];
Entry *entry = [sectionDict objectAtIndex:[path row]];
- ContactSections_e sect = contactSections[[path section]];
+ ContactSections sect = (ContactSections)[path section];
ABPropertyID property = [self propertyIDForSection:sect];
NSString *value = [textField text];
@@ -844,8 +839,8 @@ static const ContactSections_e contactSections[ContactSections_MAX] = {
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
- if (section == 0 || (!self.tableView.isEditing && (contactSections[section] == ContactSections_First_Name ||
- contactSections[section] == ContactSections_Last_Name))) {
+ if (section == 0 || (!self.tableView.isEditing &&
+ (section == ContactSections_First_Name || section == ContactSections_Last_Name))) {
return 1e-5;
}
return [self tableView:tableView viewForHeaderInSection:section].frame.size.height;
diff --git a/Classes/LinphoneUI/UIChatBubblePhotoCell.h b/Classes/LinphoneUI/UIChatBubblePhotoCell.h
index 31d1b9a3c..f196dbcd1 100644
--- a/Classes/LinphoneUI/UIChatBubblePhotoCell.h
+++ b/Classes/LinphoneUI/UIChatBubblePhotoCell.h
@@ -33,6 +33,7 @@
@property(weak, nonatomic) IBOutlet UIButton *cancelButton;
@property(weak, nonatomic) IBOutlet UIView *imageSubView;
@property(weak, nonatomic) IBOutlet UIView *totalView;
+@property(strong, nonatomic) IBOutlet UITapGestureRecognizer *imageGestureRecognizer;
- (void)setChatMessage:(LinphoneChatMessage *)message;
- (void)connectToFileDelegate:(FileTransferDelegate *)ftd;
diff --git a/Classes/LinphoneUI/UIChatBubblePhotoCell.m b/Classes/LinphoneUI/UIChatBubblePhotoCell.m
index a8b53e714..85f44023b 100644
--- a/Classes/LinphoneUI/UIChatBubblePhotoCell.m
+++ b/Classes/LinphoneUI/UIChatBubblePhotoCell.m
@@ -25,7 +25,7 @@
#import
@implementation UIChatBubblePhotoCell {
- FileTransferDelegate *ftd;
+ FileTransferDelegate *_ftd;
}
#pragma mark - Lifecycle Functions
@@ -53,10 +53,7 @@
#pragma mark -
- (void)setChatMessage:(LinphoneChatMessage *)amessage {
- if (amessage == self.message) {
- return;
- }
-
+ _imageGestureRecognizer.enabled = NO;
_messageImageView.image = nil;
_fileTransferProgress.progress = 0;
[self disconnectFromFileDelegate];
@@ -70,10 +67,8 @@
(linphone_chat_message_is_outgoing(aftd.message) == linphone_chat_message_is_outgoing(amessage)) &&
strcmp(name, linphone_content_get_name(
linphone_chat_message_get_file_transfer_information(aftd.message))) == 0) {
- if (ftd != aftd) {
- LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", amessage, aftd);
- [self connectToFileDelegate:aftd];
- }
+ LOGI(@"Chat message [%p] with file transfer delegate [%p], connecting to it!", amessage, aftd);
+ [self connectToFileDelegate:aftd];
break;
}
}
@@ -113,6 +108,7 @@
[_messageImageView setFullImageUrl:asset];
[_messageImageView stopLoading];
_messageImageView.hidden = NO;
+ _imageGestureRecognizer.enabled = YES;
});
}
});
@@ -122,7 +118,7 @@
}];
}
// we are uploading the image
- if (ftd.message != nil) {
+ if (_ftd.message != nil) {
_cancelButton.hidden = NO;
_fileTransferProgress.hidden = NO;
_downloadButton.hidden = YES;
@@ -133,7 +129,7 @@
// we must download the image: either it has already started (show cancel button) or not yet (show download
// button)
} else {
- _messageImageView.hidden = _cancelButton.hidden = (ftd.message == nil);
+ _messageImageView.hidden = _cancelButton.hidden = (_ftd.message == nil);
_downloadButton.hidden = !_cancelButton.hidden;
_fileTransferProgress.hidden = NO;
@@ -156,20 +152,27 @@
}
- (IBAction)onDownloadClick:(id)event {
- [ftd cancel];
- ftd = [[FileTransferDelegate alloc] init];
- [self connectToFileDelegate:ftd];
- [ftd download:self.message];
+ [_ftd cancel];
+ _ftd = [[FileTransferDelegate alloc] init];
+ [self connectToFileDelegate:_ftd];
+ [_ftd download:self.message];
_cancelButton.hidden = NO;
_downloadButton.hidden = YES;
+
+ // we must tell the tableview to refresh the cell to reflect its internal state
+ ChatConversationView *view = VIEW(ChatConversationView);
+ [view.tableController updateChatEntry:self.message];
}
- (IBAction)onCancelClick:(id)sender {
- FileTransferDelegate *tmp = ftd;
+ FileTransferDelegate *tmp = _ftd;
[self disconnectFromFileDelegate];
[tmp cancel];
_fileTransferProgress.progress = 0;
[self update];
+ // we must tell the tableview to refresh the cell to reflect its internal state
+ ChatConversationView *view = VIEW(ChatConversationView);
+ [view.tableController updateChatEntry:self.message];
}
- (void)onResendClick:(id)event {
@@ -194,22 +197,28 @@
#pragma mark - LinphoneFileTransfer Notifications Handling
- (void)connectToFileDelegate:(FileTransferDelegate *)aftd {
- ftd = aftd;
+ if (aftd.message && linphone_chat_message_get_state(aftd.message) == LinphoneChatMessageStateFileTransferError) {
+ LOGW(@"This file transfer failed unexpectedly, cleaning it");
+ [aftd stopAndDestroy];
+ return;
+ }
+
+ _ftd = aftd;
_fileTransferProgress.progress = 0;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onFileTransferSendUpdate:)
name:kLinphoneFileTransferSendUpdate
- object:ftd];
+ object:_ftd];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onFileTransferRecvUpdate:)
name:kLinphoneFileTransferRecvUpdate
- object:ftd];
+ object:_ftd];
}
- (void)disconnectFromFileDelegate {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- ftd = nil;
+ _ftd = nil;
}
- (void)onFileTransferSendUpdate:(NSNotification *)notif {
@@ -241,23 +250,4 @@
}
}
-- (CGSize)viewSizeWithWidth:(int)width {
- static const CGFloat IMAGE_HEIGHT = 100.0f;
- static const CGFloat IMAGE_WIDTH = 100.0f;
-
- NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:self.message];
- CGSize messageSize = (localImage != nil) ? CGSizeMake(IMAGE_WIDTH, IMAGE_HEIGHT) : CGSizeMake(50, 50);
-
- CGSize dateSize = [self computeBoundingBox:self.contactDateLabel.text
- size:self.contactDateLabel.frame.size
- font:self.contactDateLabel.font];
-
- CGSize bubbleSize;
- bubbleSize.width =
- MAX(messageSize.width, dateSize.width + self.statusErrorImage.frame.size.width + 5) + MARGIN_WIDTH;
- bubbleSize.height = messageSize.height + MARGIN_HEIGHT;
-
- return bubbleSize;
-}
-
@end
diff --git a/Classes/LinphoneUI/UIChatBubblePhotoCell.xib b/Classes/LinphoneUI/UIChatBubblePhotoCell.xib
index 567b1088d..dfcba671f 100644
--- a/Classes/LinphoneUI/UIChatBubblePhotoCell.xib
+++ b/Classes/LinphoneUI/UIChatBubblePhotoCell.xib
@@ -15,6 +15,7 @@
+
@@ -119,7 +120,7 @@
-
+
diff --git a/Classes/LinphoneUI/UIChatBubbleTextCell.h b/Classes/LinphoneUI/UIChatBubbleTextCell.h
index dfeb87e88..adc558ce8 100644
--- a/Classes/LinphoneUI/UIChatBubbleTextCell.h
+++ b/Classes/LinphoneUI/UIChatBubbleTextCell.h
@@ -28,6 +28,8 @@ static const CGFloat TEXT_MIN_WIDTH = 150.0f;
static const CGFloat MARGIN_WIDTH = 60;
static const CGFloat MARGIN_HEIGHT = 19 + 16 /*this 16 is because textview add some top&bottom padding*/;
static const CGFloat CHECK_BOX_WIDTH = 40;
+static const CGFloat IMAGE_HEIGHT = 100.0f;
+static const CGFloat IMAGE_WIDTH = 100.0f;
@interface UIChatBubbleTextCell : UITableViewCell
@@ -43,7 +45,7 @@ static const CGFloat CHECK_BOX_WIDTH = 40;
@property(strong, nonatomic) IBOutlet UIView *bubbleView;
@property(strong, nonatomic) IBOutlet UITapGestureRecognizer *resendRecognizer;
-- (CGSize)viewSizeWithWidth:(int)width;
++ (CGSize)ViewSizeForMessage:(LinphoneChatMessage *)chat withWidth:(int)width;
- (void)setChatMessage:(LinphoneChatMessage *)message;
@@ -52,6 +54,6 @@ static const CGFloat CHECK_BOX_WIDTH = 40;
- (void)update;
+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message;
-- (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font;
++ (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font;
@end
diff --git a/Classes/LinphoneUI/UIChatBubbleTextCell.m b/Classes/LinphoneUI/UIChatBubbleTextCell.m
index 7e126ea57..d5d21a031 100644
--- a/Classes/LinphoneUI/UIChatBubbleTextCell.m
+++ b/Classes/LinphoneUI/UIChatBubbleTextCell.m
@@ -30,13 +30,15 @@
- (id)initWithIdentifier:(NSString *)identifier {
if ((self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]) != nil) {
- 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];
+ if ([identifier isEqualToString:NSStringFromClass(self.class)]) {
+ 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;
}
@@ -63,16 +65,22 @@
linphone_chat_message_ref(_message);
linphone_chat_message_set_user_data(_message, (void *)CFBridgingRetain(self));
linphone_chat_message_cbs_set_msg_state_changed(linphone_chat_message_get_callbacks(_message), message_status);
- [self update];
}
}
-+ (NSString *)TextMessageForChat:(LinphoneChatMessage *)_message {
- const char *text = linphone_chat_message_get_text(_message) ?: "";
++ (NSString *)TextMessageForChat:(LinphoneChatMessage *)message {
+ const char *text = linphone_chat_message_get_text(message) ?: "";
return [NSString stringWithUTF8String:text] ?: [NSString stringWithCString:text encoding:NSASCIIStringEncoding]
?: NSLocalizedString(@"(invalid string)", nil);
}
++ (NSString *)ContactDateForChat:(LinphoneChatMessage *)message {
+ return [NSString
+ stringWithFormat:@"%@ - %@", [LinphoneUtils timeToString:linphone_chat_message_get_time(message)
+ withFormat:LinphoneDateChatBubble],
+ [FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(message)]];
+}
+
- (NSString *)textMessage {
return [self.class TextMessageForChat:_message];
}
@@ -83,6 +91,8 @@
return;
}
+ _statusInProgressSpinner.accessibilityLabel = @"Delivery in progress";
+
if (_messageText) {
[_messageText setHidden:FALSE];
/* We need to use an attributed string here so that data detector don't mess
@@ -108,10 +118,7 @@
bordered:NO
withRoundedRadius:YES];
}
- _contactDateLabel.text = [NSString
- stringWithFormat:@"%@ - %@", [LinphoneUtils timeToString:linphone_chat_message_get_time(_message)
- withFormat:LinphoneDateChatBubble],
- [FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(_message)]];
+ _contactDateLabel.text = [self.class ContactDateForChat:_message];
_backgroundColorImage.image = _bottomBarColor.image =
[UIImage imageNamed:(outgoing ? @"color_A.png" : @"color_D.png")];
@@ -165,7 +172,7 @@
return;
LinphoneChatMessageState state = linphone_chat_message_get_state(_message);
- if (state == LinphoneChatMessageStateNotDelivered) {
+ if (state == LinphoneChatMessageStateNotDelivered || state == LinphoneChatMessageStateFileTransferError) {
if (linphone_chat_message_get_file_transfer_information(_message) != NULL) {
NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:_message];
NSURL *imageUrl = [NSURL URLWithString:localImage];
@@ -204,7 +211,7 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
#pragma mark - Bubble size computing
-- (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font {
++ (CGSize)computeBoundingBox:(NSString *)text size:(CGSize)size font:(UIFont *)font {
if (!text || text.length == 0)
return CGSizeMake(0, 0);
@@ -222,21 +229,36 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
{ return [text sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByCharWrapping]; }
}
-- (CGSize)viewSizeWithWidth:(int)width {
++ (CGSize)ViewSizeForMessage:(LinphoneChatMessage *)chat withWidth:(int)width {
+ static UIFont *messageFont = nil;
+ static UIFont *dateFont = nil;
+ static CGSize dateViewSize;
+
int messageAvailableWidth = width - MARGIN_WIDTH - CHECK_BOX_WIDTH;
+ CGSize messageSize;
- NSString *text = [UIChatBubbleTextCell TextMessageForChat:_message];
+ if (!messageFont) {
+ UIChatBubbleTextCell *cell =
+ [[UIChatBubbleTextCell alloc] initWithIdentifier:NSStringFromClass(UIChatBubbleTextCell.class)];
+ messageFont = cell.messageText.font;
+ dateFont = cell.contactDateLabel.font;
+ dateViewSize = cell.contactDateLabel.frame.size;
+ }
- CGSize messageSize =
- [self computeBoundingBox:text size:CGSizeMake(messageAvailableWidth, CGFLOAT_MAX) font:_messageText.font];
- messageSize.width = MAX(TEXT_MIN_WIDTH, ceil(messageSize.width));
- messageSize.height = MAX(TEXT_MIN_HEIGHT, ceil(messageSize.height));
-
- CGSize dateSize =
- [self computeBoundingBox:_contactDateLabel.text size:_contactDateLabel.frame.size font:_contactDateLabel.font];
+ if (linphone_chat_message_get_file_transfer_information(chat)) {
+ NSString *localImage = [LinphoneManager getMessageAppDataForKey:@"localimage" inMessage:chat];
+ messageSize = (localImage != nil) ? CGSizeMake(IMAGE_WIDTH, IMAGE_HEIGHT) : CGSizeMake(50, 50);
+ } else {
+ NSString *text = [UIChatBubbleTextCell TextMessageForChat:chat];
+ messageSize =
+ [self computeBoundingBox:text size:CGSizeMake(messageAvailableWidth, CGFLOAT_MAX) font:messageFont];
+ messageSize.width = MAX(TEXT_MIN_WIDTH, ceil(messageSize.width));
+ messageSize.height = MAX(TEXT_MIN_HEIGHT, ceil(messageSize.height));
+ }
+ CGSize dateSize = [self computeBoundingBox:[self ContactDateForChat:chat] size:dateViewSize font:dateFont];
CGSize bubbleSize;
- bubbleSize.width = MAX(messageSize.width, dateSize.width + _statusErrorImage.frame.size.width + 5) + MARGIN_WIDTH;
+ bubbleSize.width = MAX(messageSize.width, dateSize.width + 20 /*error icon*/ + 5) + MARGIN_WIDTH;
bubbleSize.height = messageSize.height + MARGIN_HEIGHT;
return bubbleSize;
@@ -248,7 +270,7 @@ static void message_status(LinphoneChatMessage *msg, LinphoneChatMessageState st
UITableView *tableView = VIEW(ChatConversationView).tableController.tableView;
BOOL is_outgoing = linphone_chat_message_is_outgoing(_message);
CGRect bubbleFrame = _bubbleView.frame;
- bubbleFrame.size = [self viewSizeWithWidth:self.frame.size.width];
+ bubbleFrame.size = [self.class ViewSizeForMessage:_message withWidth:self.frame.size.width];
bubbleFrame.origin.x =
tableView.isEditing ? 0 : (is_outgoing ? self.frame.size.width - bubbleFrame.size.width : 0);
_bubbleView.frame = bubbleFrame;
diff --git a/Classes/LinphoneUI/UIChatBubbleTextCell.xib b/Classes/LinphoneUI/UIChatBubbleTextCell.xib
index 52153f10c..86fada1a5 100644
--- a/Classes/LinphoneUI/UIChatBubbleTextCell.xib
+++ b/Classes/LinphoneUI/UIChatBubbleTextCell.xib
@@ -67,7 +67,7 @@
-
+
diff --git a/Classes/SettingsView.m b/Classes/SettingsView.m
index fa63981ff..a627fcc29 100644
--- a/Classes/SettingsView.m
+++ b/Classes/SettingsView.m
@@ -685,7 +685,10 @@ static UICompositeViewDescription *compositeDescription = nil;
while (rooms) {
const MSList *messages = linphone_chat_room_get_history(rooms->data, 0);
while (messages) {
- [LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:messages->data];
+ LinphoneChatMessage *msg = messages->data;
+ if (!linphone_chat_message_is_outgoing(msg)) {
+ [LinphoneManager setValueInMessageAppData:nil forKey:@"localimage" inMessage:messages->data];
+ }
messages = messages->next;
}
rooms = rooms->next;
diff --git a/TestsUI/ChatTester.m b/TestsUI/ChatTester.m
index ca64d5cab..214b05317 100644
--- a/TestsUI/ChatTester.m
+++ b/TestsUI/ChatTester.m
@@ -22,9 +22,7 @@
- (void)beforeEach {
[super beforeEach];
- if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Back" error:nil]) {
- [self goBackFromChat];
- }
+ [self goBackFromChat];
[tester tapViewWithAccessibilityLabel:@"Chat"];
[self removeAllRooms];
}
@@ -33,9 +31,7 @@
[super afterAll];
linphone_core_set_log_level(ORTP_MESSAGE);
// at the end of tests, go back to chat rooms to display main bar
- if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Back" error:nil]) {
- [self goBackFromChat];
- }
+ [self goBackFromChat];
ASSERT_EQ([LinphoneManager instance].fileTransferDelegates.count, 0)
}
@@ -51,8 +47,14 @@
[tester tapViewWithAccessibilityLabel:@"DELETE" traits:UIAccessibilityTraitButton];
}
+- (void)dismissKeyboard {
+ [tester tapScreenAtPoint:CGPointMake(0, 0)]; // dismiss keyboard, if any
+}
- (void)goBackFromChat {
- [tester tapViewWithAccessibilityLabel:@"Back"];
+ [self dismissKeyboard];
+ if ([tester tryFindingTappableViewWithAccessibilityLabel:@"Back" error:nil]) {
+ [tester tapViewWithAccessibilityLabel:@"Back"];
+ }
}
- (void)startChatWith:(NSString *)user {
@@ -135,9 +137,8 @@
[self startChatWith:user];
[self sendMessage:user];
- [tester waitForViewWithAccessibilityLabel:@"Message status"
- value:@"not delivered"
- traits:UIAccessibilityTraitImage];
+ [tester waitForViewWithAccessibilityLabel:@"Delivery failed" traits:UIAccessibilityTraitImage];
+ [self dismissKeyboard];
[tester tapViewWithAccessibilityLabel:@"Edit" traits:UIAccessibilityTraitButton];
[tester waitForViewWithAccessibilityLabel:@"Checkbox" value:@"Deselected" traits:UIAccessibilityTraitButton];